docs(boundary): drop changelog framing, dedupe ReloadGatewayNginx explainer
This commit is contained in:
parent
58459bbbb3
commit
c6eda124b1
1 changed files with 28 additions and 29 deletions
|
|
@ -5,12 +5,10 @@ _implementation_ work — container network isolation, the unifying
|
|||
gateway, core-daemon privsep — is tracked as `area:ops` issues on
|
||||
the forge.
|
||||
|
||||
The operator/agent boundary is now technically enforced, not just a
|
||||
convention. Containers run in private netns (network isolation is
|
||||
The operator/agent boundary is technically enforced, not just a
|
||||
convention: containers run in private netns (network isolation is
|
||||
always on), the gateway proxies all operator-facing traffic, and
|
||||
`hive-c0re` runs as the unprivileged `hive-core` user. All three
|
||||
`area:ops` pillars — network isolation, the gateway, and privsep —
|
||||
are complete and active.
|
||||
`hive-c0re` runs as the unprivileged `hive-core` user.
|
||||
|
||||
## Two principals, two paths
|
||||
|
||||
|
|
@ -47,9 +45,9 @@ every boundary claim above is aspirational. Network isolation is what
|
|||
makes the boundary _real_; the gateway and privsep are ergonomics and
|
||||
defence-in-depth layered on top.
|
||||
|
||||
Network isolation is now complete and always on: every agent container
|
||||
runs in a private netns behind the hive bridge. The shared-netns mode
|
||||
was removed. See `docs/network.md`.
|
||||
Network isolation is complete and always on: every agent container
|
||||
runs in a private netns behind the hive bridge, and there is no
|
||||
shared-netns mode. See `docs/network.md`.
|
||||
|
||||
Concretely, the core daemon's dashboard `/api` carries **no
|
||||
application-layer authentication** — operator-authority routes are served
|
||||
|
|
@ -64,15 +62,18 @@ operator-authority route inherits that assumption. `hive-ci` is treated like an
|
|||
agent for this purpose — it runs untrusted PR code and is netns-isolated for
|
||||
the same reason.
|
||||
|
||||
The `area:ops` issues followed this sequencing:
|
||||
The boundary rests on three layers:
|
||||
|
||||
1. **Gateway** — pure ergonomics win, unblocks same-origin (lets the
|
||||
cross-origin CORS shim on `/answer-question/{id}` go away), no
|
||||
behavioural risk. An nginx nixos-container now sits in front of all
|
||||
surfaces; per-agent UIs are proxied under `/agent/<name>/`.
|
||||
2. **Network isolation** — the load-bearing step that turns the
|
||||
honour-system split into an enforced boundary. **Complete** —
|
||||
always-on, unconditional; the shared-netns mode was removed.
|
||||
1. **Gateway** — fronts all surfaces (dashboard + every per-agent UI)
|
||||
on one origin. An nginx nixos-container proxies per-agent UIs under
|
||||
`/agent/<name>/`, which is what lets the inline-answer POST to
|
||||
`/answer-question/{id}` go same-origin instead of needing a
|
||||
cross-origin CORS shim. Pure ergonomics — no behavioural risk on
|
||||
its own.
|
||||
2. **Network isolation** — the load-bearing layer: every agent
|
||||
container runs in a private netns behind the hive bridge, always
|
||||
on and unconditional. This is what turns the operator/agent split
|
||||
from an honour-system convention into an enforced boundary.
|
||||
3. **Privsep** — defence in depth on the core process; `hive-c0re`
|
||||
runs as the unprivileged `hive-core` user and delegates root
|
||||
operations to `hive-priv`, a narrow socket-activated helper. See
|
||||
|
|
@ -84,15 +85,14 @@ The `area:ops` issues followed this sequencing:
|
|||
systemd unit. The unit binds `/run/hive/priv.sock` with
|
||||
`SocketGroup=hive-core` and mode `0660` and passes the ready listener
|
||||
to the helper as fd 3 (`LISTEN_FDS`). The helper requires this and
|
||||
bails if it isn't socket-activated — there is intentionally no
|
||||
self-bind fallback.
|
||||
bails if it isn't socket-activated.
|
||||
|
||||
Dropping the old fallback removed a dev/prod divergence: when
|
||||
`hive-priv` bound the socket itself it created the file owned by
|
||||
root's primary group rather than `hive-core`, so a `hive-core` client
|
||||
couldn't connect the way the socket unit's `SocketGroup` grant
|
||||
intends. Requiring socket activation everywhere means dev and prod
|
||||
take the exact same path and the group grant always holds.
|
||||
⚠️ There is intentionally no self-bind fallback: if `hive-priv` bound
|
||||
the socket itself, it would create the file owned by root's primary
|
||||
group rather than `hive-core`, and a `hive-core` client couldn't
|
||||
connect the way the socket unit's `SocketGroup` grant intends.
|
||||
Requiring socket activation everywhere keeps dev and prod on the
|
||||
exact same path, so the group grant always holds.
|
||||
|
||||
### the per-agent socket dir
|
||||
|
||||
|
|
@ -129,10 +129,9 @@ nginx reaches all of `/run/hive-agent` as a plain host path. Dropping
|
|||
them and the rest of the host. That costs no network isolation: nginx
|
||||
binds the host's `:80`/`:443` and reaches `localhost` upstreams, which a
|
||||
netns would have to be opened up for anyway.
|
||||
🔑 It does mean nothing *implicitly* scopes the privileged reload verb,
|
||||
so the scope is explicit: the unit name is hard-coded in `hive-priv` —
|
||||
see `PrivRequest::ReloadGatewayNginx`. **A caller cannot name the unit,
|
||||
so the verb cannot be steered at another service.**
|
||||
🔑 It does mean nothing *implicitly* scopes the privileged reload verb —
|
||||
see [`docs/security.md`](security.md#hive-c0re-privilege-separation) for
|
||||
how `PrivRequest::ReloadGatewayNginx`'s containment works.
|
||||
|
||||
⚠️ Contrast `/shared`, which *is* sticky world-writable (`1777`): it has
|
||||
many legitimate writers, so sticky is the best available answer there.
|
||||
|
|
|
|||
Loading…
Reference in a new issue