Watch
0
0
Fork
You've already forked hyperhive
0

swarm UI: show the accounts linked to each agent

GET /api/hives/{hive}/agents/{agent}/linked-accounts returns one row per
account linked to the agent, as kind, name and host: each matrix account
under swarm/agents/<agent>/matrix (with its homeserver, and the agent's own
`main` marked reserved), each forge label under swarm/agents/<agent>/forge
(with its url), and github when swarm/agents/<agent>/github-token exists
(host github.com, which is not stored). No credential field is in the
response type.

Listing those two directories needs a new controller grant: `list` on
secret/metadata/swarm/agents/+/matrix and .../+/forge only, pinned in
bao-grants.nix as the only metadata stanzas under agents/ beside the queue
revocation. Checked against a dev OpenBao 2.6.3: the grant lists those two
directories and is refused on agents/, agents/<agent>/, and a leaf.

The swarm UI agent detail panel shows all rows under "accounts"; the table
view's matrix column shows the matrix rows. The link badges stay.

Refs #4855
This commit is contained in:
atlas 2026-10-02 20:02:03 +02:00
commit 3380c1915f
13 changed files with 577 additions and 30 deletions

View file

@ -400,6 +400,14 @@ let
capabilities = ["delete"]
}
path "${credentialMountPath}/metadata/swarm/agents/+/matrix" {
capabilities = ["list"]
}
path "${credentialMountPath}/metadata/swarm/agents/+/forge" {
capabilities = ["list"]
}
path "${credentialMountPath}/data/swarm/hives/+/matrix/sender-token" {
capabilities = ["create", "read", "update"]
}

View file

@ -1195,6 +1195,23 @@ let
&& !(lib.hasInfix "secret/metadata/swarm/agents/*" s)
&& !(lib.hasInfix "secret/metadata/*" s);
}
{
# `linked_accounts` names an agent's matrix accounts and forge labels by
# listing their two directories. A LIST matches the directory path
# itself, so each stanza reaches that one directory: not the agent's
# other keys, not `agents/` itself, not anything below. Pinned as whole
# stanzas, and as the only metadata stanzas under `agents/` beside the
# queue revocation, so a widened path or an added capability fails.
name = "the controller may list each agent's matrix and forge accounts, and nothing else under agents";
ok =
let
s = baoGrantHere.systemd.services.swarm-bao-controller-policy.script;
stanzas = lib.length (lib.splitString "path \"secret/metadata/swarm/agents/" s) - 1;
in
lib.hasInfix "path \"secret/metadata/swarm/agents/+/matrix\" {\n capabilities = [\"list\"]\n}" s
&& lib.hasInfix "path \"secret/metadata/swarm/agents/+/forge\" {\n capabilities = [\"list\"]\n}" s
&& stanzas == 3;
}
{
# The swarm appservice token is a homeserver-admin credential. The
# controller mints agents' accounts with it and has no business replacing