docs: move the socket-dir ownership rule to boundary.md

It was written into gateway.md, which only owns half the story: that
doc describes the web.sock path, and before this branch it never
mentioned agent.sock at all. Putting a rule shared by hive-c0re, the
harness and nginx inside the gateway walkthrough means someone asking
"why can't c0re dial agent.sock" has no reason to look there.

boundary.md already covers who may touch what across the trust boundary
-- including the sibling case of hive-priv's socket getting its mode
from the unit rather than the process -- so the rule lives there now,
with the three principals as a table. gateway.md keeps a two-line note
about the one fact it needs (nginx traverses via o=--x) and links out.
This commit is contained in:
atlas 2026-08-04 00:45:58 +02:00 committed by mara
commit 289db00321
2 changed files with 39 additions and 17 deletions

View file

@ -96,23 +96,11 @@ now set unconditionally for every agent. The mechanism:
harness's `unlink + bind(2)` cycle on socket replace. Per-agent
subdir keeps each agent's container blind to siblings' sockets.
**Ownership of that dir is declared, not repaired.** The tmpfiles.d
entry written by `SyncAgentTmpfiles` names the agent's container
uid/gid directly — `d /run/hive-agent/<name> 0751 <uid> <gid> -`.
Three principals need the dir and no two share a group: the harness
(owner, `rwx`, binds + unlinks its sockets), `hive-c0re` (dials
`agent.sock`) and the gateway's nginx (dials `web.sock`, and has all
of `/run/hive-agent` bind-mounted in). The latter two only need
traverse, which is what `o=--x` grants; both sockets are `0666`.
Do **not** reintroduce a chown here: tmpfiles re-applies this entry
on every boot *and* every agent spawn/destroy, so any ownership set
afterwards is reverted the next time any agent changes. The mode is
also load-bearing — write permission on a *directory* is what confers
the right to unlink its entries, whoever owns them, and the sticky bit
is the only thing that would restrain that (it is not set here). So a
world-writable socket dir would let anything able to reach the path
replace an agent's socket with its own; `o=--x` removes that
permission outright rather than qualifying it.
The dir is `0751`, owned by the agent's container uid/gid, so
nginx reaches `web.sock` through `o=--x` (traverse) and the socket's
own `0666`. The gateway is one of three principals sharing that dir
and does not own its ownership rules — see
[`docs/boundary.md`](boundary.md#the-per-agent-socket-dir).
3. **Marker gate**. After successful `bind_unix`, the harness drops
`<dir>/hyperhive-socket-bound` next to the socket. c0re's
`agent_sockets::write` filters its JSON map by marker presence —