From 461c599e099f6e2afd72786b9e6c5e4bd82f7b06 Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 8 Sep 2026 12:07:42 +0200 Subject: [PATCH] docs: fix genuine passive-voice hits in docs/trust-boundary Third batch of hyperhive#4042's Passive pass (see #4098/#4099 for the first two and the read-every-hit discipline this pass uses). 23 hits across boundary.md (10) and security.md (13). boundary.md, 2 of 10 rewritten: - "Operator-authority actions ... are served by the core daemon and only reachable via the gateway" -> "The core daemon serves operator-authority actions ..., reachable only via the gateway" -- the actor was already named in the sentence, and the parallel "Agent" bullet right below it is already active voice ("speaks only for itself"), so the Operator bullet was the inconsistent one. - "ownership set afterwards is reverted the next time any agent changes" -> "and reverts any ownership set afterwards the next time any agent changes" -- continues the same subject ("the `d` re-applies ... and reverts ...") already established one clause earlier, avoiding a subject switch entirely. security.md, 6 of 13 rewritten (across 3 edits touching 6 flagged locations): - "A compromised/confused agent's reach ... is bounded by its own account's scope" -> "Its own account's scope bounds a compromised/confused agent's reach" -- matches the section's own header ("Scoped tokens bound the blast radius"), which is already active voice. - "Two allow-listed root prefixes are accepted; all other paths are rejected" -> "It accepts two allow-listed root prefixes and rejects all other paths" -- continues "it" from the endpoint named one sentence earlier. - The container-allowlist paragraph (3 flagged locations: "is validated", "are accepted", "are rejected") rewritten as one consistent-subject passage with `hive-priv` as the actor throughout, matching the neighboring bullets in the same subsection ("**Socket-activated** -- systemd starts hive-priv...", already active voice) -- the passive version was the odd one out among siblings, not the house style. 15 of 23 hits left alone. The recurring legitimate shapes, same categories as #4098: predicate-adjective copulas that only look like passives ("an agent is trusted code", "the agent is privileged" -- "trusted"/"privileged" modify the noun, there's no actor to name), quoted rhetorical contrasts where the passive is doing real work (a "wrong-framing" quote left passive on purpose, paired with an active "right-framing" quote right after it), the "is tracked as/in X" idiom (twice, same as #4098's precedent), and "X can't be Yed" / negative-capability invariant statements (matches #4098's "No X is Y" security-guarantee idiom). One deliberately left despite a nameable antecedent ("hive-gateway's access is scoped [by ReloadGatewayNginx] instead") -- lower-confidence rewrite than the others, left rather than force it. Verified: vale docs/trust-boundary before/after -- 23 -> 15 write-good.Passive hits, exactly the 8 rewritten, no other rule's hit count moved (the TooWordy/Microsoft.Avoid/alex hits vale also reports on these two files are pre-existing and out of scope for a Passive-only pass; TooWordy's hits specifically already have a fix queued in #4097, not duplicated here). --- docs/trust-boundary/boundary.md | 10 +++++----- docs/trust-boundary/security.md | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/trust-boundary/boundary.md b/docs/trust-boundary/boundary.md index be8c00d9..c1e6e5e7 100644 --- a/docs/trust-boundary/boundary.md +++ b/docs/trust-boundary/boundary.md @@ -14,9 +14,9 @@ always on), the gateway proxies all operator-facing traffic, and - **Operator** — reaches every UI (the dashboard + every per-agent page) through the gateway, on one origin. - Operator-authority actions (approve / deny, answer-as-operator, - lifecycle POSTs) are served by the core daemon and only - reachable via the gateway. + The core daemon serves operator-authority actions (approve / deny, + answer-as-operator, lifecycle POSTs), reachable only via the + gateway. - **Agent** — speaks only for itself, only over its per-agent unix socket. The socket's identity _is_ the agent (see `docs/process/conventions.md`, "identity = socket"). An agent must not @@ -112,8 +112,8 @@ both sockets are `0666`, which is all a dialer needs. **Ownership is declared, not repaired.** The tmpfiles.d entry written by `SyncAgentTmpfiles` names the uid/gid directly. Don't add a chown alongside it: `d` re-applies on every boot _and_ every agent -spawn/destroy, so ownership set afterwards is reverted the next time any -agent changes — which is exactly how this dir spent a long time at +spawn/destroy, and reverts any ownership set afterwards the next time +any agent changes — which is exactly how this dir spent a long time at `0777 root root` while a privileged chown appeared to be fixing it. The mode is load-bearing, not cosmetic. Write permission on a diff --git a/docs/trust-boundary/security.md b/docs/trust-boundary/security.md index 48c77cbb..c6fa8982 100644 --- a/docs/trust-boundary/security.md +++ b/docs/trust-boundary/security.md @@ -34,8 +34,8 @@ Each agent gets its own scoped credentials, never shared: collaborator grants; can't act as another agent or as `core`). - **matrix token** → that agent's matrix account only. -A compromised/confused agent's reach on the forge or matrix is bounded by -_its own_ account's scope, not the swarm's. This is the main thing standing +_Its own_ account's scope bounds a compromised/confused agent's reach on the +forge or matrix, not the swarm's. This is the main thing standing between "one agent does something dumb" and "the whole hive is affected." **Identity vs. secret (matrix).** The scoping is on the _secret_, not the @@ -100,7 +100,7 @@ provider) before handing them over. `GET /api/state-file?path=

` serves files from agent state dirs and the shared space to authenticated dashboard users (browser, operator). -Two allow-listed root prefixes are accepted; all other paths are rejected +It accepts two allow-listed root prefixes and rejects all other paths before touching the filesystem: - `/var/lib/hyperhive/agents//state/` — per-agent durable notes @@ -224,13 +224,13 @@ known operations; there is no arbitrary command pass-through: | `WriteAgentForgeToken` / `WriteAgentMatrixToken` | write `0600` credential file into agent state dir | | `RestartMatrixDaemon` | `systemctl --machine=h- restart hive-matrix-daemon.service` | -**Container allowlist** — every request is validated against an -allowlist before any operation: only names matching the agent-name -convention (char-validated) or the known sibling service containers -(`hive-forge`, `hive-matrix`, `hive-ci`) are accepted. `hive-gateway` is -a host unit, not a container, so it's not in this list — see -`ReloadGatewayNginx` above for how its access is scoped instead. -Arbitrary container names are rejected. +**Container allowlist** — `hive-priv` validates every request against +an allowlist before any operation: the allowlist accepts only names +matching the agent-name convention (char-validated) or the known +sibling service containers (`hive-forge`, `hive-matrix`, `hive-ci`), +and rejects arbitrary container names. `hive-gateway` is a host unit, +not a container, so it's not in this list — see `ReloadGatewayNginx` +above for how its access is scoped instead. **Socket-activated** — systemd starts `hive-priv` on the first incoming connection (`LISTEN_FDS=1`); it's not running between calls.