Watch
0
0
Fork
You've already forked hyperhive
0

docs(networking): fix round — argus review + audit E1/E2

observability.md: "Why two tiers" claimed the harness currently writes an
upstream token into the agent's own claude settings; that path was removed
with the direct-export mode it served (nix/agent-modules/otel.nix:56-63).
Reworded as the hypothetical the paragraph is actually making.

gateway.md: restored the agent-trust pointer to
/run/hive-ca/trust-bundle.pem in "Cert prompts" (hive-ca-trust.nix:41),
dropped by the earlier rewrite. Corrected the SPA-fallback section: only
the chat.<swarm> vhost uses the Accept-header map
(hive-matrix.nix:693-696); per-agent split mode uses file-existence
try_files (gateway_nginx.rs:93-134), not the same mechanism.

Refs #3902
This commit is contained in:
atlas 2026-10-01 23:53:27 +02:00
commit 54556e4661
2 changed files with 8 additions and 9 deletions

View file

@ -87,7 +87,7 @@ The issuer is a **host-held hive CA**, not a bare self-signed leaf. `hive-tls-ca
**Rotation**: `hive-tls-ca.service` re-signs the leaf when it's missing, within 30 days of expiry, or no longer covers the configured names, always under the same CA. It regenerates the CA only if missing or expired. To force a leaf rotation, delete `gateway.pem` under the state dir, restart the unit, then reload `nginx`. **Rotation**: `hive-tls-ca.service` re-signs the leaf when it's missing, within 30 days of expiry, or no longer covers the configured names, always under the same CA. It regenerates the CA only if missing or expired. To force a leaf rotation, delete `gateway.pem` under the state dir, restart the unit, then reload `nginx`.
**Cert prompts**: browsers warn once per host until you add the hive's `trust-bundle.pem` (the anchor, not the leaf) to the browser or OS trust store. **Cert prompts**: browsers warn once per host until you add the hive's `trust-bundle.pem` (the anchor, not the leaf) to the browser or OS trust store. A container that needs to trust it for its own outbound TLS gets the bundle a different way, bind-mounted read-only at `/run/hive-ca/trust-bundle.pem` (`nix/host-modules/lib/hive-ca-trust.nix`).
### Operator-provided cert (`tls.certDir`) ### Operator-provided cert (`tls.certDir`)
@ -261,14 +261,12 @@ How the gateway does what the sections above describe. Read before changing `hiv
### SPA fallback (Accept-header pattern) ### SPA fallback (Accept-header pattern)
The per-agent UIs and the `chat.<swarm>` vhost serve a flutter/SPA bundle via the Accept-header pattern below. The dashboard instead routes by **path** — see [Dashboard: path-based routing](#dashboard-path-based-routing-not-accept-header) below. Two requirements collide: The `chat.<swarm>` vhost (fluffychat) serves a flutter/SPA bundle via the Accept-header pattern below. Per-agent UIs solve the same two requirements differently, with file-existence `try_files` — see [Per-agent static frontend split](#per-agent-static-frontend-split). The dashboard routes by **path** — see [Dashboard: path-based routing](#dashboard-path-based-routing-not-accept-header) below. Two requirements collide for a vhost whose client-side router owns every route under `/`:
- hard-refresh on a sub-route must serve `index.html` (SPA's client-side router takes over after JS bootstrap) - hard-refresh on a sub-route must serve `index.html` (SPA's client-side router takes over after JS bootstrap)
- a non-navigation request that isn't an on-disk asset must NOT get HTML with the wrong content-type - a non-navigation request that isn't an on-disk asset must NOT get HTML with the wrong content-type
Solution: an `nginx http`-context `map $http_accept $<name>_spa_target { ... }` keyed on the request's Accept header. Browser navigations (`Accept: text/html,...`) get `index.html`; everything else (`Accept: image/*`, `*/*`, `application/json`, `text/event-stream`, …) gets a sentinel nonexistent path, so `try_files $uri $<name>_spa_target <final>` falls through to `<final>`. No extension allowlist, no `if` block, no regex heuristics. Solution: an `nginx http`-context `map $http_accept $matrix_spa_target { ... }` keyed on the request's Accept header. Browser navigations (`Accept: text/html,...`) get `index.html`; everything else (`Accept: image/*`, `*/*`, `application/json`, `text/event-stream`, …) gets a sentinel nonexistent path, so `try_files $uri $uri/ $matrix_spa_target =404` falls through to a plain `404` — a missing asset is just missing. No extension allowlist, no `if` block, no regex heuristics.
For matrix and per-agent static assets, `<final>` is `=404` (a missing asset is just missing).
#### Dashboard: path-based routing (not Accept-header) #### Dashboard: path-based routing (not Accept-header)

View file

@ -59,10 +59,11 @@ the control plane, so degraded telemetry isn't degraded operation.
### Why two tiers ### Why two tiers
**The hive tier isn't optional.** Exporting straight to `endpoint` would mean **The hive tier isn't optional.** Exporting straight to `endpoint` would mean
every agent needs the credential — and the harness delivers that token into every agent needs the credential — and the only place to hand it to an agent
the agent's own `~/.claude/settings.json`, a file the agent can read. `0600` container is somewhere the agent itself can read, its own claude settings
protects it from other containers, not from the agent itself. An option that among them. `0600` protects a secret from other containers, not from the
could select the direct path would reopen that hole. agent it belongs to. An option that could select that path would reopen the
hole.
**The tiers stay separate on one box.** An all-local hive is a statement about **The tiers stay separate on one box.** An all-local hive is a statement about
_where_ processes run, not about the shape of the deployment. A boundary that _where_ processes run, not about the shape of the deployment. A boundary that