Watch
0
0
Fork
You've already forked hyperhive
0

grant manage_root_agent by stored permission only, not by the name ruth

Permission::default_for and hive-sh4re's MANAGER_AGENT are gone: every
agent with no permissions key holds Permission::DEFAULT, ruth included.
The agent-name parameters that only fed default_for go with it
(permissions::effective, HiveCopy::before_read/after_read and their
callers).

swarm-controller seeds the grant ruth held by name: at start, a declared
ruth whose permissions are unset gets DEFAULT plus manage_root_agent
written into her key, once, logged. A set key is never touched. It is a
one-shot to delete once every swarm has passed it.

The swarm UI setup assistant opens the create form with
manage_root_agent checked, so a new ruth is created with the grant.
permissions_import no longer adds ruth to the import or splits her
default. Docs and help text no longer say ruth holds the grant by
default; swarmctl-cli.md regenerated.
This commit is contained in:
atlas 2026-10-16 23:10:05 +02:00 • committed by mara
commit 7b5400ecb8
26 changed files with 380 additions and 216 deletions

View file

@ -78,9 +78,9 @@ module docs for the exact call chain.
## Hard-coded manager behaviour
The **manager (`ruth`)** differs from other agents in naming/bootstrap,
its socket flavour and its default permissions; its prompt, tool
allow-list and state dirs work as for every other agent.
The **manager (`ruth`)** differs from other agents in naming/bootstrap
and its socket flavour; its permissions, prompt, tool allow-list and
state dirs work as for every other agent.
<!-- vale write-good.Passive = NO -->
@ -97,13 +97,13 @@ allow-list and state dirs work as for every other agent.
both flavours; matrix, bash and forge don't call it — their
notifications push a todo on the harness's in-agent socket (see
[`docs/turn-loop/mcp.md`](../turn-loop/mcp.md#waking-the-agent-from-inside-the-container)).
- **Storage/mounts** — the manager container gets
- **Storage/mounts** — the `manage_root_agent` permission, which the swarm
UI's setup assistant creates ruth with, gets a container
`/var/lib/hyperhive/agents` bind-mounted RW at `/agents` (so it can
manage any agent's state dir — config isn't authored there, since a
real config change is a PR from a clone), plus RO mounts for
`/applied` (diff against what's deployed) and `/meta` (system-wide
deploy log). That grant is the `manage_root_agent` permission: ruth
holds it by default, and any agent holding it gets the same mounts.
deploy log). Any agent holding it gets the same mounts.
The operator dashboard's `POST /api/meta-update` is the only path
that writes `flake.lock`.
- **Prompt** — identical for every container: `prompts/system.md`
@ -115,8 +115,8 @@ allow-list and state dirs work as for every other agent.
(`filter_role_blocks(SAMPLE, "manager")`).
- **Tool allow-list** — the MCP tools claude sees come from the agent's
permissions alone, the same mechanism for every agent
([`docs/turn-loop/mcp.md`](../turn-loop/mcp.md)). Ruth's default
permissions add only `manage_root_agent` (`Permission::default_for`).
([`docs/turn-loop/mcp.md`](../turn-loop/mcp.md)). Ruth's permissions
are the default plus `manage_root_agent`, stored for her like any grant.
- **State dirs** — _not_ special-cased: `HYPERHIVE_STATE_DIR` is
injected uniformly via `systemd.globalEnvironment` for every
container including the manager, so all token/state paths resolve

View file

@ -270,10 +270,13 @@ dirs.
⚠️ nspawn bakes bind flags at container start, so hive-c0re restarts
an agent, after its current turn, when its `manage_root_agent` changes.
The root agent holds the permission by default: an agent whose record
leaves `permissions` unset gets the default, which includes
`manage_root_agent` for `ruth` and for no other agent. Setting her
permissions without it revokes it.
No agent holds the permission by default: an agent whose record leaves
`permissions` unset gets the default, which doesn't include
`manage_root_agent`, whatever the agent's name. The swarm UI's setup
assistant creates ruth with it. For a ruth that predates that, whose
permissions were unset, swarm-controller writes the default plus
`manage_root_agent` into her key once at start, so she keeps her mounts;
it never touches a key that's already set.
Each proposed repo (`/agents/<n>/config/`) is pre-configured
with `applied` as a git remote pointing at
@ -331,8 +334,10 @@ Differences from sub-agents:
(vs `agent-base`).
- Web UI port via `lifecycle::agent_web_port("ruth")` — same
FNV-1a hash as every other agent (8100..8999 range).
- `set_nspawn_flags` adds two extra binds: `/var/lib/hyperhive/agents`
→ `/agents` (RW) so the root agent can edit per-agent proposed repos,
- The root agent holds `manage_root_agent` (the swarm UI's setup
assistant creates her with it), for which `set_nspawn_flags` adds two extra binds:
`/var/lib/hyperhive/agents` → `/agents` (RW) so the root agent can edit
per-agent proposed repos,
and `/var/lib/hyperhive/applied` → `/applied` (RO) so the root agent
can `git fetch` deployed/failed/denied tags from any agent's
authoritative applied repo (see "Root-agent view of applied" below).

View file

@ -408,7 +408,8 @@ Contents:
to live here; nothing reads or writes it now. An old copy in the meta repo
is harmless and you can delete it.
The root agent has the meta dir RO-mounted at `/meta/`.
An agent holding `manage_root_agent`, normally ruth, has the meta dir
RO-mounted at `/meta/`.
Outside the meta repo, `/var/lib/hyperhive/swarm-agent-permissions.json`
holds the permissions the swarm grants this hive's agents, as

View file

@ -93,8 +93,10 @@ SSO login asks for its forge password once, to link the two.
hive-c0re creates no agent at startup. You create ruth, the manager agent,
like any other: open the swarm UI start page and click the paperclip, which
opens the create form with `ruth` filled in. The form declares her, creates
her config repo and deploys her to the hive you pick.
opens the create form with `ruth` filled in and the `manage_root_agent`
permission checked: that permission mounts the other agents into her
container so she can recover them. The form declares her, creates her
config repo and deploys her to the hive you pick.
The swarm declares a new agent `paused`, so without a further step ruth runs
but drives no turns. Open `/agents` in the swarm UI and set her `up` from her

View file

@ -301,8 +301,8 @@ the agent's key in the `agent-permissions` KV bucket
writes. Set them with `swarmctl agent permissions get|set|clear <agent>`
(`/api/agents/{name}/permissions`), or on the swarm UI's create-agent screen
(`permissions` in `POST /api/agents`). A missing key or an unset field means
the default (`Permission::default_for`): `messaging`, `meta`, `inbox`,
`execution`, plus `manage_root_agent` for `ruth`. `"permissions": []` grants
the default (`Permission::DEFAULT`): `messaging`, `meta`, `inbox`,
`execution`, for every agent whatever its name. `"permissions": []` grants
none.
**How a change applies** —

View file

@ -207,7 +207,7 @@ Clear every field for an agent, so it goes back to its own values
Show or change the permissions the swarm grants an agent.
The agent applies its tool permissions at its next turn; the hive running it restarts it, after its current turn, when `manage_root_agent` changes. Unset leaves the agent on the default: `messaging`, `meta`, `inbox`, `execution`, plus `manage_root_agent` for `ruth`.
The agent applies its tool permissions at its next turn; the hive running it restarts it, after its current turn, when `manage_root_agent` changes. Unset leaves the agent on the default: `messaging`, `meta`, `inbox`, `execution`, whatever its name.
**Usage:** `swarmctl agent permissions <COMMAND>`