matrix: provision per-agent accounts on startup via UIAA registration (#548 phase 2)

This commit is contained in:
damocles 2026-05-29 10:46:24 +02:00 committed by Mara
commit 50ceb929d7
4 changed files with 397 additions and 7 deletions

View file

@ -29,9 +29,21 @@ in
#
# Initial rollout (#548): federation enabled (needed for multi-hive
# swarms; trusted_servers starts empty so no actual federation traffic
# leaves until peers are explicitly listed), registration via admin
# API only, e2ee disabled per operator call (tracked for follow-up at
# #551).
# leaves until peers are explicitly listed), registration enabled via
# a `registration_token_file` known only to hive-c0re (so agents can't
# self-register without going through the coordinator), e2ee disabled
# per operator call (tracked for follow-up at #551).
#
# Provisioning model (matches `nix/modules/hive-forge.nix` shape):
# hive-c0re generates a 32-byte random `registration_token` on first
# boot, writes it to `/var/lib/hyperhive/matrix-register-token` (mode
# 0600, root-only), and bind-mounts that file read-only into the
# tuwunel container at the same path so tuwunel can read it via
# `registration_token_file`. hive-c0re then uses the token to register
# each agent account via the matrix-spec UIAA registration flow, and
# persists the returned `access_token` to `<agent-state>/matrix-token`
# so the agent's matrix MCP client can authenticate without ever
# seeing the shared registration token.
options.hyperhive.matrix = {
enable = lib.mkOption {
@ -127,6 +139,22 @@ in
media uploads + the upstream tuwunel default.
'';
};
registrationTokenFile = lib.mkOption {
type = lib.types.path;
default = "/var/lib/hyperhive/matrix-register-token";
description = ''
Host path to a file containing the matrix registration token
tuwunel reads to authorise new-account creation. The token is
generated automatically by `hive-c0re` on first boot (32-byte
random hex, mode 0600) and is bind-mounted read-only into the
tuwunel container at the same path. Agents never see this
token hive-c0re uses it to provision per-agent accounts
and the agent only receives the resulting `access_token`.
Override only when integrating with externally-managed
registration tokens.
'';
};
};
config = lib.mkIf cfg.enable {
@ -160,6 +188,16 @@ in
# host-side services, no port-forward plumbing, and agent
# containers (also host netns) reach it via plain `localhost`.
privateNetwork = false;
# Read-only bind of the host-managed registration token so
# tuwunel can resolve `registration_token_file` to a real
# file inside the container. The host path doesn't need to
# exist at eval time (the file is generated by hive-c0re's
# `matrix::ensure_register_token` on first boot); nspawn will
# create the bind mount on container start either way.
bindMounts.${cfg.registrationTokenFile} = {
hostPath = cfg.registrationTokenFile;
isReadOnly = true;
};
config =
{ ... }:
{
@ -181,10 +219,13 @@ in
# keeps it effectively closed until peers are listed.
allow_federation = true;
trusted_servers = cfg.trustedServers;
# Registration off — operator seeds agent accounts via
# the tuwunel admin API (mirrors the forge pattern;
# see `hive-c0re/src/matrix.rs` once #548 PR 2 lands).
allow_registration = false;
# Token-gated registration: hive-c0re holds the token,
# agents never see it. allow_registration must be true
# for the token flow to engage; the absent
# `yes_i_am_very_very_sure_…_open_registration_…` flag
# keeps the server closed to anyone without the token.
allow_registration = true;
registration_token_file = toString cfg.registrationTokenFile;
# E2EE disabled in initial rollout per operator call
# (#548) — re-enabling tracked at #551.
allow_encryption = false;