From 2d29711df933e1cae6ba4d9ce0b34ca09bc25e74 Mon Sep 17 00:00:00 2001 From: iris Date: Mon, 26 Oct 2026 16:32:12 +0100 Subject: [PATCH] docs: split credentials.md into an overview and a per-secret reference The overview keeps the store invariant, the mTLS exception and the minter/reader/renewal contract. The table of every credential and the operating notes (forge token checks, re-creating agents, revoking a queue credential, store login retries) move unchanged to credentials-reference.md, and the links that asked where a credential lives point there. --- docs/README.md | 3 +- docs/integrations/github.md | 2 +- docs/swarm/README.md | 5 +- docs/swarm/builder.md | 2 +- docs/swarm/credentials-reference.md | 84 ++++++++++++++++++++++++++++ docs/swarm/credentials.md | 86 +++-------------------------- docs/swarm/ui.md | 2 +- 7 files changed, 101 insertions(+), 83 deletions(-) create mode 100644 docs/swarm/credentials-reference.md diff --git a/docs/README.md b/docs/README.md index cede24f9..18342c77 100644 --- a/docs/README.md +++ b/docs/README.md @@ -78,7 +78,8 @@ declarations. [`networking/snapshot-store.md`](networking/snapshot-store.md). - **Who mints each credential, who reads it, and how does it rotate — and where's that shape headed?** → [`swarm/credentials.md`](swarm/credentials.md) - (current state and target state); + (the overview) and [`swarm/credentials-reference.md`](swarm/credentials-reference.md) + (each credential, current state and target state); [`swarm/secrets.md`](swarm/secrets.md) for where each file lives today. - **How does the secret store come up, who writes its grants, how's it sealed?** → [`swarm/bao.md`](swarm/bao.md). diff --git a/docs/integrations/github.md b/docs/integrations/github.md index f973afb1..7495cb72 100644 --- a/docs/integrations/github.md +++ b/docs/integrations/github.md @@ -50,7 +50,7 @@ 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.md](../swarm/credentials.md). +reads it: [credentials-reference.md](../swarm/credentials-reference.md). ## Security diff --git a/docs/swarm/README.md b/docs/swarm/README.md index b9714262..88d9bcd4 100644 --- a/docs/swarm/README.md +++ b/docs/swarm/README.md @@ -43,7 +43,8 @@ grafana, the controller, authelia, …) → → [`sso.md`](sso.md) - **secrets** — every credential the swarm holds, who mints it and where it lives → [`secrets.md`](secrets.md) · the per-secret minter/reader/renewal - contract → [`credentials.md`](credentials.md) · how the store comes up, + contract → [`credentials.md`](credentials.md), per credential in + [`credentials-reference.md`](credentials-reference.md) · how the store comes up, who writes its grants and how it unseals → [`bao.md`](bao.md) - **swarm CA** — the store root every hive's gateway leaf chains to, and what to hand a peer. → [`ca.md`](ca.md) @@ -168,7 +169,7 @@ it's stored in the queue, not in the daemon. An agent connects to the queue as itself, with a credential `swarm-controller` mints for it when it creates the agent (`swarm/agents//queue` in the -secret store, see [`credentials.md`](credentials.md)). The harness reads it from +secret store, see [`credentials-reference.md`](credentials-reference.md)). The harness reads it from the store under the agent's own certificate before each connection attempt and holds it in memory only. The one thing to configure is where the queue is: diff --git a/docs/swarm/builder.md b/docs/swarm/builder.md index fddc36c2..c014a68f 100644 --- a/docs/swarm/builder.md +++ b/docs/swarm/builder.md @@ -190,7 +190,7 @@ status. The same `git` fetches a config's own inputs, so the builder registers the helper for the forge's URL only, and the helper answers only an `https` request for the forge's host: any other host gets nothing. The builder holds no write credential; swarm-controller writes the status with its own forge token. Details per path: -[`credentials.md`](credentials.md). +[`credentials-reference.md`](credentials-reference.md). ## Isolation diff --git a/docs/swarm/credentials-reference.md b/docs/swarm/credentials-reference.md new file mode 100644 index 00000000..f8fb1097 --- /dev/null +++ b/docs/swarm/credentials-reference.md @@ -0,0 +1,84 @@ +# Credentials: the per-secret reference + +Every credential in the swarm's secret store, in one table: who mints it, who +reads it, and whether it renews on its own. The overview and the rules a +credential follows are in [`credentials.md`](credentials.md); this page is +the detail, so it changes whenever someone adds a credential or moves its minting. +[`secrets.md`](secrets.md) maps the files that exist on disk today. + +In the table, **automatic re-mint** is something replacing the stored value +without an operator. **Automatic re-pull** is the reader picking up a replaced +value without a restart. ✅ means it happens today, ❌ means it doesn't, and +the rest of the cell says how. + + + +| store path | minter | reader | automatic re-mint | automatic re-pull | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `swarm/agents//matrix/main` | `swarm-controller`, at agent creation and every 5 minutes | the agent | ✅ when missing or rejected by the homeserver | ✅ the daemon restarts within 5 minutes of a rejection | +| `swarm/agents//matrix/` | `swarm-controller`, from a credential you hand it | the agent | must be stated | ✅ retried within 2 to 16 minutes after a rejection | +| `swarm/agents//matrix-recovery/` | `swarm-controller`, a random passphrase per account | the agent | ❌ never replaced: the account's key backup opens only with this passphrase | ❌ read when the account comes up | +| `swarm/controller/swarm-controller/matrix/appservice-token` | `swarm-matrix-ctl` in `hive-matrix`, once | `swarm-controller` | ❌ minted once | ✅ read every 5 minutes | +| `swarm/controller/swarm-controller/oidc/client` | authelia, first boot | `swarm-controller` | ❌ minted once; `swarm-secret-publish` republishes a re-mint | ✅ re-read when authelia refuses it | +| `swarm/controller/swarm-controller/forge/token` | the forge, once | `swarm-controller` | ❌ minted once; delete `/var/lib/forgejo/swarm-controller-token-name` in the forge container to mint a new one | ✅ re-read on a 401 | +| `swarm/controller/swarm-controller/grafana/token` | `swarm-bao-grafana-controller-token` on Grafana's host | `swarm-controller` | ✅ every 10 minutes, when Grafana refuses it or none is stored | ✅ re-read on a 401 | +| `swarm/agents//bao-mtls` | the store's agent PKI mount (`deploy.bao.agentPkiMountPath`), at agent creation | `hive-c0re`, then the agent | ✅ re-issued every 5 minutes once past half its 7-day validity | ✅ the agent re-reads every 10 minutes; it renews only while its current leaf is valid | +| `swarm/agents//queue` | `swarm-controller`, at agent creation | the agent; the queue, log and metrics auth services | ✅ re-minted at 45 days; skipped for `Destroyed` agents, whose path is deleted | ✅ read on every reconnect; an open connection keeps the old secret for up to an hour; the log and metrics stores honour a replaced secret for up to `deploy.victorialogs.authVerdictTtl` and `deploy.victoriametrics.agentAuthVerdictTtl` (60 s by default) | +| `swarm/agents//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//forge/