refactor: harden internal daemon entrypoint and cleanup observations

Remove the internal daemon subcommand from the public CLI surface,
start the daemon via an internal env trigger, and ensure generated
completions/help never expose internal entrypoints.

Also finish the pending observation cleanups and docs updates,
including config/key deduplication, registry matching cleanup, and
remaining roadmap/project map staleness fixes.
This commit is contained in:
44r0n7
2026-04-18 11:55:18 -04:00
parent 274844b558
commit 795aa2f713
13 changed files with 131 additions and 129 deletions
+20 -8
View File
@@ -84,21 +84,37 @@ impl TvctlConfig {
/// Return one flattened config value by stable key.
pub fn get_value(&self, key: &str) -> Option<String> {
self.entries().remove(key)
match key {
"daemon.socket" => Some(self.daemon.socket.clone()),
"daemon.http_enabled" => Some(self.daemon.http_enabled.to_string()),
"daemon.http_port" => Some(self.daemon.http_port.to_string()),
"daemon.http_host" => Some(self.daemon.http_host.clone()),
"daemon.log_level" => Some(self.daemon.log_level.clone()),
"discovery.auto_discover" => Some(self.discovery.auto_discover.to_string()),
"discovery.interval_secs" => Some(self.discovery.interval_secs.to_string()),
"discovery.timeout_secs" => Some(self.discovery.timeout_secs.to_string()),
"devices.default" => Some(self.devices.default.clone()),
"remote.roku_key_mode" => Some(self.remote.roku_key_mode.clone()),
"remote.roku_press_duration_ms" => Some(self.remote.roku_press_duration_ms.to_string()),
"dev.enabled" => Some(self.dev.enabled.to_string()),
"dev.roku_username" => Some(self.dev.roku_username.clone()),
"dev.roku_password" => Some(self.dev.roku_password.clone()),
_ => None,
}
}
/// Set one flattened config value by stable key.
pub fn set_value(&mut self, key: &str, value: &str) -> anyhow::Result<()> {
match key {
"daemon.socket" => self.daemon.socket = value.to_string(),
"daemon.http_enabled" => self.daemon.http_enabled = parse_bool(key, value)?,
"daemon.http_enabled" => self.daemon.http_enabled = parse_value(key, value)?,
"daemon.http_port" => self.daemon.http_port = parse_value(key, value)?,
"daemon.http_host" => self.daemon.http_host = value.to_string(),
"daemon.log_level" => {
validate_log_level(value)?;
self.daemon.log_level = value.to_string();
}
"discovery.auto_discover" => self.discovery.auto_discover = parse_bool(key, value)?,
"discovery.auto_discover" => self.discovery.auto_discover = parse_value(key, value)?,
"discovery.interval_secs" => self.discovery.interval_secs = parse_value(key, value)?,
"discovery.timeout_secs" => self.discovery.timeout_secs = parse_value(key, value)?,
"devices.default" => self.devices.default = value.to_string(),
@@ -106,7 +122,7 @@ impl TvctlConfig {
"remote.roku_press_duration_ms" => {
self.remote.roku_press_duration_ms = parse_value(key, value)?
}
"dev.enabled" => self.dev.enabled = parse_bool(key, value)?,
"dev.enabled" => self.dev.enabled = parse_value(key, value)?,
"dev.roku_username" => self.dev.roku_username = value.to_string(),
"dev.roku_password" => self.dev.roku_password = value.to_string(),
other => bail!("unknown config key '{other}'"),
@@ -301,10 +317,6 @@ fn current_uid() -> u32 {
unsafe { libc::geteuid() }
}
fn parse_bool(key: &str, value: &str) -> anyhow::Result<bool> {
parse_value(key, value)
}
fn parse_value<T>(key: &str, value: &str) -> anyhow::Result<T>
where
T: std::str::FromStr,