docs: fix genuine passive-voice hits in docs/swarm

Read all 94 write-good.Passive hits across docs/swarm/ (ca.md,
README.md, secrets.md, services.md, sso.md, ui.md) in context. 44 are
genuine catches with a nameable, usually already-established actor
(swarm-controller, authelia, swarmctl, the controller, the gateway,
this module, hyperhive itself, or 'the operator' for manual actions) —
rewritten to active. 50 are legitimate passives or false catches, left
alone: predicate-adjective state descriptions (is expected/misconfigured/
broken), negative-capability idioms (no X is needed/placed, can't be
Yed/listed/fetched), config-state conditionals (whenever/when X is
enabled/configured/set), requirement-list labels (is required),
'is tracked as' idiom, backward-looking changelog facts with no actor
(was removed/verified/introduced), ambiguous-actor statements left
conservatively alone (agents are created and destroyed — could be
hive-c0re or swarm-controller, doc doesn't say), and a couple of
deliberately-parallel idiom pairs.

Several sibling-inconsistency fixes: a passive clause sitting next to
an already-active sibling describing the same fact/mechanism (ca.md's
two-bullet consumer list, README's 4-item WireGuard-mesh bullet list,
README's controller-registers-hooks paragraph, sso.md's followed-a-302
sentence).

Verified via vale on the whole directory, diffed against main's exact
baseline (not just the Passive count): write-good.Passive 94 -> 50
exactly, every other category unchanged (1 pre-existing
Microsoft.Contractions error at services... at secrets.md:182,
8 TooWordy, 1 Microsoft.We, 1 Microsoft.FirstPerson — same counts,
same locations).
This commit is contained in:
iris 2026-09-08 13:37:57 +02:00 committed by mara
commit fab2a0dedc
6 changed files with 79 additions and 78 deletions

View file

@ -8,7 +8,7 @@ Two rules run through all of it.
**Private key material and access tokens are paths, never values.** Every option
carrying one takes a file path (`*File`), because a literal written into a nix
expression is rendered into the nix store — world-readable and permanent. No
expression ends up in the nix store — world-readable and permanent. No
option in this tree accepts one inline, and adding one would be a leak rather
than a convenience.
@ -27,7 +27,7 @@ container that starts after it.
## Topologies, by who places secrets
Every row below is read against one of these. This is a different cut
Read every row below against one of these. This is a different cut
from the [deployment shapes](services.md#deployment-shapes) --- those
say _where services run_, these say _who is responsible for a secret
file being there_ --- the two lists don't line up one-to-one, and
@ -58,7 +58,7 @@ neither is a renaming of the other.
| the secret store's own contents | openbao, on first `bao operator init`**an operator action, not a unit** | inside the `swarm-bao` container, at its own `/var/lib/openbao`, kept across rebuilds by `ephemeral = false`. ⚠️ **Not a host path**: `nixos-container destroy swarm-bao` takes the raft data with it, so back up the container's tree, not `/var/lib/`. Only the store's TLS material (`/var/lib/swarm-bao-tls`) and its PKCS11 token (`/var/lib/swarm-bao-token`) are host-level | n/a — there is one store; a hive elsewhere is a _client_ of it and holds none of this |
| the secret store's unseal material | the HSM/TPM under `deploy.bao.seal = "pkcs11"`; openbao itself under `"shamir"` | in the token; or held by whoever ran `bao operator init`, which is what `"shamir"` means and why it's stated rather than inferred | n/a — only the host running the store seals anything |
The three keys authelia mints for itself are generated in-container precisely
Authelia mints the three keys for itself, in-container, precisely
because nothing outside that container ever reads them. **That's the test worth
applying to any secret added here** — and the client secret's plaintext half is
the one row that fails it, which is the entire reason a delivery step exists.
@ -71,8 +71,8 @@ an all-local swarm it reads authelia's file where it lies and no second copy is
made. On any other topology it's an ordinary "operator provides the file"
case — see `services.hyperhive.otel.clientSecretFile`.
The **swarm's** collector does need one. It runs in a container, so its copy is
placed by `swarm-otel-oidc-secret.service` and lands at
The **swarm's** collector does need one. It runs in a container, so
`swarm-otel-oidc-secret.service` places its copy, landing at
`/var/lib/swarm-otel-oidc/<client-id>.secret` — the same shape as the forge and
homeserver rows below, and for the same reason: the container that mints the
secret isn't the container that reads it.
@ -120,7 +120,7 @@ refuses every client rather than degrading — and a refusal reaches the client
a timeout, so the symptom is every consumer hanging with nothing logged.
One consequence of the generated path worth knowing before you debug it: with
`autoGenerateCallout` set, the queue's config is assembled at boot rather than at
`autoGenerateCallout` set, the queue assembles its config at boot rather than at
build time, so a malformed one surfaces when the container starts instead of
when the system builds. The server names the offending file and refuses to run.