hyperhive/swarm-matrix-minter
Repository files (latest commit first)
Filename Latest commit message Latest commit date
atlas fb9c6122df matrix: name the credential after the account it authenticates as
The store path and every identifier around it called this an admin
token. It is not one: of ~15 hive-c0re call sites only two need
homeserver admin, and the homeserver no longer promotes the account at
boot, so the name overstated both what the credential is and what it may
do.

Renaming it to the account was not enough either. "The `@hive:` token"
reads as the token of a hive user, and no such user is provisioned —
`@hive:<server_name>` is the appservice registration's own
`sender_localpart`, an account the homeserver creates for itself when it
loads the registration.

So it is the **sender token**: the matrix appservice sender account's
access token, at `swarm/services/matrix/sender-token`. The name says
what it authenticates as rather than what it may do, which is the part
that was wrong.

The path has one constructor, and the bao grant, the grant assertion and
three unit tests pin its literal independently — so a half-finished
rename fails a check rather than leaving the minter and its readers
disagreeing at runtime. `tracing` messages are renamed with the code, so
the journal reads the way the source does.

The host-side file keeps its name (`matrix/access-token`): it carried no
admin framing, and renaming it would orphan the file on every deployed
hive for nothing.

`docs/tools/hivectl-cli.md` is regenerated from the clap tree.
2026-09-20 22:07:16 +02:00
..
src matrix: name the credential after the account it authenticates as 2026-09-20 22:07:16 +02:00
Cargo.toml matrix: mint the appservice sender token in the matrix container 2026-09-20 22:07:16 +02:00
README.md matrix: name the credential after the account it authenticates as 2026-09-20 22:07:16 +02:00

swarm-matrix-minter

A boot-time oneshot that runs inside containers.hive-matrix, beside the homeserver, and puts the appservice sender account's access token into the swarm's secret store under an identity of its own.

Why it lives in the matrix container

The credential it mints 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 @hive: 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 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.