# swarm-matrix-ctl The rust that runs **inside `containers.hive-matrix`**, beside the homeserver. One binary with subcommands rather than one binary per job. Running code in that container is not free: it needs its own store identity, its own cert role and its own bind mounts, and every one of those is per-_container_, not per-task. A second single-purpose crate would have had to duplicate that plumbing to add one action, so the next thing that has to run in here is a **verb**, not a new crate. ## Verbs ### `mint` Puts the appservice sender account's access token into the swarm's secret store, under an identity of its own. A boot-time oneshot. Configured entirely by the `MATRIX_MINT_*` environment the unit sets — no flags. A systemd `Environment=` block is what a nix module can render; a command line full of paths is not. The prefix is scoped to the verb rather than to the binary so the next verb brings its own, instead of widening a shared one nobody can then narrow. ## Why this lives in the matrix container The credential `mint` writes is authorised by the appservice `as_token`, and the container already holds that: `nix/host-modules/hive-matrix.nix` bind-mounts the rendered appservice registration into it read-only, because that is how tuwunel itself is handed the registration. Minting anywhere else would mean copying the `as_token` to a second holder — and the point of this component is that the hive stops being one. It is not the swarm controller for the same reason, plus a structural one: a homeserver has exactly **one** appservice registration and so one sender account, and a swarm runs one homeserver, so "mint it once" needs no lock, no lease and no trigger surface — it is a property of the thing being minted. ## Idempotency The **store** is the key, not the homeserver. A `mint` run reads `swarm/services/matrix/sender-token` first and returns without touching the homeserver when something is already there. Only an empty path reaches the mint ladder: 1. `POST /_matrix/client/v3/register` with `"type": "m.login.application_service"` — one round trip, no UIAA. 2. `M_USER_IN_USE` (the expected arm on a homeserver that has already loaded the registration, since the account is the appservice's own `sender_localpart`) → `POST /_matrix/client/v3/login` as the appservice, same pinned `device_id`, so the old device is replaced rather than duplicated. 3. Write the result to the store. A crash between the homeserver call and the store write is recoverable: the next run takes arm 2. ## 🩸 A secret is a path, never a value Nothing here logs, prints or interpolates a token. The mint ladder's errors are built from the homeserver's _status_ and its `errcode`, never its body, because a `/login` response body is an access token. The one identifier this binary logs is the store path it wrote.