diff --git a/docs/integrations/forge.md b/docs/integrations/forge.md index 38586440..4d1ff43e 100644 --- a/docs/integrations/forge.md +++ b/docs/integrations/forge.md @@ -15,7 +15,7 @@ each agent on relevant activity. ## Token scopes -Two scope sets: +Three scope sets: **`AGENT_TOKEN_SCOPES`** (swarm-controller's `forge::agent_token`, pinned by a test). swarm-controller mints every agent token with it: @@ -40,6 +40,53 @@ hive-c0re only mints the token when the file at a token minted with admin scopes keeps them until an operator deletes that file and restarts hive-c0re. +**`HIVE_TOKEN_SCOPES`** (swarm-controller's `forge::hive_token`, pinned by a +test): `read:repository` alone, for each hive's read-only account (next +section). + +--- + +## How a hive reads the forge + +Each hive in swarm-controller's hive directory has its own forge account, +`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//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. + +The account name isn't reserved, so an agent may carry the name `hive-` too. +swarm-controller creates the hive's account with the email +`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 creation 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. Where the store holds none, +it falls back to the `core` token file, which only the host running the forge +container has. These reads go through it, and none of them needs a local +forge container: + +- fetching a merged config commit for a swarm deploy, and + `hivectl forge reconcile-config` +- reseeding a purged `applied` repo, and the meta-update cascade's + fast-forward of `applied/main` +- seeding `proposed` from `agent-configs/` on first deploy +- finding the PR that merged a config commit the hive refused to deploy +- cloning and pulling `/knowledge` + +Posting the refusal as a comment on that PR still needs the `core` token, so +only the forge host posts it. + +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 with the +core file, or not at all, until the controller's next pass. + --- ## Per-agent forge accounts diff --git a/docs/integrations/knowledge.md b/docs/integrations/knowledge.md index 36b41176..7ef42196 100644 --- a/docs/integrations/knowledge.md +++ b/docs/integrations/knowledge.md @@ -87,10 +87,12 @@ message only, no forced wake, and it carries the standard "this was a broadcast" hint. hive-c0re logs a diff or per-agent send failure without blocking the pull itself. -`knowledge::ensure_local_clone` creates (or refreshes) the local -clone once at startup. If the repo is brand new and -empty, `ensure_local_clone` seeds it with the default README -before returning. +On a hive with no local clone yet, `knowledge::pull()` takes the clone +instead of pulling, so every hive gets `/knowledge` from its first pull, +whether or not it runs the forge. It authenticates with the hive's forge +read token when it has one (see +[forge.md](forge.md#how-a-hive-reads-the-forge)) and clones the public +repo anonymously otherwise. ## State diff --git a/docs/swarm/credentials.md b/docs/swarm/credentials.md index 26b46724..18b004ae 100644 --- a/docs/swarm/credentials.md +++ b/docs/swarm/credentials.md @@ -67,6 +67,7 @@ of the cell says how. | `swarm/agents//forge/