swarm: let every hive read every agent's credential, and say so

A hive reads its agents' credentials with its own certificate, and nothing
said which paths that certificate may read, so the read half of a delivery
answered 403.

The grant is wide on purpose. An agent's path does not name the hive
hosting it -- agents move -- so a per-hive grant has to be an enumeration
the controller re-emits whenever the roster changes, and an enumeration
that can drift or land out of order advertises a boundary it does not
hold. A wide grant that says what it is beats a narrow one that only looks
narrow. mara's call, on the PR: rather a too-lax scope than one that
pretends to be strict.

What that buys, beyond honesty: the document is identical for every hive
and depends on nothing, so it is written once at startup beside the rest of
a hive's provisioning instead of on every declaration. No derived state, no
re-emission, and the ordering hazard that came with one stops existing.

What still holds is read-only. A hive cannot write an agent's credential,
so it cannot hand itself an agent's identity, and the grant reaches nothing
in the store outside the agent-credential prefix.

The fact is documented where someone meets the boundary rather than only in
this message, and the two ways to narrow it later -- scope per hive, or
give agents their own store identity -- are tracked.
This commit is contained in:
atlas 2026-09-09 17:41:31 +02:00 committed by mara
commit 3752482524
5 changed files with 119 additions and 306 deletions

View file

@ -45,6 +45,28 @@ matrix **identities** — the public handles (`name`, `user_id` `@user:server`,
peers can find and address one another on a shared matrix instance. Only the
public handle crosses that boundary; the token never does.
### The swarm secret store is not a boundary between hives
A hive reads its agents' credentials out of the swarm's secret store with its
own certificate. **Every hive's policy grants read on every agent's
credentials**, not only on the agents it hosts — so a compromised hive can read
the matrix token of an agent running on a different hive.
That is deliberate and it is the interim state, not the intent. An agent's
credential path does not name the hive hosting it (agents move between hives),
so a per-hive grant has to be an enumeration the controller re-emits whenever
the roster changes — and an enumeration that can drift or land out of order
advertises a boundary it does not actually hold. A wide grant that says what it
is beats a narrow one that only looks narrow.
What still holds: the grant is **read-only** (a hive cannot write an agent's
credential, so it cannot hand itself an agent's identity), and it is scoped to
the agent-credential prefix — nothing else in the store is reachable with it.
Narrowing it is tracked in **#4137**, with the two candidate directions: scope
the grant per hive (and pay for the re-emission), or give each agent container
its own store identity so credentials never pass through a hive at all.
### Threat model: prompt injection → confused deputy
The realistic adversary **never needs to breach the container**. They supply