Watch
0
0
Fork
You've already forked hyperhive
0

matrix: swarm-controller is the only minter

Every hive is in a swarm and every swarm runs matrix, so every swarm has a
swarm-controller, and since #4810 its hive_sender pass mints each hive's
@hive-<hive>: sender token into the store every five minutes. The two
other minters of that token go:

- swarm-matrix-ctl mint: the systemd.services.swarm-matrix-ctl unit in the
  hive-matrix container, Command::Mint and src/mint.rs. The binary, its
  appservice render/publish verbs, ctlPackage, ctlActive and the ctl cert
  role stay. bao-matrix-reader's checks on the deleted unit are removed;
  the leaf-identity and no-token-in-env checks now look at
  swarm-matrix-appservice-publish, which runs under the same identity.
- the hive-side mint ladder in hive-c0re's ensure_hive_user
  (register/appservice-login/password-login with the local as_token), with
  read_appservice_token, paths::matrix_appservice_token and the helpers
  only it used. ensure_hive_user now takes the store's token, keeps the
  file when the store has none or can't be reached, and fails otherwise.
- hivectl matrix sync-admin: the verb, HostRequest::MatrixSyncAdmin and
  handle_matrix_sync_admin. The periodic MatrixSweep (ensure_all) is
  unchanged apart from no longer reading the local as_token.

This removes the double-mint race #4810's review flagged: two minters
logging in on one pinned device could leave a dead token in the store
until the next pass.

Closes #4813
Closes #4814
This commit is contained in:
atlas 2026-09-29 23:49:57 +02:00 • committed by mara
commit ddb7d7196d
22 changed files with 187 additions and 1162 deletions

View file

@ -1,21 +1,15 @@
//! Each hive's sender account, `@hive-<hive>:`, on the swarm's homeserver:
//! created here with the **swarm's** appservice token and stored at
//! `swarm/hives/<hive>/matrix/sender-token`, where hive-c0re's matrix sweep
//! reads it under the hive's own store identity. A hive whose homeserver runs
//! elsewhere holds no appservice token, so this is its only sender token.
//! reads it under the hive's own store identity.
//!
//! Runs for every hive in the directory, local or remote, and decides the
//! same way [`super::agent_token`] does: a stored token that `whoami`
//! confirms as `@hive-<hive>:` is kept, so this writes only when the path is
//! empty or its token is dead.
//!
//! ⚠️ `swarm-matrix-ctl mint` also writes this path for the hive whose host
//! runs the homeserver, and skips when it is non-empty. Both log in on the
//! same pinned device, so if both find it empty at once, one of the two
//! tokens is dead on arrival. Whichever of them lands in the store, the next
//! [`RECONCILE_INTERVAL`] pass either keeps it (live) or re-mints it
//! (`Revoked`), and matrix-ctl never writes a non-empty path — so the store
//! converges on one live token, and the hive's sweep takes whatever it holds.
//! This is the only writer of that path: hive-c0re never mints, it takes
//! whatever the store holds.
use std::sync::Arc;
@ -158,7 +152,7 @@ mod tests {
#[test]
fn a_dead_token_mints() {
// What the loser of a simultaneous mint with matrix-ctl leaves behind.
// A token the homeserver revoked, or a device a manual login replaced.
assert_eq!(
classify_hive("pr1ma", &Probe::Whoami(Whoami::UnknownToken)),
Decision::Mint(MintReason::Revoked)
@ -191,8 +185,8 @@ mod tests {
#[test]
fn the_published_path_is_the_one_the_hive_reads() {
// hive-c0re's `stored_sender_token` and `swarm-matrix-ctl mint` both
// resolve this path; the literal is what the bao grant names.
// hive-c0re's `stored_sender_token` resolves this path; the literal is
// what the bao grant names.
assert_eq!(
matrix::sender_token_path("pr1ma").expect("a plain name is legal"),
"swarm/hives/pr1ma/matrix/sender-token"