From 6c9cb66dce1d87efb71962b88de1cc555a7bc4f5 Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 12 Oct 2026 03:38:25 +0200 Subject: [PATCH] docs: the review classifier's try-out service, its key and its subject - review-classifier.md: claude runs spawn through hive-claude directly with no tools and no session (hive-runtime holds only TurnStop); the answer's fields, the 500-character reason cap and what a failure does; how the try-out page reaches the classifier; the settled parts of the open list (API key path, try-out subject, --tools "" on claude). The banner stays. - services.md: a Review classifier section with the two operator steps. - secrets.md, credentials.md: the classifier's leaf and the key row. - network.md: the container's row. CLAUDE.md: the crate. --- CLAUDE.md | 6 ++++ docs/networking/network.md | 15 ++++---- docs/swarm/credentials.md | 39 ++++++++++---------- docs/swarm/review-classifier.md | 64 ++++++++++++++++++++------------- docs/swarm/secrets.md | 39 ++++++++++---------- docs/swarm/services.md | 21 +++++++++++ 6 files changed, 115 insertions(+), 69 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6768cdf5..b91f2f1a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -187,6 +187,12 @@ hand-maintained per-file tree drifts out of sync with the code. defaults look for `VAULT_ADDR`/`VAULT_CLIENT_CERT`/`VAULT_CLIENT_KEY`, which no unit in this tree sets, so falling through to them yields a client with **no identity** and a TLS handshake failure that names no cause. +- **`swarm-review-classifier/`** — the review classifier's try-out daemon, + in its own container where `deploy.review-classifier.enable` is set. Takes + a PR and classifications from `swarm-controller` over the queue, runs one + `claude --print` per classification (no tools, no session) and replies + with the rows and the overall verdict. Holds no forge credential. Design: + [`docs/swarm/review-classifier.md`](docs/swarm/review-classifier.md). - **`swarmctl/`** — swarm-level operator CLI, installed by the swarm-controller module on the host that runs the daemon. Runs as **root and acts directly** — it serves no socket, publishes no HTTP diff --git a/docs/networking/network.md b/docs/networking/network.md index 194a5c44..c4678ca4 100644 --- a/docs/networking/network.md +++ b/docs/networking/network.md @@ -42,13 +42,14 @@ that touches it. └─────────┘ └─────────┘ └─────────┘ ``` -| container | netns | IPv4 | listens / reached via | -| ----------------- | ----------------------- | -------------- | ----------------------------------------------------------------------------------------------- | -| gateway (host) | host | host addresses | nginx `:80`/`:443` (every vhost); dnsmasq `bridgeIp:53` + DHCP `:67` on the bridge | -| `hive-forge` | host (shared) | host addresses | forgejo `:3000` http, `:2222` git-ssh; fronted by the `forge.` vhost | -| `hive-matrix` | host (shared) | host addresses | tuwunel `:8008` (+ optional federation port); fronted by the matrix vhost | -| `swarm-ci-runner` | private, veth on bridge | DHCP pool | outbound only (runner → forge); no inbound surface | -| `h-` | private, veth on bridge | DHCP pool | web UI via UDS `/run/hive-agent/` → nginx sub-path; in-container UI port hashed 8100–8999 | +| container | netns | IPv4 | listens / reached via | +| ------------------------- | ----------------------- | -------------- | ----------------------------------------------------------------------------------------------- | +| gateway (host) | host | host addresses | nginx `:80`/`:443` (every vhost); dnsmasq `bridgeIp:53` + DHCP `:67` on the bridge | +| `hive-forge` | host (shared) | host addresses | forgejo `:3000` http, `:2222` git-ssh; fronted by the `forge.` vhost | +| `hive-matrix` | host (shared) | host addresses | tuwunel `:8008` (+ optional federation port); fronted by the matrix vhost | +| `swarm-ci-runner` | private, veth on bridge | DHCP pool | outbound only (runner → forge); no inbound surface | +| `swarm-review-classifier` | private, veth on bridge | DHCP pool | outbound only (classifier → queue, secret store, hive collector); no inbound surface | +| `h-` | private, veth on bridge | DHCP pool | web UI via UDS `/run/hive-agent/` → nginx sub-path; in-container UI port hashed 8100–8999 | The flows, end to end: diff --git a/docs/swarm/credentials.md b/docs/swarm/credentials.md index 84703b97..11fe8bfc 100644 --- a/docs/swarm/credentials.md +++ b/docs/swarm/credentials.md @@ -55,25 +55,26 @@ of the cell says how. -| store path | minter | reader — pulls at runtime, holds in memory | automatic re-mint | automatic re-pull | -| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `swarm/agents//matrix/main` | `swarm-controller`, with the swarm's appservice token, at agent creation and in a five-minute pass | the agent container itself, under the certificate its hive passed in | ✅ the pass re-mints when the stored token is missing, unknown to the homeserver, or someone else's | ✅ `hive-matrix-daemon` exits when the homeserver rejects its token, and a five-minute timer restarts it, which reads the store again | -| `swarm/agents//matrix/` | `swarm-controller` | the agent container itself, under the certificate its hive passed in | must be stated | must be stated | -| `swarm/controller/swarm-controller/matrix/appservice-token` | `swarm-matrix-ctl`, inside the `hive-matrix` container, once | `swarm-controller`, under its own certificate | ❌ `swarm-matrix-ctl` mints it once; the container keeps its copy and republishes it when the store's differs | ✅ the controller reads it on every five-minute matrix pass | -| `swarm/controller/swarm-controller/oidc/client` | authelia, at its first boot; `swarm-secret-publish` copies it in | `swarm-controller`, under its own certificate, once at start | ❌ authelia mints it once. A re-mint is republished by `swarm-secret-publish`'s path unit | ❌ read once at start; the controller holds the old value until it restarts | -| `swarm/controller/swarm-controller/forge/token` | the forge, inside the `hive-forge` container, once; `swarm-bao-forge-publisher` on the forge's host copies it in under its own certificate, with a write-only grant | `swarm-controller`, under its own certificate, at start | ❌ the forge mints it once and keeps its copy in the container; the publisher writes that copy each time the forge container starts and each time the mint writes the file | ❌ the controller reads it at start, and in the background with backoff until it first finds it; a replaced token reaches it with the next restart | -| `swarm/agents//bao-mtls` | the store's agent PKI mount (`deploy.bao.agentPkiMountPath`), which generates the key, at `swarm-controller`'s request at agent creation | `hive-c0re`, under the hive's own certificate, when it writes the agent's container config; then `hive-agent-bao-identity` in the agent container, under the leaf it holds | ✅ `swarm-controller`'s five-minute pass re-issues a live agent's leaf once it's past half its validity (45 of 90 days, read from the certificate itself) | ✅ `hive-agent-bao-identity` re-reads it every 10 minutes and swaps a new leaf into `/run/hive-agent-bao-identity/`, which every store login in the container presents. It reads under the leaf it holds, so it renews only while that leaf is valid | -| `swarm/agents//queue` | `swarm-controller`, at agent creation | `hive-agent` in the agent container, under the agent's own certificate, held in memory — the identity it presents to the swarm queue, naming that one agent rather than its hive | ✅ `swarm-controller`'s five-minute pass re-mints a live agent's secret once it's 45 days old by `minted_at` on the stored object; a secret with no `minted_at` gets one stamped, value unchanged. The pass skips agents declared `Destroyed` — declaring an agent destroyed deletes every version of the path instead, the undo of the mint rather than another one | ✅ `hive-agent` reads the path before its first connect and again on every reconnect attempt, so a reconnect after a re-mint presents the new secret. An open connection keeps the secret it connected with; after a revocation the agent keeps retrying under the queue client's backoff | -| `swarm/agents//forge-token` | `swarm-controller`, at agent creation and in a pass every 5 minutes over every agent with a store identity | the agent container itself, under its own certificate, fetched to `/run/hive-agent-forge-token/token` | ✅ the controller re-mints when the stored token is missing or no longer matches the forge (last eight characters and scopes) | ✅ the agent re-fetches on a 10-minute timer | -| `swarm/agents//forge/