docs: suppress reviewed write-good.Passive false positives
133 hits across 38 files, all previously classified during #4548's sweep and deliberately left un-rewritten (predicate-adjective state/necessity description, design-intent idiom, structural/type-description idiom, no-single-actor topology claim, parallel-triple exception, vale substring-match artifact — see hyperhive#4548's per-PR bodies for the per-hit reasoning). Wraps each one in a scoped <!-- vale write-good.Passive = NO/YES --> pair (the supported mechanism — TokenIgnores has a known offset-drift bug) rather than a blanket per-file or per-rule silence, so a *new* passive-voice hit anywhere in these files still fails once the rule gates CI (next commit). Table/list false positives (docs/swarm/credentials.md's renewal-table cells) wrap the whole block, not each cell. Part of #4546.
This commit is contained in:
parent
7abb16e6d5
commit
04e27c4fb6
38 changed files with 368 additions and 71 deletions
|
|
@ -40,6 +40,8 @@ services.hyperhive = {
|
|||
};
|
||||
```
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
`swarm.domain` and `hiveName` are **required** whenever hyperhive is
|
||||
enabled; eval fails with a hint naming each. Neither defaults,
|
||||
because a guessed value here is a wrong hostname that evaluates cleanly
|
||||
|
|
@ -47,7 +49,9 @@ and deploys — an eval failure asking the operator to write the address
|
|||
down is the cheaper outcome. **Upgrading past this release means setting
|
||||
both once.**
|
||||
|
||||
`domain` is required too, but you no longer _write_ it: it's read from
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
You must still set `domain` too, but you no longer _write_ it: it's read from
|
||||
this hive's own entry in the directory, whose `domain` defaults to
|
||||
`<name>.<swarm.domain>`. A conventional swarm states no addresses at
|
||||
all, and a hive addressed by something else states it in the one place
|
||||
|
|
@ -276,8 +280,8 @@ If one host is behind NAT and can't accept incoming connections, only
|
|||
that host needs a null `wireguardEndpoint` on the peer config — the
|
||||
other side initiates. With keepalive on, the NAT hole stays open.
|
||||
|
||||
If both hosts are behind NAT, a STUN relay or a third host (exit node)
|
||||
is required. Out of scope for v0.
|
||||
If both hosts are behind NAT, you need a STUN relay or a third host
|
||||
(exit node). Out of scope for v0.
|
||||
|
||||
## Snapshot store
|
||||
|
||||
|
|
@ -458,12 +462,16 @@ leftover at startup. A webhook has exactly one target URL, so per-hive
|
|||
registration never added a recipient — it took delivery away from
|
||||
whichever hive registered before it.
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
**The `agent-configs` org isn't yet.** Each hive still registers its own
|
||||
`pull_request` hook there, so that repo has two — the hive's and the
|
||||
controller's — and **both are expected; don't delete either.** Removing
|
||||
a hive's stops it acting on config PRs; removing the controller's just
|
||||
gets recreated on its next start.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
Nothing to configure. The controller registers the hooks only when this
|
||||
host also serves the swarm UI vhost — that's what publishes the
|
||||
endpoint, and a hook the forge can't reach would collect failed
|
||||
|
|
|
|||
|
|
@ -71,9 +71,13 @@ its own subdomain — enforced by every verifier rather than by
|
|||
convention. The constraint excludes both IP families as well, since a
|
||||
permitted-DNS-only constraint says nothing about IP SANs.
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
The root is issued with `pathlen:1`: it may sign hive CAs, and those may
|
||||
sign leaves, and the chain stops there.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
## What to hand a peer
|
||||
|
||||
`hivectl peer-config` prints the `services.hyperhive.swarm.hives."<name>"`
|
||||
|
|
@ -103,6 +107,8 @@ per-hive file.
|
|||
|
||||
## Adopting the hierarchy on an existing hive
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
A hive that predates the swarm root carries a self-signed `ca.pem`, and
|
||||
adopting the hierarchy means replacing it. That invalidates an anchor
|
||||
consumers already trust, and they refresh on their own schedule — agents
|
||||
|
|
@ -110,6 +116,8 @@ only pick up new trust when their container restarts, peers only on
|
|||
their own rebuild. **Who is allowed to decide that's what splits the
|
||||
two cases.**
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
### Where this host owns the root (`autoConfigure`)
|
||||
|
||||
Adoption happens by itself, once. `hive-tls-ca.service` notices that
|
||||
|
|
@ -141,10 +149,14 @@ rm <deploy.hive-controller.tls.stateDir>/ca.pem <deploy.hive-controller.tls.stat
|
|||
systemctl restart hive-tls-ca.service
|
||||
```
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
Failing rather than warning is deliberate: a hive whose CA doesn't
|
||||
chain to the root it received is misconfigured, and a warning in a
|
||||
build log isn't something anyone reads twice.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
To keep the current CA on purpose — a hive that deliberately stays
|
||||
outside the hierarchy, or one mid-migration — `touch` the marker file
|
||||
named in the message. That's a decision, and it's recorded as one.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
# Credentials: the target shape
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
The swarm's credential store is bao. This page describes the shape every
|
||||
credential is meant to have — who mints it, who reads it, and how it renews
|
||||
— not what's on disk today. [`secrets.md`](secrets.md) remains the map of
|
||||
the files that exist right now; this page replaces it, and `secrets.md` gets
|
||||
deleted, once the swarm's credential path matches what's described below.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
**Public material is a value.** The store hands a certificate or a public
|
||||
nkey to every client that connects, so it's a fine place for that material.
|
||||
Nothing below is about those.
|
||||
|
|
@ -48,6 +52,8 @@ path at runtime — not a path on disk, and not a unit whose job is to turn a
|
|||
store value into a file. A renewal cell may never read `NONE`: state the
|
||||
strategy for every credential, including the mTLS leaf.
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
| store path | minter | reader — pulls at runtime, holds in memory | renewal |
|
||||
| -------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | -------------- |
|
||||
| `swarm/agents/<agent>/matrix/<account>` | `swarm-controller` | the agent container itself, under the certificate its hive passed in | must be stated |
|
||||
|
|
@ -57,6 +63,8 @@ strategy for every credential, including the mTLS leaf.
|
|||
| `swarm/services/<clientId>/oidc/client` | authelia | the service process that presents the client secret, under the certificate of the host it runs on | must be stated |
|
||||
| _(not in the store)_ a hive's mTLS leaf | the store's own PKI, or an operator placing it by hand | its own client, off disk — the exception above, because it's what makes every other row's pull possible | must be stated |
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
**An agent's mTLS leaf is in the store; a hive's isn't, and the difference
|
||||
isn't an inconsistency.** The rule the exception protects is that nothing
|
||||
can fetch from the store the credential it would need in order to fetch. A
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ eval, naming the option it wants. That's deliberate: a queue that started
|
|||
without them would accept `CONNECT {"user":"auth"}` from anyone sharing the
|
||||
host's network namespace, and nothing would look wrong until somebody connected.
|
||||
|
||||
**All four or none** — the seed paths are required too, not just the public
|
||||
**All four or none** — you must supply the seed paths too, not just the public
|
||||
keys. They're two halves of the same pair: the server verifies with the public
|
||||
half, the responder signs with the private one. Supplying only the public keys
|
||||
used to pass eval and leave the queue with an auth-callout nobody answers, which
|
||||
|
|
@ -195,7 +195,7 @@ the client id it authenticates, because that's how a queue client reads them —
|
|||
the secret by path, the id by value. No local fallback exists, and none is
|
||||
possible, so absent files mean this hive's agents don't connect, which is what
|
||||
a swarm looks like before the publisher on the authelia host has run. The
|
||||
reader runs before `hive-c0re.service` and is wanted (not required) by it, so
|
||||
reader runs before `hive-c0re.service`, which wants it (doesn't require it), so
|
||||
an agent container never renders ahead of the credential; an unreachable store
|
||||
delays the daemon's start rather than failing it.
|
||||
|
||||
|
|
@ -231,9 +231,9 @@ exists so a host holds **one** out-of-band secret, its client certificate, and
|
|||
reads everything else with it.
|
||||
|
||||
Two things follow, and `swarm-grafana.nix` asserts both rather than degrading:
|
||||
running Grafana requires `swarm.authelia.url` (its local login form is disabled
|
||||
unconditionally, so SSO isn't a feature of some topologies — it's the only way
|
||||
in), and it requires this host's `deploy.bao.clientCertFile` /
|
||||
running Grafana requires `swarm.authelia.url` (this module disables its local
|
||||
login form unconditionally, so SSO isn't a feature of some topologies — it's the
|
||||
only way in), and it requires this host's `deploy.bao.clientCertFile` /
|
||||
`clientKeyFile`. Each refusal names the option to set. Both used to be silent:
|
||||
a null URL dropped the OIDC block, a missing leaf produced a warning, and
|
||||
either one left a Grafana with no SSO and no password box — nothing failed, so
|
||||
|
|
|
|||
|
|
@ -118,12 +118,16 @@ See `retentionPeriod` below before leaving it at its default.
|
|||
| `swarm.grafana.oidc.role` | Default `Admin` for everyone who logs in. Lower to `Viewer`/`Editor` if the swarm grows operators who shouldn't be able to reconfigure Grafana. |
|
||||
| `deploy.grafana.datasourceUrl` | Only if you front VictoriaMetrics with something else. It defaults to the store on this host, which is the only thing it can reach. |
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
**Logging in.** Grafana is behind swarm SSO, so the accounts are the
|
||||
authelia ones — there is no separate Grafana password, and this module
|
||||
switches off the local login form whenever SSO is configured. If you enable
|
||||
Grafana on a host with no authelia, the form stays on and Grafana's
|
||||
default `admin`/`admin` applies; change it before exposing that host.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
**Where the data comes from.** The swarm's OTEL collector, below.
|
||||
|
||||
Neither container is reachable except through the gateway: both bind
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ read that same value, so the redirect URI authelia accepts and the one
|
|||
the service actually sends can't drift apart. A mismatch there is a
|
||||
rejected login with no error text worth reading.
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
⚠️ The delivery is a copy, not a `bindMounts` entry, and deliberately so:
|
||||
nixos-container refuses to start a container whose bind source is
|
||||
missing, and this secret doesn't exist until authelia's first boot has
|
||||
|
|
@ -128,6 +130,8 @@ run. Binding it would make the service wait on a file that waits on a
|
|||
container that starts after it — on a fresh hive, a permanent stall
|
||||
presenting as "the forge is broken," many layers from its cause.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
### 2. Swarm-managed services
|
||||
|
||||
The controller side owns provisioning: `swarmctl` writes both halves, the
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ fine and still gets bounced.
|
|||
swarmctl user add <you> --group admins
|
||||
```
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
`admins` deliberately, not a new word: [`../getting-started/setup.md`](../getting-started/setup.md) has
|
||||
told every operator to create exactly that group since the bootstrap step
|
||||
existed, so an account made by following the guide already passes. This
|
||||
|
|
@ -45,6 +47,8 @@ is the first rule that _consumes_ a group name — inventing a second one
|
|||
would have meant those accounts silently failing a check they were
|
||||
supposed to pass.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
An account created without any group needs re-adding with the flag —
|
||||
`swarmctl` reads the existing entry out of `users.yml,` so the group is
|
||||
what changes.
|
||||
|
|
@ -73,6 +77,8 @@ a container":
|
|||
| vhost + `gateway.localNames` | the service's own module (for example `nix/host-modules/swarm-ui.nix`) |
|
||||
| **certificate name** | `nix/host-modules/swarm.nix` (`serviceDomains`) |
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
The DNS record and the local-dev `/etc/hosts` entry need no separate
|
||||
edit: both derive from `services.hyperhive.gateway.localNames`,
|
||||
which a service's own module already has to push its domain into to be
|
||||
|
|
@ -82,6 +88,8 @@ the surface the hive's own domain serves (dashboard, per-agent routing,
|
|||
matrix discovery); a swarm service declares its own vhost next to its
|
||||
own options, the way `swarm-ui.nix` and `swarm-authelia.nix` do.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
⚠️ The certificate one is the hardest to predict and the most visible when
|
||||
missed. `serviceDomains` is _both_ the services sub-CA's
|
||||
`nameConstraints` set and the leaf's SAN list, and the apex is a
|
||||
|
|
|
|||
Loading…
Reference in a new issue