docs/gateway.md: drop duplicate 'Per-agent UDS upstream' section

mara/damocles wrote a fuller version of the same section at line 70
(`Per-agent unix-socket upstream (#784)`) as part of #832 — covers
the 4-step rollout flow including the .bound marker filter that
landed in #832. The atlas-side section at line 207 was the pre-#832
version with the eval-time path-exists gate notes; superseded.

Net effect: one canonical section on the unix-socket upstream story
rather than two with overlapping content.
This commit is contained in:
atlas 2026-05-31 16:35:26 +02:00
commit 4821f1a36e

View file

@ -204,56 +204,3 @@ already special cased in the nginx config". Other gateway routes
(forge / matrix / fluffychat) get nginx defaults — extending the
custom-error pattern there is a separate follow-up.
## Per-agent UDS upstream (#784)
Per-agent `/agent/<name>/` upstreams default to TCP loopback
(`http://127.0.0.1:<port>/`) but each agent can opt in to unix-
domain socket upstream by flipping `hyperhive.web.useUnixSocket =
true` in its `agent.nix`. Rollout flow:
1. **Harness** binds a `UnixListener` at
`/run/hive-agent/<name>/web.sock` when `HIVE_WEB_SOCKET` is set
(PR #800). The env var is set by `harness-base.nix` from the
`useUnixSocket` option (#822).
2. **hive-c0re** writes a sibling `agent-sockets.json` next to
`agent-ports.json` (PR #809) and bind-mounts the per-agent
subdir `/run/hive-agent/<name>/` into each sub-agent container
via `set_nspawn_flags` (PR #813). Path-shape lives in
`hive_c0re::agent_sockets::socket_path_for(name)` — one canonical
derivation, no triangulation across the c0re / harness / gateway
boundaries.
3. **Gateway** reads both `agentPortsFile` + `agentSocketsFile` at
deploy time. Per agent: a socket entry beats the TCP port. The
gateway container bind-mounts `/run/hive-agent/` read-only so
nginx inside can `connect(2)` to the per-agent sockets.
Mixed state during rollout: agents flip per-agent. Agents that
haven't opted in keep the TCP path; agents that have flipped use
the UDS path. The two coexist on the same gateway with zero
per-agent special-casing in the nginx config (`agentUpstreamFor`
resolves the right shape from the JSON maps).
**Eval-time gate during the rollout window**: `agentUpstreamFor`
checks `builtins.pathExists` on the socket path before picking the
UDS upstream. c0re's `agent_sockets::write` emits an entry for every
sub-agent regardless of whether they've actually flipped, so the
gateway has no other signal that a given agent is or isn't actually
binding the socket. The path-exists check works because a flipped
agent's harness binds the socket on container start, and the
gateway-container rebuild (which re-runs nix eval) happens on every
topology change — so a freshly-flipped agent flips through TCP →
UDS over one rebuild cycle. Once c0re's `.bound` marker filter
ships (#784 step 2d follow-up), `agent-sockets.json` only contains
agents that have actually bound, and the path-exists check is
redundant but harmless. Step 4 drops it.
**Why per-agent subdir** (not a flat `/run/hive-agent/<name>.sock`):
the harness's `bind_unix` helper unlinks any stale socket before
calling `bind(2)`, and a file bind-mount loses its host-side anchor
on unlink. Dir bind-mount keeps the same dir inode visible on both
sides, so the new `web.sock` shows up on the host the moment the
harness binds it (damocles #813 design note).
**Step 4 plan**: once every agent has flipped + soaked, the
`agentPortsFile` fallback drops + the harness's TCP bind goes away
entirely. Tracked at #784 step 4.