commit f8f2c6c96506ce573a7003810495c3201089e23b
parent 3d10d708a66ca2eec9b7cb881289d17dae5e913c
Author: triesap <tyson@radroots.org>
Date: Mon, 27 Apr 2026 06:08:29 +0000
cli: repair public global flags
- remove deferred target parser globals
- carry account-id into the output actor
- drop signer-session-id from public write context
- extend target cli coverage for rejected flags
Diffstat:
7 files changed, 51 insertions(+), 50 deletions(-)
diff --git a/src/operation_adapter.rs b/src/operation_adapter.rs
@@ -7,8 +7,8 @@ use serde_json::{Map, Value};
use crate::operation_registry::{OPERATION_REGISTRY, OperationSpec, get_operation};
use crate::output_contract::{
- CliExitCode, EnvelopeContext, NextAction, OUTPUT_SCHEMA_VERSION, OutputEnvelope, OutputError,
- OutputWarning,
+ CliExitCode, EnvelopeActor, EnvelopeContext, NextAction, OUTPUT_SCHEMA_VERSION, OutputEnvelope,
+ OutputError, OutputWarning,
};
use crate::target_cli::{TargetCliArgs, TargetOutputFormat};
@@ -64,9 +64,6 @@ impl Default for OperationInputMode {
pub struct OperationContext {
pub output_format: OperationOutputFormat,
pub account_id: Option<String>,
- pub farm_id: Option<String>,
- pub profile: Option<String>,
- pub signer_session_id: Option<String>,
pub relays: Vec<String>,
pub network_mode: OperationNetworkMode,
pub dry_run: bool,
@@ -85,9 +82,6 @@ impl OperationContext {
Self {
output_format: OperationOutputFormat::from(args.format),
account_id: args.account_id.clone(),
- farm_id: args.farm_id.clone(),
- profile: args.profile.clone(),
- signer_session_id: args.signer_session_id.clone(),
relays: args.relay.clone(),
network_mode: if args.offline {
OperationNetworkMode::Offline
@@ -116,6 +110,10 @@ impl OperationContext {
let mut context = EnvelopeContext::new(request_id, self.dry_run);
context.correlation_id = self.correlation_id.clone();
context.idempotency_key = self.idempotency_key.clone();
+ context.actor = self.account_id.as_ref().map(|account_id| EnvelopeActor {
+ account_id: account_id.clone(),
+ role: "account".to_owned(),
+ });
context
}
}
@@ -771,12 +769,6 @@ mod tests {
"json",
"--account-id",
"acct_test",
- "--farm-id",
- "farm_test",
- "--profile",
- "repo_local",
- "--signer-session-id",
- "sess_test",
"--relay",
"wss://relay.one",
"--online",
@@ -803,9 +795,6 @@ mod tests {
assert_eq!(context.output_format, OperationOutputFormat::Json);
assert_eq!(context.account_id.as_deref(), Some("acct_test"));
- assert_eq!(context.farm_id.as_deref(), Some("farm_test"));
- assert_eq!(context.profile.as_deref(), Some("repo_local"));
- assert_eq!(context.signer_session_id.as_deref(), Some("sess_test"));
assert_eq!(context.relays, vec!["wss://relay.one".to_owned()]);
assert_eq!(context.network_mode, OperationNetworkMode::Online);
assert!(context.dry_run);
@@ -817,6 +806,11 @@ mod tests {
assert!(context.verbose);
assert!(context.trace);
assert!(!context.color);
+
+ let envelope_context = context.envelope_context("req_test");
+ let actor = envelope_context.actor.expect("account actor");
+ assert_eq!(actor.account_id, "acct_test");
+ assert_eq!(actor.role, "account");
}
#[test]
diff --git a/src/operation_farm.rs b/src/operation_farm.rs
@@ -140,11 +140,7 @@ impl OperationService<FarmPublishRequest> for FarmOperationService<'_> {
.idempotency_key
.clone()
.or_else(|| string_input(&request, "idempotency_key")),
- signer_session_id: request
- .context
- .signer_session_id
- .clone()
- .or_else(|| string_input(&request, "signer_session_id")),
+ signer_session_id: string_input(&request, "signer_session_id"),
print_job: bool_input(&request, "print_job").unwrap_or(false),
print_event: bool_input(&request, "print_event").unwrap_or(false),
};
diff --git a/src/operation_listing.rs b/src/operation_listing.rs
@@ -176,11 +176,7 @@ where
.idempotency_key
.clone()
.or_else(|| string_input(request, "idempotency_key")),
- signer_session_id: request
- .context
- .signer_session_id
- .clone()
- .or_else(|| string_input(request, "signer_session_id")),
+ signer_session_id: string_input(request, "signer_session_id"),
print_job: bool_input(request, "print_job").unwrap_or(false),
print_event: bool_input(request, "print_event").unwrap_or(false),
})
@@ -198,7 +194,7 @@ where
"action": action,
"file": optional_path(request, "file").map(|path| path.display().to_string()),
"idempotency_key": request.context.idempotency_key,
- "signer_session_id": request.context.signer_session_id,
+ "signer_session_id": string_input(request, "signer_session_id"),
}))
}
diff --git a/src/operation_order.rs b/src/operation_order.rs
@@ -46,11 +46,7 @@ impl OperationService<OrderSubmitRequest> for OrderOperationService<'_> {
.idempotency_key
.clone()
.or_else(|| string_input(&request, "idempotency_key")),
- signer_session_id: request
- .context
- .signer_session_id
- .clone()
- .or_else(|| string_input(&request, "signer_session_id")),
+ signer_session_id: string_input(&request, "signer_session_id"),
};
let mut config = self.config.clone();
if request.context.dry_run {
diff --git a/src/runtime/daemon.rs b/src/runtime/daemon.rs
@@ -1078,10 +1078,10 @@ pub fn resolve_signer_session_id(
match matches.len() {
1 => Ok(matches.pop().expect("exactly one signer session")),
0 => Err(DaemonRpcError::Unconfigured(format!(
- "no authorized signer session matched {actor_role} pubkey `{actor_pubkey}` for sign_event:{event_kind}; connect a signer session or pass --signer-session-id"
+ "no authorized signer session matched {actor_role} pubkey `{actor_pubkey}` for sign_event:{event_kind}; configure exactly one signer session"
))),
_ => Err(DaemonRpcError::Unconfigured(format!(
- "multiple authorized signer sessions matched {actor_role} pubkey `{actor_pubkey}` for sign_event:{event_kind}; pass --signer-session-id"
+ "multiple authorized signer sessions matched {actor_role} pubkey `{actor_pubkey}` for sign_event:{event_kind}; configure exactly one signer session"
))),
}
}
diff --git a/src/target_cli.rs b/src/target_cli.rs
@@ -18,12 +18,6 @@ pub struct TargetCliArgs {
pub format: TargetOutputFormat,
#[arg(long = "account-id", global = true)]
pub account_id: Option<String>,
- #[arg(long = "farm-id", global = true)]
- pub farm_id: Option<String>,
- #[arg(long = "profile", global = true)]
- pub profile: Option<String>,
- #[arg(long = "signer-session-id", global = true)]
- pub signer_session_id: Option<String>,
#[arg(long = "relay", global = true)]
pub relay: Vec<String>,
#[arg(long = "offline", global = true, action = ArgAction::SetTrue, conflicts_with = "online")]
@@ -791,12 +785,6 @@ mod tests {
"ndjson",
"--account-id",
"acct_test",
- "--farm-id",
- "farm_test",
- "--profile",
- "repo_local",
- "--signer-session-id",
- "sess_test",
"--relay",
"wss://relay.one",
"--relay",
@@ -819,9 +807,6 @@ mod tests {
assert_eq!(parsed.format, TargetOutputFormat::Ndjson);
assert_eq!(parsed.account_id.as_deref(), Some("acct_test"));
- assert_eq!(parsed.farm_id.as_deref(), Some("farm_test"));
- assert_eq!(parsed.profile.as_deref(), Some("repo_local"));
- assert_eq!(parsed.signer_session_id.as_deref(), Some("sess_test"));
assert_eq!(
parsed.relay,
vec!["wss://relay.one".to_owned(), "wss://relay.two".to_owned()]
@@ -846,6 +831,15 @@ mod tests {
vec!["radroots", "--yes", "config", "get"],
vec!["radroots", "--non-interactive", "config", "get"],
vec!["radroots", "--signer", "myc", "config", "get"],
+ vec!["radroots", "--farm-id", "farm_test", "config", "get"],
+ vec!["radroots", "--profile", "repo_local", "config", "get"],
+ vec![
+ "radroots",
+ "--signer-session-id",
+ "sess_test",
+ "config",
+ "get",
+ ],
];
for args in rejected {
diff --git a/tests/target_cli.rs b/tests/target_cli.rs
@@ -67,6 +67,9 @@ fn removed_global_flags_are_rejected_publicly() {
["--yes", "workspace", "get"].as_slice(),
["--non-interactive", "workspace", "get"].as_slice(),
["--signer", "myc", "workspace", "get"].as_slice(),
+ ["--farm-id", "farm_test", "workspace", "get"].as_slice(),
+ ["--profile", "repo_local", "workspace", "get"].as_slice(),
+ ["--signer-session-id", "session_test", "workspace", "get"].as_slice(),
] {
let output = radroots().args(args).output().expect("run removed flag");
@@ -94,6 +97,28 @@ fn removed_command_families_are_rejected_publicly() {
}
#[test]
+fn account_id_global_populates_envelope_actor() {
+ let output = radroots()
+ .args([
+ "--format",
+ "json",
+ "--account-id",
+ "acct_test",
+ "workspace",
+ "get",
+ ])
+ .output()
+ .expect("run workspace get");
+
+ assert!(output.status.success());
+ let value: Value = serde_json::from_slice(&output.stdout).expect("json envelope");
+
+ assert_eq!(value["operation_id"], "workspace.get");
+ assert_eq!(value["actor"]["account_id"], "acct_test");
+ assert_eq!(value["actor"]["role"], "account");
+}
+
+#[test]
fn target_command_outputs_standard_json_envelope() {
let output = radroots()
.args(["--format", "json", "workspace", "get"])