fix(#1021): error on unauthorized target (not silent ignore); allow child targeting without cap

This commit is contained in:
damocles 2026-06-01 21:26:42 +02:00
commit d35b7ab9b4
3 changed files with 44 additions and 38 deletions

View file

@ -625,10 +625,15 @@ fn auto_reminder_path(agent: &str) -> String {
}
/// Resolve the target agent name for `GetLooseEnds`, `CountPendingReminders`,
/// and `ReminderRollup` on the agent socket. Returns the caller's own name
/// when no target is specified or when the caller lacks `query_agent_state`.
/// Returns an error string when the caller requests `"*"` (hive-wide scans
/// are manager-only) or requests another agent without the capability.
/// and `ReminderRollup` on the agent socket. Rules:
///
/// - `None` → caller's own threads (always allowed).
/// - `Some(caller)` → same as `None`.
/// - `Some("<child>")` where child is a direct descendant of caller per
/// `topology.json` → allowed without any extra capability.
/// - `Some("<other>")` where other is not a child → requires the
/// `query_agent_state` capability; returns an error otherwise.
/// - `Some("*")` → always rejected (hive-wide scans are manager-only).
fn resolve_agent_state_target<'a>(caller: &'a str, target: Option<&'a str>) -> Result<&'a str, String> {
match target {
None => Ok(caller),
@ -640,12 +645,16 @@ fn resolve_agent_state_target<'a>(caller: &'a str, target: Option<&'a str>) -> R
if name == caller {
return Ok(caller);
}
// Direct children are visible to their parent without extra capability.
if crate::topology::children_of(caller).iter().any(|c| c == name) {
return Ok(name);
}
if crate::capabilities::has_cap(caller, hive_sh4re::Capability::QueryAgentState) {
Ok(name)
} else {
Err(format!(
"agent `{caller}` does not have the query_agent_state capability; \
agent field ignored grant the capability to query other agents"
"agent `{caller}` cannot query `{name}`: not a direct child and \
`query_agent_state` capability is not granted"
))
}
}