From 0e10473e6f30f24ed12e9e8964b6e42dc45a7713 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 6 Nov 2026 18:34:41 +0100 Subject: [PATCH] fixup! docs: sort the top-level directories into five sections by what the reader wants --- README.md | 10 +++++----- docs/1-getting-started/nixos.md | 6 +++--- docs/1-getting-started/setup.md | 14 +++++++------- docs/2-handbook/agent-lifecycle/config-changes.md | 2 +- docs/2-handbook/agent-lifecycle/persistence.md | 2 +- docs/2-handbook/integrations/matrix.md | 2 +- docs/2-handbook/swarm/README.md | 10 +++++----- docs/2-handbook/swarm/services.md | 4 ++-- docs/2-handbook/swarm/sso.md | 6 +++--- docs/2-handbook/swarm/ui.md | 2 +- docs/2-handbook/web-ui/README.md | 8 ++++---- docs/4-implementation/networking/gateway.md | 12 ++++++------ docs/4-implementation/networking/network.md | 4 ++-- docs/4-implementation/scheduler/jobq.md | 2 +- docs/4-implementation/scheduler/observability.md | 6 +++--- docs/4-implementation/swarm/bao.md | 2 +- .../turn-loop/claude-invocation.md | 2 +- hive-agent/README.md | 4 ++-- 18 files changed, 49 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 327c2243..669e8d7d 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ box it gets: ## Quick start: an all-local swarm The whole swarm on one box — a hive plus every shared service. Good for a -dev box or a single-host deployment; [`docs/swarm/`](docs/2-handbook/swarm/README.md) +dev box or a single-host deployment; [`docs/2-handbook/swarm/`](docs/2-handbook/swarm/README.md) covers spreading a swarm across hosts. ```nix @@ -173,7 +173,7 @@ once, top to bottom. → [reference](docs/2-handbook/reference/swarmctl-cli.md) - **per-hive** — each hive's dashboard (container state, rebuild queue) and `hivectl` for host-level administration and - container shells. → [`docs/web-ui/`](docs/2-handbook/web-ui/README.md) · + container shells. → [`docs/2-handbook/web-ui/`](docs/2-handbook/web-ui/README.md) · [hivectl](docs/2-handbook/tools/hivectl.md) You are an SSO user too: `swarmctl user add --group admins`, and a @@ -187,10 +187,10 @@ one becomes a homeserver admin within five minutes of that first login. pick the page for your task rather than reading front to back. Some common entry points: -- connecting hives into a swarm → [`swarm/`](docs/2-handbook/swarm/README.md) -- how config changes flow → [`agent-lifecycle/config-changes.md`](docs/2-handbook/agent-lifecycle/config-changes.md) +- connecting hives into a swarm → [`2-handbook/swarm/`](docs/2-handbook/swarm/README.md) +- how config changes flow → [`2-handbook/agent-lifecycle/config-changes.md`](docs/2-handbook/agent-lifecycle/config-changes.md) - trust boundary + threat model → [`trust-boundary/`](docs/2-handbook/trust-boundary/boundary.md) -- what an agent's turn looks like → [`turn-loop/`](docs/4-implementation/turn-loop/README.md) +- what an agent's turn looks like → [`4-implementation/turn-loop/`](docs/4-implementation/turn-loop/README.md) - every `services.hyperhive.*` option → [options reference](https://hyperhive.darkest.space/options/) ## Hacking on it diff --git a/docs/1-getting-started/nixos.md b/docs/1-getting-started/nixos.md index eadf59ef..d66557b5 100644 --- a/docs/1-getting-started/nixos.md +++ b/docs/1-getting-started/nixos.md @@ -84,11 +84,11 @@ Run `nixos-rebuild switch --flake .#my-host`. The swarm UI then answers at Leave the other options at their defaults until you need them: - Spreading a swarm over more than one host, and the credentials a split swarm - needs: [`swarm/README.md`](../2-handbook/swarm/README.md) and - [`swarm/credentials.md`](../2-handbook/swarm/credentials.md). + needs: [`2-handbook/swarm/README.md`](../2-handbook/swarm/README.md) and + [`2-handbook/swarm/credentials.md`](../2-handbook/swarm/credentials.md). - Every option, with its type and default: [the options reference](https://hyperhive.darkest.space/options/). -- The secret store's seal and the granter: [`swarm/bao.md`](../4-implementation/swarm/bao.md). +- The secret store's seal and the granter: [`4-implementation/swarm/bao.md`](../4-implementation/swarm/bao.md). ## Next diff --git a/docs/1-getting-started/setup.md b/docs/1-getting-started/setup.md index b3fdf7e2..a608cea7 100644 --- a/docs/1-getting-started/setup.md +++ b/docs/1-getting-started/setup.md @@ -10,7 +10,7 @@ Every command runs as **root on the host**. > **Not all-local?** Each step says which host it runs on. A split swarm > also has credentials you can't generate where they're read — each -> host's mTLS identity at the secret store. Read [`swarm/credentials.md`](../2-handbook/swarm/credentials.md) first; it +> host's mTLS identity at the secret store. Read [`2-handbook/swarm/credentials.md`](../2-handbook/swarm/credentials.md) first; it > says which files you place, and where. ## 1 · Secret store @@ -53,7 +53,7 @@ active` while the store comes up; the units retry every 30s for a day. With the default `pkcs11` seal the store unseals itself from here on. With `deploy.bao.seal = "shamir"`, run `bao operator unseal` after every restart. What the granter is, why it's root-equivalent, and the store's TLS: -[`swarm/bao.md`](../4-implementation/swarm/bao.md). +[`4-implementation/swarm/bao.md`](../4-implementation/swarm/bao.md). ## 2 · Your SSO account @@ -71,13 +71,13 @@ It prints a generated password once — record it. Keep both flags: - **`--email`** — the forge won't create an account without one. Fix either afterwards with `swarmctl user update mara --add-group admins ---email …`. Details: [`swarm/sso.md`](../2-handbook/swarm/sso.md). +--email …`. Details: [`2-handbook/swarm/sso.md`](../2-handbook/swarm/sso.md). ## 3 · Swarm UI login Open `https:///` and sign in with the account from step 2. The name resolves on the box itself through `/etc/hosts`; from anywhere else it -needs a real DNS record. → [`swarm/ui.md`](../2-handbook/swarm/ui.md) +needs a real DNS record. → [`2-handbook/swarm/ui.md`](../2-handbook/swarm/ui.md) Signing in to the forge once through SSO creates your forge account under the same username. Then, _on the swarm-controller's host_: @@ -114,7 +114,7 @@ container keeps starting with the hive meanwhile. From here on, ask ruth. Open her card on `/agents` in the swarm UI and use the message box under her terminal. She is the manager agent: her MCP surface is the privileged one that configures agents, and she can recover the others. Changes to -an agent's config arrive as PRs you merge. → [`agent-lifecycle/agent-roster.md`](../2-handbook/agent-lifecycle/agent-roster.md) +an agent's config arrive as PRs you merge. → [`2-handbook/agent-lifecycle/agent-roster.md`](../2-handbook/agent-lifecycle/agent-roster.md) To create an agent yourself instead, use the swarm UI, or: @@ -129,10 +129,10 @@ swarm UI's job view for progress. Later config changes are PRs on `agent-configs/iris`; you merge them on the forge, and the merge deploys them. → -[`agent-lifecycle/config-changes.md`](../2-handbook/agent-lifecycle/config-changes.md#config-changes) +[`2-handbook/agent-lifecycle/config-changes.md`](../2-handbook/agent-lifecycle/config-changes.md#config-changes) ## After setup: use the swarm UI Day-to-day operation happens in the swarm UI at `https:///`: agents, hives, jobs and messages. Swarm-level operations take over from the -per-hive dashboard and `hivectl`. → [`swarm/ui.md`](../2-handbook/swarm/ui.md) +per-hive dashboard and `hivectl`. → [`2-handbook/swarm/ui.md`](../2-handbook/swarm/ui.md) diff --git a/docs/2-handbook/agent-lifecycle/config-changes.md b/docs/2-handbook/agent-lifecycle/config-changes.md index e0e2f1ab..0f67f5b0 100644 --- a/docs/2-handbook/agent-lifecycle/config-changes.md +++ b/docs/2-handbook/agent-lifecycle/config-changes.md @@ -201,7 +201,7 @@ wraps it with identity + `HIVE_PORT` / `HIVE_LABEL`. ### Forge config repos The bundled `hive-forge` container runs on the swarm's forge host -(`deploy.forgejo.enable`, see [`../swarm/services.md`](../swarm/services.md)). +(`deploy.forgejo.enable`, see [`2-handbook/swarm/services.md`](../swarm/services.md)). Every agent created through the swarm has a repo in the private `agent-configs` Forgejo org, created and seeded by swarm-controller. hive-c0re pushes nothing to it, keeps no clone and reads nothing from it: forge diff --git a/docs/2-handbook/agent-lifecycle/persistence.md b/docs/2-handbook/agent-lifecycle/persistence.md index 8e5d00bc..4db31cde 100644 --- a/docs/2-handbook/agent-lifecycle/persistence.md +++ b/docs/2-handbook/agent-lifecycle/persistence.md @@ -69,7 +69,7 @@ table, and the per-agent power-intent registry: On a host whose hive-c0re once kept scheduled prompts, the file also holds `scheduled_prompts` and `scheduled_prompt_targets`. Nothing opens them; scheduled prompts live at swarm level -([`swarm/schedules.md`](../swarm/schedules.md)). They're safe to drop by +([`2-handbook/swarm/schedules.md`](../swarm/schedules.md)). They're safe to drop by hand. Retention: diff --git a/docs/2-handbook/integrations/matrix.md b/docs/2-handbook/integrations/matrix.md index 29b0bc68..bf4491c5 100644 --- a/docs/2-handbook/integrations/matrix.md +++ b/docs/2-handbook/integrations/matrix.md @@ -351,7 +351,7 @@ federation at the protocol level from first boot (`allow_federation = true`) but trusts no remote homeserver until you list it here. For a closed single-hive deployment the default empty list is correct — add peer hive domains here when connecting hives into a swarm (see -[`docs/swarm/`](../swarm/README.md)). +[`docs/2-handbook/swarm/`](../swarm/README.md)). **`maxRequestSize`** (default `20_000_000` bytes = 20 MB) — maximum size of a single matrix client request body. Matches the matrix-spec diff --git a/docs/2-handbook/swarm/README.md b/docs/2-handbook/swarm/README.md index be942f7f..5e2d0ffc 100644 --- a/docs/2-handbook/swarm/README.md +++ b/docs/2-handbook/swarm/README.md @@ -583,7 +583,7 @@ mechanism. added to the public CAs; it holds the store's `pki` root, so a peer whose certificate chains to the same root validates. A peer outside this swarm's root needs a CA-issued certificate (ACME). Federation firewall - and TLS requirements: [`integrations/matrix.md`](../integrations/matrix.md). + and TLS requirements: [`2-handbook/integrations/matrix.md`](../integrations/matrix.md). 3. **WireGuard mesh** (optional) — `deploy.wireguard.enable` reads each entry's `wireguardPublicKey`/`wireguardEndpoint`/`wireguardAddress` @@ -672,11 +672,11 @@ If both hosts are behind NAT, you need a STUN relay or a third host ## Cross-references - [`ui.md`](ui.md) — the swarm UI, the operator surface for "what hives exist" -- [`../networking/snapshot-store.md`](../../4-implementation/networking/snapshot-store.md) — the +- [`4-implementation/networking/snapshot-store.md`](../../4-implementation/networking/snapshot-store.md) — the swarm's `btrfs receive` endpoint and the `swarm.snapshotStore` option -- [`../process/conventions.md`](../../5-project/process/conventions.md) § Hive identity — +- [`5-project/process/conventions.md`](../../5-project/process/conventions.md) § Hive identity — env vars, qualified labels -- [`../integrations/matrix.md`](../integrations/matrix.md) — matrix +- [`2-handbook/integrations/matrix.md`](../integrations/matrix.md) — matrix federation, TLS cert autogeneration, firewall posture -- [`../networking/gateway.md`](../../4-implementation/networking/gateway.md) — nginx vhosts and +- [`4-implementation/networking/gateway.md`](../../4-implementation/networking/gateway.md) — nginx vhosts and the `.well-known/matrix/` autodiscovery scheme diff --git a/docs/2-handbook/swarm/services.md b/docs/2-handbook/swarm/services.md index 4a0b3a36..45f67147 100644 --- a/docs/2-handbook/swarm/services.md +++ b/docs/2-handbook/swarm/services.md @@ -439,7 +439,7 @@ doesn't gate them: that option says this host _runs_ the store, while the swarm has one either way, reached by its swarm name through the gateway. Agent-side configuration, and what a hive's own collector does, are in -[`../scheduler/observability.md`](../../4-implementation/scheduler/observability.md). +[`4-implementation/scheduler/observability.md`](../../4-implementation/scheduler/observability.md). ### CI runner @@ -452,7 +452,7 @@ It needs neither the forge nor a hive on its host. It reaches the forge at publishes to the secret store, which it reads under its own `ci-runner` leaf. On a host without the store, that leaf is the one file to copy. Registration, the container and the threat model are in -[`../scheduler/ci.md`](../../4-implementation/scheduler/ci.md). +[`4-implementation/scheduler/ci.md`](../../4-implementation/scheduler/ci.md). The runner's built-in Prometheus endpoint is on, bound to `127.0.0.1:9101` in the container's own network namespace. The container's journal forwarder diff --git a/docs/2-handbook/swarm/sso.md b/docs/2-handbook/swarm/sso.md index 57179793..d3681e17 100644 --- a/docs/2-handbook/swarm/sso.md +++ b/docs/2-handbook/swarm/sso.md @@ -16,7 +16,7 @@ authelia binds no TCP port: its listeners are unix sockets only the gateway can publishes it as `auth.` — vhost, dnsmasq record and TLS name all follow `deploy.authelia`, so there is nothing to turn on separately. (Details, including why a client hive must not declare that -vhost: [`../networking/gateway.md`](../../4-implementation/networking/gateway.md).) +vhost: [`4-implementation/networking/gateway.md`](../../4-implementation/networking/gateway.md).) **Nobody can log in until the first user exists.** authelia exits at startup on an empty user set: @@ -50,7 +50,7 @@ this password is stored nowhere — record it now the hash. It reads and writes authelia's `users.yml` directly — it's the one user store, shared with `swarm-authelia-bridge`, which creates agent identities in the same file. No restart: authelia watches it. Full -reference: [`../tools/swarmctl-cli.md`](../reference/swarmctl-cli.md). +reference: [`2-handbook/reference/swarmctl-cli.md`](../reference/swarmctl-cli.md). You can edit `users.yml` by hand, and `swarmctl` will read what you wrote. ⚠️ It rewrites the whole file on every change, so **comments and @@ -208,7 +208,7 @@ Four consequences worth stating plainly: - **A member of `admins` becomes a matrix homeserver admin** once their first matrix login has created the account: `swarm-controller` promotes them within five minutes, and never demotes. See - [`../integrations/matrix.md`](../integrations/matrix.md#operators-are-homeserver-admins). + [`2-handbook/integrations/matrix.md`](../integrations/matrix.md#operators-are-homeserver-admins). - **tuwunel re-reads its secret file on every OAuth exchange**, not only at startup, and its own sandboxing hides most paths from it. It gets the diff --git a/docs/2-handbook/swarm/ui.md b/docs/2-handbook/swarm/ui.md index ad4a0922..38eb0937 100644 --- a/docs/2-handbook/swarm/ui.md +++ b/docs/2-handbook/swarm/ui.md @@ -1089,4 +1089,4 @@ swarm's front page opens with a name mismatch. ## Cross-references - [`sso.md`](sso.md) — the authelia instance itself, and the user store. -- [`../networking/gateway.md`](../../4-implementation/networking/gateway.md) — the full vhost map and TLS modes. +- [`4-implementation/networking/gateway.md`](../../4-implementation/networking/gateway.md) — the full vhost map and TLS modes. diff --git a/docs/2-handbook/web-ui/README.md b/docs/2-handbook/web-ui/README.md index dd2967ae..1ab234a5 100644 --- a/docs/2-handbook/web-ui/README.md +++ b/docs/2-handbook/web-ui/README.md @@ -55,16 +55,16 @@ merging a config change or bumping a flake input. **Grant or revoke a permission.** Not on the hive dashboard: an agent's permissions live in the swarm. Set them with `swarmctl agent permissions`, or on the swarm UI's create-agent screen when creating the agent; see -[`process/conventions.md`](../../5-project/process/conventions.md#permissions). +[`5-project/process/conventions.md`](../../5-project/process/conventions.md#permissions). **Read an agent's logs.** Logs aren't in the hive dashboard. Every hive ships its agents', daemons' and infra containers' journals to the swarm's VictoriaLogs; read them in Grafana's **Explore** — see -[`swarm/services.md`](../swarm/services.md#logs-victorialogs). +[`2-handbook/swarm/services.md`](../swarm/services.md#logs-victorialogs). **Set up a schedule.** Scheduled prompts are swarm-level: set them with -`swarmctl schedule` ([`swarm/schedules.md`](../swarm/schedules.md)) or -in the schedules card on the swarm UI's messages tab ([`swarm/ui.md`](../swarm/ui.md)). +`swarmctl schedule` ([`2-handbook/swarm/schedules.md`](../swarm/schedules.md)) or +in the schedules card on the swarm UI's messages tab ([`2-handbook/swarm/ui.md`](../swarm/ui.md)). ## More depth diff --git a/docs/4-implementation/networking/gateway.md b/docs/4-implementation/networking/gateway.md index 16c6d445..ff5590ea 100644 --- a/docs/4-implementation/networking/gateway.md +++ b/docs/4-implementation/networking/gateway.md @@ -20,7 +20,7 @@ You rarely switch it on yourself. `gateway.enable` defaults to off, and every mo | `chat./` | fluffychat-web static | `hive-matrix.nix`, `swarm.matrix.gatewayHost != null` | | `chat./config.json` | inline JSON (FluffyChat boot config) | `hive-matrix.nix`, `swarm.matrix.gatewayHost != null` | | `/metrics` | the queue exporter's `/metrics` on loopback, behind an authelia `auth_request`; every other path, `/` included, returns `403`, so `/varz` and `/connz` are never reachable | `swarm-nats.nix`, the queue's host | -| `grafana.`, `metrics.`, `logs.`, `otel.`, `bao.` | the matching swarm service | that service's module → [`swarm/services.md`](../../2-handbook/swarm/services.md) | +| `grafana.`, `metrics.`, `logs.`, `otel.`, `bao.` | the matching swarm service | that service's module → [`2-handbook/swarm/services.md`](../../2-handbook/swarm/services.md) | A service module declares its vhost as `services.hyperhive.gateway.vhosts.`: the locations, `forceSSL` and any `extraConfig` it needs. The gateway renders it into `services.nginx.virtualHosts.` and adds the `listen` set, the certificate for that name and the [security headers](#security-headers) (ahead of the vhost's own `extraConfig`), and drops `addSSL` from a vhost that sets `forceSSL`. The eval fails for a vhost that sets `listen`, `addSSL`, `onlySSL`, `enableACME`, `useACMEHost`, `sslCertificate` or `sslCertificateKey` itself, and for any vhost declared while `gateway.enable` is false. A name with a certificate from outside the gateway's leaves (the queue's) sets `certificate = { cert; key; }` instead. `hive-gateway/vhosts.nix` declares the gateway's own catch-all (`_`) the same way, `hive-c0re/vhosts.nix` the dashboard and the hive domain, and `glue-matrix-hive-discovery.nix` adds the matrix redirect to the hive domain where the homeserver runs, and discovery there when the hive domain is the pinned server name. The catch-all sets `securityHeaders = false` because it sends no response, and the gateway renders a vhost's `default` at `mkDefault` priority. @@ -78,17 +78,17 @@ nginx obtains and renews certs via the HTTP-01 challenge on `port` (default 80); On by default, listening on `httpsPort` (default 443) beside the plain-http `port` (default 80). `httpsPort` only sets the listen port: swarm service URLs never carry a port, so clients reach them on 443. -The issuer is the **secret store's `pki` mount**, not a bare self-signed leaf. `hive-tls-resign.service` (from `hive-tls.nix`) asks the store for a gateway **leaf** through this hive's own role, presenting the hive's own store identity (`services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityCertFile` / `baoHiveIdentityKeyFile`), and writes it under `…tls.stateDir` (default `/var/lib/hive-tls`). `hive-gateway-self-signed-cert` then imports the leaf into nginx's state dir (`/var/lib/hive-gateway/tls/{cert,key}.pem`). On a host that runs no hive the import unit installs the swarm-services leaf there instead, or a throwaway self-signed pair until that leaf lands. [`swarm/ca.md`](../swarm/ca.md) has the role, the identity and what a hive without one does. +The issuer is the **secret store's `pki` mount**, not a bare self-signed leaf. `hive-tls-resign.service` (from `hive-tls.nix`) asks the store for a gateway **leaf** through this hive's own role, presenting the hive's own store identity (`services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityCertFile` / `baoHiveIdentityKeyFile`), and writes it under `…tls.stateDir` (default `/var/lib/hive-tls`). `hive-gateway-self-signed-cert` then imports the leaf into nginx's state dir (`/var/lib/hive-gateway/tls/{cert,key}.pem`). On a host that runs no hive the import unit installs the swarm-services leaf there instead, or a throwaway self-signed pair until that leaf lands. [`4-implementation/swarm/ca.md`](../swarm/ca.md) has the role, the identity and what a hive without one does. ⚠️ **Keep the import unit.** It does two jobs nginx needs: it re-modes the key to `0640 root:nginx` (nginx's pre-start `nginx -t` runs as the nginx user and fails on the source's `0600 root:root` key), and it puts a file at **every cert path the config names**, because nginx refuses a config naming a missing cert file and one missing leaf would take down every vhost, not just one. Where the gateway waits for the swarm-services leaf, a missing one fails the import unit, naming `swarm-services-cert.service`, and nginx stays down until that unit issues it. Where it doesn't — a host fronting no swarm name, or only the store's UI, which starts its passthrough with the store sealed — the hive leaf stands in until the services leaf lands, or on a host that runs no hive a throwaway self-signed pair. **Why an issuer, not a bare leaf**: a bare self-signed leaf is its own trust anchor, so every regeneration is a new anchor every consumer must re-trust, and an agent's build sets its trust store once, before any leaf exists. Agents and federation peers trust the store's root once; leaf rotation never breaks them. -**What consumers trust**: `trust-bundle.pem` in the same state dir. It carries the store's `pki` root ([`swarm/ca.md`](../swarm/ca.md#the-trust-bundle)). nginx serves the leaf alone, since its issuer is a self-signed root. The CI and forge containers and federating peers read the bundle. Agents fetch the root from the store themselves ([`swarm/ca.md`](../swarm/ca.md#distributing-the-root)). +**What consumers trust**: `trust-bundle.pem` in the same state dir. It carries the store's `pki` root ([`4-implementation/swarm/ca.md`](../swarm/ca.md#the-trust-bundle)). nginx serves the leaf alone, since its issuer is a self-signed root. The CI and forge containers and federating peers read the bundle. Agents fetch the root from the store themselves ([`4-implementation/swarm/ca.md`](../swarm/ca.md#distributing-the-root)). **Why on by default**: matrix-dart-sdk (FluffyChat's SDK) fetches `https:///.well-known/matrix/client` and never falls back to plain http, so without TLS the browser client can't bootstrap. -**Cert shape**: the leaf's CN is the bare hive domain; its SANs are `` and `*.`. The hive's role allows nothing outside ``, so a swarm-service name can't go on this leaf. Those names get the swarm-services leaf instead ([`swarm/ca.md`](../swarm/ca.md)). +**Cert shape**: the leaf's CN is the bare hive domain; its SANs are `` and `*.`. The hive's role allows nothing outside ``, so a swarm-service name can't go on this leaf. Those names get the swarm-services leaf instead ([`4-implementation/swarm/ca.md`](../swarm/ca.md)). **Rotation**: `hive-tls-resign.service` runs at boot, on every deploy and once a day, and asks the store for a new leaf when the current one is missing, past half its 720-hour lifetime, doesn't cover the configured names, doesn't match its key, or doesn't chain to the store's root. A leaf already on disk lets the gateway start while the store can't answer; a failed renewal leaves it in place. To force a rotation, delete `gateway.pem` under the state dir and restart the unit; it re-imports the leaf and reloads `nginx` itself. @@ -116,7 +116,7 @@ Give the gateway the real cert (`tls.certDir` or `tls.acme`) so it serves proper ## Dashboard access -The dashboard answers on `.hives.` (`deploy.hive-controller.dashboardDomain`, derived from the hive name and `swarm.domain`), behind an authelia `auth_request`. Log in with your authelia account; only accounts in the `admins` group get in, the same rule as the swarm UI. Add one with `swarmctl user add --group admins` ([`swarm/sso.md`](../../2-handbook/swarm/sso.md)). +The dashboard answers on `.hives.` (`deploy.hive-controller.dashboardDomain`, derived from the hive name and `swarm.domain`), behind an authelia `auth_request`. Log in with your authelia account; only accounts in the `admins` group get in, the same rule as the swarm UI. Add one with `swarmctl user add --group admins` ([`2-handbook/swarm/sso.md`](../../2-handbook/swarm/sso.md)). The name sits under the swarm domain so authelia's session cookie reaches it, whatever the hive's own domain is. Any path on the hive domain other than the matrix routes redirects there, so old bookmarks still land. @@ -146,7 +146,7 @@ It shares the host network namespace (`privateNetwork = false`): the container i State lives at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` and survives restarts and reboots; destroy the container to wipe it. -Only the swarm's forge host runs it (`services.hyperhive.deploy.forgejo.enable`, see [`swarm/services.md`](../../2-handbook/swarm/services.md)). Every other hive reaches that host's gateway by `forge.`. +Only the swarm's forge host runs it (`services.hyperhive.deploy.forgejo.enable`, see [`2-handbook/swarm/services.md`](../../2-handbook/swarm/services.md)). Every other hive reaches that host's gateway by `forge.`. ### Network and port configuration diff --git a/docs/4-implementation/networking/network.md b/docs/4-implementation/networking/network.md index f80b8612..9ae95ae8 100644 --- a/docs/4-implementation/networking/network.md +++ b/docs/4-implementation/networking/network.md @@ -74,7 +74,7 @@ The flows, end to end: the host forwards + masquerades out its uplink. - **Swarm** — peer hives connect over the `wg-hive` WireGuard mesh and reach each other's gateway/forge across it - ([`docs/swarm/`](../../2-handbook/swarm/README.md)). + ([`docs/2-handbook/swarm/`](../../2-handbook/swarm/README.md)). - **Control plane (no network)** — per-agent broker socket `/run/hive/mcp.sock`, privileged helper `/run/hive/priv.sock`, operator admin `/run/hyperhive/host.sock`, and the per-agent UI @@ -105,7 +105,7 @@ The hive domain (`services.hyperhive.domain`, which the resolver answers for) comes from this hive's entry in the swarm directory: `swarm.hives..domain`, default `.`. Eval fails until `swarm.domain` and that entry exist -([`swarm/README.md`](../../2-handbook/swarm/README.md) § Hive identity config). +([`2-handbook/swarm/README.md`](../../2-handbook/swarm/README.md) § Hive identity config). ## Bridge addressing diff --git a/docs/4-implementation/scheduler/jobq.md b/docs/4-implementation/scheduler/jobq.md index 3b9104a9..9e0e0f95 100644 --- a/docs/4-implementation/scheduler/jobq.md +++ b/docs/4-implementation/scheduler/jobq.md @@ -34,7 +34,7 @@ swarm controller and hive-c0re each build their own graph on it. Two views, one per graph, drawn by the same component: the swarm UI's `/jobs` page shows the swarm controller's graph, and the hive dashboard's **R3BU1LD QU3U3** tab (see -[`web-ui/dashboard.md`](../../2-handbook/web-ui/dashboard.md)) shows that hive's. Each +[`2-handbook/web-ui/dashboard.md`](../../2-handbook/web-ui/dashboard.md)) shows that hive's. Each **row** is one job; the rows nested under it are that job's steps, in order (occasionally a couple run side by side). A step shows one of: diff --git a/docs/4-implementation/scheduler/observability.md b/docs/4-implementation/scheduler/observability.md index e20ebf7e..dd193ba5 100644 --- a/docs/4-implementation/scheduler/observability.md +++ b/docs/4-implementation/scheduler/observability.md @@ -40,7 +40,7 @@ switch on: there is no per-hive or per-agent opt-in. `upstream.endpoint` is where telemetry ends up after it leaves the swarm — optional, because the swarm's own metrics store (`deploy.victoriametrics`) is a destination in its own right. With both, telemetry goes to both. See -[`swarm/services.md`](../../2-handbook/swarm/services.md#metrics-victoriametrics--grafana). +[`2-handbook/swarm/services.md`](../../2-handbook/swarm/services.md#metrics-victoriametrics--grafana). **Telemetry leaves a hive exactly one way: through the collector that runs on the host.** Agents never talk to `upstream.endpoint` themselves — @@ -50,7 +50,7 @@ can reach. They dial it as every hive and every swarm, which each hive's own dnsmasq answers with its bridge IP, so an agent's build carries no hive-specific address and no swarm domain. The otel module opens that port on the bridge itself. That collector forwards to the swarm's -([`swarm/services.md`](../../2-handbook/swarm/services.md#telemetry-collector-otel)), the +([`2-handbook/swarm/services.md`](../../2-handbook/swarm/services.md#telemetry-collector-otel)), the single process holding the upstream credential and the only writer to the swarm's stores. No agent holds a copy, and neither does the hive. @@ -193,7 +193,7 @@ a build error naming the reason rather than telemetry silently going nowhere. Agent containers reach the host only on ports 80 and 443 (plus DNS). The collector port needs nothing from you: the hive collector opens it on the bridge. To let agents reach some other host-local service of your own → -[`networking/network.md`](../networking/network.md#reaching-host-services-exposehostports). +[`4-implementation/networking/network.md`](../networking/network.md#reaching-host-services-exposehostports). ## Options reference diff --git a/docs/4-implementation/swarm/bao.md b/docs/4-implementation/swarm/bao.md index e72fb868..e246aa0b 100644 --- a/docs/4-implementation/swarm/bao.md +++ b/docs/4-implementation/swarm/bao.md @@ -7,7 +7,7 @@ principal's own certificate identity. What lives in it and who reads what: comes up, who may write its grants, and how it's sealed and reached. The operator steps (init, the one-time granter bootstrap) are in -[`../getting-started/setup.md`](../../1-getting-started/setup.md#1--secret-store); +[`1-getting-started/setup.md`](../../1-getting-started/setup.md#1--secret-store); this page is the why behind them. diff --git a/docs/4-implementation/turn-loop/claude-invocation.md b/docs/4-implementation/turn-loop/claude-invocation.md index 72a8a635..7636aa4f 100644 --- a/docs/4-implementation/turn-loop/claude-invocation.md +++ b/docs/4-implementation/turn-loop/claude-invocation.md @@ -57,7 +57,7 @@ unset). The swarm changes the model at runtime, not the web terminal: a model or effort the swarm sets for the agent replaces the `Bus` value from the next turn, and the harness doesn't persist it; clearing it goes back to the local value → -[`swarm/inference.md`](../swarm/inference.md). +[`4-implementation/swarm/inference.md`](../swarm/inference.md). `harness_state::context_window_tokens(model)` looks up context-window size per-model. Resolution order (first diff --git a/hive-agent/README.md b/hive-agent/README.md index 4273537c..7ba0eedc 100644 --- a/hive-agent/README.md +++ b/hive-agent/README.md @@ -16,7 +16,7 @@ understand or change: what happens between a message landing in the inbox and the agent's reply, how the harness bootstraps login/auth, how it serves the per-agent web UI, or how turn/event stats get recorded. Architecture detail lives in -[`docs/turn-loop/`](../docs/4-implementation/turn-loop/README.md); this README is just the +[`docs/4-implementation/turn-loop/`](../docs/4-implementation/turn-loop/README.md); this README is just the map of the module tree. ## Shape @@ -49,5 +49,5 @@ map of the module tree. Siblings: **`hive-agent-mcp`** (the MCP server this loop points the agent at every turn) and **`hive-runtime`** (the library a turn runs through). -[`docs/turn-loop/::Harness binary shape`](../docs/4-implementation/turn-loop/README.md#harness-binary-shape) +[`docs/4-implementation/turn-loop/::Harness binary shape`](../docs/4-implementation/turn-loop/README.md#harness-binary-shape) covers all three together.