Watch
0
0
Fork
You've already forked hyperhive
0

docs: agents' matrix accounts come from the swarm

The integration, tool, persistence and setup pages described hive-c0re
minting each agent's token into its state dir. They now describe the
swarm's appservice, its admin sender, the controller's mint and pass, the
daemon's store read and re-start timer, and the two new credential rows.
ruth's matrix account comes from the same pass once she holds the store
identity the setup page already has the operator mint.
This commit is contained in:
atlas 2026-09-25 02:12:26 +02:00 • committed by mara
commit 85ba45b2de
5 changed files with 90 additions and 52 deletions

View file

@ -129,31 +129,52 @@ a token.
the bind-mount path. It reads only `.yaml`/`.yml` entries from there,
so the sibling credentials are invisible to it. The `.yaml` suffix on
the credential id is what makes this work.
5. **hive-c0re** reads the appservice token and creates each account with
one `POST /register` typed `m.login.application_service`, persisting
the returned `access_token` to `<agent-state>/matrix-token`. It never
mints the token itself: the value has to be the one the rendered
registration names, and only the nix side writes that.
6. **An account that exists but has lost its token file** is re-tokened
by an appservice `POST /login` — no password and no admin rights
involved. A stored-password login and an admin-room password reset
remain behind that, for accounts created before the appservice existed
or named outside its namespace.
7. **hive-c0re restarts `hive-matrix-daemon`** for the agent
immediately after writing the token so the daemon picks up the
new credential without waiting for a full container restart. If
the restart fails (for example daemon not yet running on first boot)
hive-c0re logs the error as a warning and the `.path`-trigger sibling
(`hive-matrix-daemon.path` watching for `matrix-token` appearance)
brings the daemon up on the same boot cycle anyway.
5. **hive-c0re** reads the appservice token and creates its own
`@hive-<hive>:` account, and the accounts an operator asks for with
`hivectl matrix create-user`. It never mints the token itself: the value
has to be the one the rendered registration names, and only the nix
side writes that.
6. **Agents' accounts aren't this hive's.** `swarm-controller` creates each
one with the swarm's own appservice token (next section), stores its
token at `swarm/agents/<agent>/matrix/main`, and the agent's
`hive-matrix-daemon` reads it from there as the agent itself.
### The swarm's appservice, and its admin sender
A second registration sits beside the hive's: id `swarm`, sender `@swarm`,
the same non-exclusive namespace. It's the swarm's identity on the
homeserver, and `swarm-controller` creates every agent's account with it.
tuwunel loads every `.yaml` in `appservice_dir` and refuses only a
duplicate `id` or `as_token`, so the two overlapping namespaces coexist.
`swarm-matrix-ctl appservice render` mints its tokens inside the
`hive-matrix` container, before tuwunel starts, and renders the
registration tuwunel loads as a second credential. `appservice publish`
then writes its `as_token` to
`swarm/controller/swarm-controller/matrix/appservice-token`. No hive's
policy reaches that path: only matrix-ctl (which writes it) and
`swarm-controller` (which reads it) hold a grant to it.
`@swarm` is the **one** account the homeserver promotes to admin at boot
(`admin_execute`). Only those two principals read its token, which is
the difference from the hive sender below: every hive reads its own
sender's token. `swarm` is a reserved name, so nothing can create an agent
as this account.
`swarm-controller` mints each agent's account with the device id
`hyperhive-<agent>`, and a login on that device replaces its token. The controller therefore reads
the stored token back with `whoami` every five minutes and re-mints only
when it's missing, unknown to the homeserver, or someone else's. An
agent's daemon picks a re-minted token up on its next start, and a timer
restarts it while it's down.
### The appservice's sender account, and why it isn't an admin
`@hive-<hive>:<server_name>` is the appservice's own `sender_localpart`,
which the homeserver creates itself when it loads the registration — on a
zero-user database, inside startup, before the HTTP listener accepts
anything. It's an **ordinary account**: nothing promotes it, and the
homeserver runs no `admin_execute` for it.
anything. It's an **ordinary account**: nothing promotes it; the
homeserver's `admin_execute` promotes only `@swarm`.
**One account per hive.** The localpart carries the hive's name, so a swarm
whose hives share a homeserver gives each of them its own identity: the
@ -185,10 +206,8 @@ when its sender is already an admin. They're swarm-level operations,
rehomed to the swarm tier rather than granted here; from the hive,
`@hive-<hive>:` has no admin sender to make that call with, so both get the
admin room's refusal rather than an over-privileged credential that
every other call site would also carry. The one hive-side path that
depends on them is the automatic password recovery for an agent that
has lost its stored password — the admin-sender limitation doesn't
touch the ordinary appservice re-login above.
every other call site would also carry. The swarm's own sender is the
admin they need; moving them there is separate work.
<details><summary>Upgrading a hive that shared one sender account with every other hive</summary>
@ -239,9 +258,6 @@ restarts, so the first boot after the switch already has both halves.
device that minted it; removing the registration token touches no
device, no account and no session. `login_with_password` stays on, so
the password fallback is still there too.
- **The per-agent sweep honours existing token files.** It skips any
agent that already has a `matrix-token`, so it re-registers no account
and displaces no session.
- **The sender account may already be an admin** on such a hive (it won the
first-user grant when the hive was new). Nothing here demotes it; the
homeserver no longer promotes it, so a hive built fresh has an