From 0e7aa74d008a8cca39f151c0bad8fbde85da8166 Mon Sep 17 00:00:00 2001 From: atlas Date: Thu, 15 Oct 2026 15:10:25 +0200 Subject: [PATCH] agent permissions: drop the test-only direct_get_subject; the failed-creation test names the refusing step --- swarm-controller/src/main.rs | 15 +++++++++++++-- swarm-nats-auth/src/policy.rs | 5 ++++- swarm-queue-client/src/agent_permissions.rs | 14 ++------------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/swarm-controller/src/main.rs b/swarm-controller/src/main.rs index 78f1ed08..a3fa16d2 100644 --- a/swarm-controller/src/main.rs +++ b/swarm-controller/src/main.rs @@ -4044,7 +4044,7 @@ mod tests { /// Through the real handler: when the inference store fails after the /// permissions are stored, the creation is refused and the permissions go /// back to what they were, the earlier value or no key. The inference - /// bucket refuses any value, as above. + /// bucket refuses any value, as above, and the refusal is that bucket's. #[tokio::test] async fn a_failed_creation_leaves_no_permissions_behind() { let nats = crate::test_nats::TestNats::start(); @@ -4073,9 +4073,20 @@ mod tests { "inference":{{"model":"opus"}}}}"# )) .expect("body parses"); - super::create_agent(axum::extract::State(state.clone()), axum::Json(req)) + let err = super::create_agent(axum::extract::State(state.clone()), axum::Json(req)) .await .expect_err("the inference write must fail"); + assert_eq!( + err.status, + Some(axum::http::StatusCode::INTERNAL_SERVER_ERROR), + "{agent}: {err:?}" + ); + assert!( + err.detail + .as_deref() + .is_some_and(|d| d.contains("message size exceeds maximum allowed")), + "{agent}: refused by the inference bucket, not an earlier check: {err:?}" + ); } let bucket = swarm_queue_client::agent_permissions::open_or_create(&client) .await diff --git a/swarm-nats-auth/src/policy.rs b/swarm-nats-auth/src/policy.rs index 5323c8f1..8c73f618 100644 --- a/swarm-nats-auth/src/policy.rs +++ b/swarm-nats-auth/src/policy.rs @@ -856,8 +856,11 @@ mod tests { /// no other, and writes none. #[test] fn a_hive_reads_every_agents_permissions_and_an_agent_only_its_own() { - use swarm_queue_client::agent_permissions::{STREAM, direct_get_subject, key_subject}; + use swarm_queue_client::agent_permissions::{STREAM, key_subject}; + let direct_get_subject = |agent: &str| { + format!("$JS.API.DIRECT.GET.KV_agent-permissions.$KV.agent-permissions.{agent}") + }; let p = policy() .with_agent_token_subjects(vec![ "$JS.API.DIRECT.GET.KV_agent-permissions.$KV.agent-permissions.{agent}".to_owned(), diff --git a/swarm-queue-client/src/agent_permissions.rs b/swarm-queue-client/src/agent_permissions.rs index 34cce1d0..9dd80ca8 100644 --- a/swarm-queue-client/src/agent_permissions.rs +++ b/swarm-queue-client/src/agent_permissions.rs @@ -11,8 +11,8 @@ //! covers every key of this bucket, read-only, for the reason //! [`crate::agent_limits`] gives. The agent itself (its harness and subagent //! daemon) applies the tool permissions; its grant covers only its own key. -//! Both read with one `DIRECT.GET` of -//! [`crate::agent_permissions::direct_get_subject`]. +//! Both read with one `DIRECT.GET` on the agent's key +//! ([`crate::agent_permissions::key_subject`]). //! //! Keyed by the agent alone, like [`crate::agent_limits`]: an agent can move //! between hives, and its permissions go with it. @@ -33,12 +33,6 @@ pub fn key_subject(agent: &str) -> String { format!("$KV.{BUCKET}.{agent}") } -/// The request subject that reads `agent`'s current entry. -#[must_use] -pub fn direct_get_subject(agent: &str) -> String { - format!("$JS.API.DIRECT.GET.{STREAM}.{}", key_subject(agent)) -} - const IMPORT_SUBJECT_PREFIX: &str = "$SWARM.permissions-import"; /// The subject `hive` sends its import on. One per hive, so the hive's grant @@ -264,10 +258,6 @@ mod tests { fn names_match_the_queue_grant() { assert_eq!(STREAM, format!("KV_{BUCKET}")); assert_eq!(key_subject("iris"), "$KV.agent-permissions.iris"); - assert_eq!( - direct_get_subject("iris"), - "$JS.API.DIRECT.GET.KV_agent-permissions.$KV.agent-permissions.iris" - ); assert_eq!(import_subject("pr1ma"), "$SWARM.permissions-import.pr1ma"); assert_eq!(import_subject_wildcard(), "$SWARM.permissions-import.*"); }