feat(#2015): require services.hyperhive.domain (assertion) when hyperhive enabled

This commit is contained in:
damocles 2026-06-26 20:29:26 +02:00 committed by mara
commit 3d39cc00d0

View file

@ -128,9 +128,11 @@ in
options.services.hyperhive.enable = lib.mkEnableOption "hyperhive the agent swarm coordinator"; options.services.hyperhive.enable = lib.mkEnableOption "hyperhive the agent swarm coordinator";
# Canonical hive DNS domain shared by every subsystem that needs a # Canonical hive DNS domain shared by every subsystem that needs a
# stable hostname. Nullable + default null so existing configs # stable hostname. Typed nullOr (default null) so the option always
# evaluate unchanged; subsystems that need it (matrix) assert # exists, but it's REQUIRED whenever hyperhive is enabled — a config
# non-null in their own config block. Full identity-surface # assertion (see the `config` block) fails eval when it's unset, since
# matrix bakes it in on first boot and the gateway/forge/agent URLs all
# derive from it (no safe default; #2015). Full identity-surface
# context (HYPERHIVE_HIVE_DOMAIN / HIVE_NAME / SWARM_NAME env-var # context (HYPERHIVE_HIVE_DOMAIN / HIVE_NAME / SWARM_NAME env-var
# chain → identity.rs → claude prompt): docs/conventions.md:: # chain → identity.rs → claude prompt): docs/conventions.md::
# Hive identity (label + domain + display names). # Hive identity (label + domain + display names).
@ -143,9 +145,10 @@ in
stable name (currently: `services.hyperhive.matrix.serverName` stable name (currently: `services.hyperhive.matrix.serverName`
derives from this, defaulting to derives from this, defaulting to
`matrix.''${services.hyperhive.domain}` when `serverName` is `matrix.''${services.hyperhive.domain}` when `serverName` is
null). No default subsystems that opt to require it assert null). **Required** when `services.hyperhive.enable` eval fails
non-null in their own config and fail eval with a helpful with a helpful message if it's unset (it's baked into matrix on
message if it's missing. Exposed to agents as first boot and drives the gateway/forge/agent URLs, with no safe
default; changing it later is destructive). Exposed to agents as
`HYPERHIVE_HIVE_DOMAIN`; consumed by `HYPERHIVE_HIVE_DOMAIN`; consumed by
`hive-ag3nt::identity::hive_domain()` for `<name>@<domain>` `hive-ag3nt::identity::hive_domain()` for `<name>@<domain>`
qualified labels. qualified labels.
@ -828,8 +831,28 @@ in
config.services.hyperhive.swarm.wireguard.listenPort config.services.hyperhive.swarm.wireguard.listenPort
]; ];
assertions = assertions = [
lib.optionals config.services.hyperhive.swarm.wireguard.enable [ {
# `domain` has no safe default: it's baked into the matrix server
# (tuwunnel) on first boot and drives the gateway/forge/agent URLs.
# Under mandatory network isolation agents can only reach the forge
# via `forge.<domain>` on the bridge — with no domain there's no
# reachable name (see #2011). Changing it later is destructive
# (deletes Matrix history), so it must be set before first boot.
assertion = config.services.hyperhive.domain != null;
message = ''
services.hyperhive.domain must be set (e.g. "darkest.space").
It's baked into the matrix server on first boot and into the
gateway / forge / agent URLs, so hyperhive needs a stable domain
and there is no safe default. Agents reach the forge via
forge.<domain> on the bridge network, so without it the forge is
unreachable from containers. Changing the domain after first boot
is destructive (deletes Matrix history) pick it before initial
setup. See docs/gateway.md and docs/matrix.md.
'';
}
]
++ lib.optionals config.services.hyperhive.swarm.wireguard.enable [
{ {
assertion = config.services.hyperhive.swarm.wireguard.privateKeyFile != null; assertion = config.services.hyperhive.swarm.wireguard.privateKeyFile != null;
message = '' message = ''