agents keep their github token in /run, fetched on every start, not in the state dir
This commit is contained in:
parent
adc61c9043
commit
4bd02ea14d
4 changed files with 310 additions and 78 deletions
|
|
@ -32,7 +32,7 @@ or the token fetch.
|
|||
swarm-wide switch is the intended control.)
|
||||
|
||||
github.com only. The token **value** never touches nix — the agent writes it
|
||||
to `<state>/github-token` at runtime (see [Provisioning](#provisioning)).
|
||||
to a file under `/run` at runtime (see [Provisioning](#provisioning)).
|
||||
|
||||
## Provisioning
|
||||
|
||||
|
|
@ -44,13 +44,19 @@ no hive writes it. One token per agent: swarm-controller refuses to link
|
|||
another until you delete the stored one, and no route hands it back.
|
||||
|
||||
The agent's `hive-agent-github-token` unit reads that path under the
|
||||
agent's own store certificate and writes `<state>/github-token` (`0600`,
|
||||
owned by the agent), on boot and every two minutes, replacing the file only
|
||||
when the token changed. It needs a store identity
|
||||
agent's own store certificate and writes `/run/hive-agent-github-token/token`
|
||||
(`0400`, owned by the agent), on every start and every two minutes, replacing
|
||||
the file only when the token changed. It needs a store identity
|
||||
(`services.hyperhive.agent.bao.addr`); an agent without one gets no token.
|
||||
The unit never deletes the file: a `github-token` already in place stays
|
||||
when the store holds none or doesn't answer. Where the token lives and who
|
||||
reads it: [credentials-reference.md](../../4-implementation/swarm/credentials-reference.md).
|
||||
|
||||
`/run` starts empty on every start, so the unit fetches the token anew each
|
||||
time: an agent whose token you removed from the store has none after its next
|
||||
start. When the
|
||||
store doesn't answer at start, the agent boots and runs without a GitHub
|
||||
token (`gh` and `git push` run unauthenticated, the unit logs one warning),
|
||||
and the unit asks again until the store answers. Nothing reads the
|
||||
`<state>/github-token` file an earlier version kept, and nothing deletes it;
|
||||
it stays on disk, unused. Where the token lives and who reads it: [credentials-reference.md](../../4-implementation/swarm/credentials-reference.md).
|
||||
|
||||
## Security
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ When enabled, the container gets:
|
|||
Host-scoped, so it never touches the forge (`localhost:3000`) or any
|
||||
other remote.
|
||||
|
||||
Both scripts read the token from `<state>/github-token` **at invocation
|
||||
time**, so a PAT written (or rotated) mid-session takes effect immediately
|
||||
— no container rebuild or restart. Until the file exists, `gh` / `git push`
|
||||
Both scripts read the token from `/run/hive-agent-github-token/token`
|
||||
(`services.hyperhive.agent.github.tokenFile`) **at invocation
|
||||
time**, so a PAT fetched (or rotated) mid-session takes effect immediately
|
||||
— no container rebuild or restart. They never read the state dir. Until the file exists, `gh` / `git push`
|
||||
fail unauthenticated. The build bakes the token path into the scripts
|
||||
(rather than reading it from an env var), because claude's Bash tool runs in a
|
||||
minimal environment that wouldn't carry one.
|
||||
|
|
@ -42,12 +43,13 @@ rather than merely switched off. it's also why this isn't a cargo
|
|||
feature — a feature would unify across the workspace and cost every
|
||||
crate its build cache.
|
||||
|
||||
At runtime the poller needs the PAT above. No PAT, no polling: the unit
|
||||
At runtime the poller needs the PAT above, at the path in
|
||||
`HIVE_GITHUB_TOKEN_FILE` (the same `/run` file). No PAT, no polling: the unit
|
||||
logs why and exits 0, which is why it's `Restart = on-failure` and
|
||||
never `always` — a clean exit on a PAT-less agent must not become a
|
||||
restart loop. The poller waits about ten minutes for the PAT to appear
|
||||
before it gives up. A path unit (`hive-github-notify.path`) starts the poller
|
||||
again when `<state>/github-token` changes, so a PAT that lands later still
|
||||
again when the token file changes, so a PAT that lands later still
|
||||
enables polling. Once polling, it re-reads the file on every
|
||||
tick, so it picks up a rotated PAT on the next tick without a restart.
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ the rest of the cell says how.
|
|||
| `swarm/agents/<agent>/forge-token` | `swarm-controller`, at agent creation and every 5 minutes | the agent | ✅ when missing or no longer matching the forge | ✅ every 10 minutes |
|
||||
| `swarm/agents/<agent>/forge/<label>` | `swarm-controller`, when you link an external forge account in the swarm UI | the agent | ❌ your token; delete it and link the label again | ✅ every 2 minutes |
|
||||
| `swarm/agents/<agent>/gitlab/<label>` | `swarm-controller`, when you link a GitLab account through the API | the agent | ❌ your token; delete it and link the label again | ✅ every 2 minutes; a deleted account leaves the agent's `glab` configuration on the next run |
|
||||
| `swarm/agents/<agent>/github-token` | `swarm-controller`, when you link a GitHub account in the swarm UI | the agent | ❌ your token; delete it and link again | ✅ every 2 minutes |
|
||||
| `swarm/agents/<agent>/github-token` | `swarm-controller`, when you link a GitHub account in the swarm UI | the agent, which keeps it in `/run` only; the `<state>/github-token` copy of an earlier version is no longer read | ❌ your token; delete it and link again | ✅ every 2 minutes |
|
||||
| `swarm/agents/<agent>/backend-env` | `hive-agent-backend-env`, in the agent's container, from the agent's `backendEnvironmentFile` when the leaf holds nothing (field `env`, the file's exact text); or `swarm-controller`, when you set the API-key environment in the swarm UI | the agent | ❌ nothing replaces it without you; a save in the swarm UI overwrites it, including text an agent wrote into an empty leaf; the agent's file stays as it was | ❌ the file in `/run` refreshes every 2 minutes, and the harness and the subagent daemon load it at their next start |
|
||||
| `swarm/agents/<agent>/claude-credentials` | `swarm-claude-login`, when you log the agent in from its card; one version per login | the agent, while it waits for a login | ❌ log in again | ✅ every 30 seconds while waiting |
|
||||
| `swarm/hives/<hive>/forge/token` | `swarm-controller`, every 5 minutes | `swarm-controller` and the hive | ✅ when missing or no longer matching the forge | ✅ read on every forge call |
|
||||
|
|
|
|||
|
|
@ -952,10 +952,10 @@ a link dialog closes.
|
|||
- **link a github account** — `PUT /api/hives/{hive}/agents/{agent}/github-account`
|
||||
with a personal access token, stored at `swarm/agents/<agent>/github-token`.
|
||||
One token per agent. The agent's
|
||||
`hive-agent-github-token` unit fetches it into `<state>/github-token`,
|
||||
the file its `gh` wrapper, git credential helper and GitHub notification
|
||||
poller read. A `github-token` already in place stays when the store holds
|
||||
none. What the token needs and how the agent uses it:
|
||||
`hive-agent-github-token` unit fetches it into
|
||||
`/run/hive-agent-github-token/token` at every start, the file its `gh`
|
||||
wrapper, git credential helper and GitHub notification poller read. A token
|
||||
removed from the store stops working at the agent's next start. What the token needs and how the agent uses it:
|
||||
[GitHub accounts](../../2-handbook/external-accounts/github.md).
|
||||
- **set the API-key environment** — `PUT /api/hives/{hive}/agents/{agent}/backend-env`
|
||||
with the text of a systemd `EnvironmentFile` (`NAME=VALUE` lines, at most
|
||||
|
|
|
|||
Loading…
Reference in a new issue