Watch
0
0
Fork
You've already forked hyperhive
0

agent capabilities live in a swarm KV record, set from swarmctl

An agent's capabilities move from the hive's meta repo
(`meta/capabilities.json`, injected as `HIVE_CAPABILITIES`) into the
`capabilities` field of its key in a new `agent-permissions` KV bucket,
which swarm-controller alone writes.

- swarm-queue-client: `agent_permissions` (bucket, key, `AgentPermissions`,
  direct-get read, the import subject and its wire types).
- swarm-controller: creates the bucket at start; `GET|PUT|DELETE
  /api/agents/{name}/permissions` (deny_unknown_fields and unknown
  capability ⇒ 422, duplicate ⇒ 400, agent must be declared by a hive);
  answers each hive's one-shot import, writing a key only where there is
  none and only for agents that hive's wanted state declares.
- swarmctl: `agent permissions get|set|clear`.
- swarm-nats-auth: a hive reads every key of the bucket and sends its
  import on its own subject; the controller subscribes to the imports and
  may answer them (`responses`).
- hive-c0re: reads each of its agents' keys every 30s into
  /var/lib/hyperhive/swarm-agent-permissions.json and restarts an agent,
  gracefully, when its capabilities change. Unset is the compiled-in
  default (ruth: manage_root_agent; everyone else: none). A failed read
  keeps the stored value. On first boot it seeds that file from
  meta/capabilities.json, sends the grants to the controller, and deletes
  the file once the controller answers.

Deleted: the capabilities.json reader/writer, `HIVE_CAPABILITIES` in the
rendered meta flake, ruth's capability seed, the capabilities half of the
permissions rebuild job (`PermPayload::Capabilities`/`Combined`), the
dashboard's capabilities table and `capabilities_changed` event, and the
now-unused `Capability::description`.

Part of #5170.
This commit is contained in:
atlas 2026-10-15 00:24:41 +02:00 • committed by mara
commit f862354e43
47 changed files with 1943 additions and 1146 deletions

View file

@ -334,35 +334,37 @@ that allows the underlying resource access.
| Capability | Effect |
|---|---|
| `manage_root_agent` | may manage *any* agent: bind-mounts every agent's state (rw) + config (ro) into the holder's container, plus `/applied` and `/meta` (ro). Takes effect on the holder's next container rebuild/restart |
| `manage_root_agent` | may manage *any* agent: bind-mounts every agent's state (rw) + config (ro) into the holder's container, plus `/applied` and `/meta` (ro). Takes effect when the holder's container restarts, which hive-c0re does itself on a change |
**Config storage** — per-agent capabilities live in
`/var/lib/hyperhive/meta/capabilities.json` alongside `tool-groups.json`.
Format: `{ "ruth": ["manage_root_agent"] }`.
An absent entry means "no extra capabilities." `render_flake` in `meta.rs`
reads this file and injects `HIVE_CAPABILITIES` (comma-separated
`snake_case` names) into each agent's systemd service env; absent entries emit
no env var so agents without capabilities don't trigger a spurious rebuild.
**Where they live** — in the swarm, not on the hive: the `capabilities` field
of the agent's key in the `agent-permissions` KV bucket
(`swarm-queue-client/src/agent_permissions.rs`), which swarm-controller alone
writes. Set them with `swarmctl agent permissions get|set|clear <agent>`
(`/api/agents/{name}/permissions`). Unset means the hive's default, which is a
constant in hive-c0re (`capabilities::default_for`): none, except `ruth`, who
gets `manage_root_agent`. `"capabilities": []` grants none.
**Setting capabilities** — the operator sets capabilities via the
C4P4B1L1T13S section in the dashboard's P3RM1SS10NS tab.
`hive-c0re::capabilities::set_caps(name, caps)` is the write path.
After a change `meta::sync_agents` commits the updated file; the next agent
rebuild picks up the new `HIVE_CAPABILITIES` env var.
**How a change applies** — every 30 seconds hive-c0re reads the key of each
agent it runs (`workers/swarm_permissions.rs`) and stores the result in
`/var/lib/hyperhive/swarm-agent-permissions.json`, outside the meta repo. nspawn
fixes the bind mounts at container start, so when an agent's capabilities
change hive-c0re restarts it after its current turn. A failed read keeps the
last stored value; it never falls back to the default.
**Runtime resolution** — at session start the harness reads `HIVE_CAPABILITIES`
and resolves each token to a `Capability` variant, logging and skipping
unrecognised ones. An absent or empty var means no extra capabilities.
**Moving off `meta/capabilities.json`** — on its first boot with this code a
hive copies the file's grants into the stored value, sends them to
swarm-controller once (written only for agents with no key, and only for
agents that hive's wanted state declares), and deletes the file from the meta
repo when the controller answers (`workers/permissions_import.rs`).
**Capability NOT configurable from `agent.nix`** — same reasoning as tool
groups: an agent that could grant its own capabilities via a config commit would
bypass the operator approval gate.
**Adding a new capability** — add a variant to `Capability` in
`hive-sh4re/src/permissions.rs` + an arm to `as_str`. Add it to `Capability::ALL`
(the source of truth for the permissions UI columns). Implement the access
check in the relevant handler (`hive-c0re/src/socket_server/mod.rs`,
`coordinator.rs`, or a handler under `hive-c0re/src/dashboard/`).
`hive-sh4re/src/permissions.rs` and to `Capability::ALL`. Implement the access
check where hive-c0re enforces it (today: `set_nspawn_flags` in
`hive-c0re/src/lifecycle/host_config.rs`).
## Async forms