Account minting, knowledge sync, the archetype refresh, the matrix appservice flow and the SSO secret delivery move to pages under 4-implementation/swarm. Each handbook page keeps what an operator does or sees, with a pointer.
88 lines
4.8 KiB
Markdown
88 lines
4.8 KiB
Markdown
# Forge accounts: hives and agents
|
|
|
|
How swarm-controller gives each hive a read-only forge account and each agent
|
|
its own user and token, and where each token lives. The operator's view of the
|
|
forge is [the forge page](../../2-handbook/swarm/forge.md).
|
|
|
|
## How a hive reads the forge
|
|
|
|
Each hive in swarm-controller's hive directory has its own forge account,
|
|
`hive-<hive>`. swarm-controller creates it, makes it a member of the `hives`
|
|
team in `agent-configs`, and mints one token named `swarm-hive` into the
|
|
swarm secret store at `swarm/hives/<hive>/forge/token`. The team has read
|
|
permission on `repo.code` and `repo.pulls` of every repo in the org,
|
|
including repos created later. A pass at start and every five minutes
|
|
creates what's missing and re-mints a token that's missing or no longer
|
|
matches the forge. A pass whose store or forge reads fail queues nothing, so
|
|
an outage never rotates every hive's token.
|
|
|
|
swarm-controller refuses to create an agent whose name starts with `hive-`:
|
|
these accounts own that prefix. An agent that already had such a
|
|
name keeps it, so the accounts are also told apart by email. swarm-controller
|
|
creates the hive's account with the email `hive-<hive>@hives.hyperhive.local`
|
|
and refuses an account by that name with any other email: it never adds an
|
|
agent's account to the team or mints a token for it. An agent's own forge
|
|
account setup refuses the hive's account the same way.
|
|
|
|
hive-c0re reads the token with `forge::reader_token()`, under the hive's own
|
|
store certificate, every time it reads the forge. A hive whose store holds
|
|
none reads nothing. These reads go through it, and none of them needs a local
|
|
forge container:
|
|
|
|
- cloning and pulling `/knowledge`
|
|
|
|
The hive builds nothing, so no nix process reads the forge as the hive's
|
|
account. hive-c0re hands the token to each `git` command it runs
|
|
(`http.extraHeader`) and keeps no copy on disk. A hive whose store holds no token
|
|
reads nothing private from the forge. This also holds on a hive with no forge
|
|
container.
|
|
|
|
Roll a change to any of this out store host first (its granter writes the
|
|
controller's grant on `swarm/hives/+/forge/token`), then the controller host,
|
|
then the hives. A hive that starts before its token exists reads nothing, and
|
|
builds nothing, until the controller's next pass.
|
|
|
|
## Per-agent forge accounts
|
|
|
|
Each agent gets its own Forgejo user and access token. swarm-controller
|
|
creates the user when it creates the agent, and mints one token named
|
|
`swarm-agent` with the admin API into the swarm secret store at
|
|
`swarm/agents/<agent>/forge-token`. A pass at start and every five minutes
|
|
covers every agent with a store identity: it creates a missing forge user and
|
|
re-mints any token that's missing or no longer matches the forge;
|
|
a rotation deletes the old `swarm-agent` token first, so each agent holds at
|
|
most one. The agent fetches the token under its own store certificate into
|
|
`/run/hive-agent-forge-token/token` (`nix/agent-modules/forge-token.nix`),
|
|
and `hive-forge`, the git credential helper, the `forge_notify` poller and
|
|
the avatar sync read it from there, falling back to `<state>/forge-token`,
|
|
the file hive-c0re wrote before. hive-c0re no longer creates agent users or
|
|
mints agent tokens. swarm-controller deletes the `hyperhive-<unix-seconds>`
|
|
tokens it left behind, for each agent whose current `swarm-agent` token is
|
|
live; tokens of other names are never touched.
|
|
|
|
Two things live in the `agent-configs` Forgejo organization:
|
|
|
|
- A config repo per agent (`agent-configs/<name>`). The
|
|
agent is a **write collaborator on its own** repo — it can push
|
|
config-change branches and open config PRs — but `main` is
|
|
branch-protected by swarm-controller: the merge and approval
|
|
allowlists are the `operators` team, and the agent can neither push
|
|
`main` directly nor self-merge. An operator's merge in the Forgejo UI
|
|
deploys the merged commit (see
|
|
[config-changes.md § Config changes](../../2-handbook/agents/config-changes.md#config-changes)).
|
|
hive-c0re pushes nothing to this org and reads nothing from it.
|
|
Repos stay private, so an agent can't read another
|
|
agent's config. The agent's **persistent meta flake input** is this repo's `main` head,
|
|
pinned by sha in `internal/meta` (`agent-<n>.url =
|
|
git+<forge>/agent-configs/<n>.git?rev=<sha>`; see
|
|
[config-changes.md § Meta flake](../../2-handbook/agents/config-changes.md#meta-flake)).
|
|
|
|
The `hive-forge` CLI (separate workspace crate, see
|
|
[`README.md`](../../README.md) file map) wraps the Forgejo REST API
|
|
with the per-agent token; agents call it for issue / PR / comment
|
|
ops as if it were a peer. All REST calls across the workspace
|
|
(`hive-forge` verbs, hive-c0re provisioning, this poller) go through
|
|
the typed `forgejo-api` crate; only non-`/api/v1` web-router routes
|
|
(attachment / artifact downloads, log streaming) and the poller's
|
|
enrichment fetches of server-provided subject URLs stay on raw
|
|
reqwest.
|