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";
# Canonical hive DNS domain shared by every subsystem that needs a
# stable hostname. Nullable + default null so existing configs
# evaluate unchanged; subsystems that need it (matrix) assert
# non-null in their own config block. Full identity-surface
# stable hostname. Typed nullOr (default null) so the option always
# exists, but it's REQUIRED whenever hyperhive is enabled — a config
# 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
# chain → identity.rs → claude prompt): docs/conventions.md::
# Hive identity (label + domain + display names).
@ -143,9 +145,10 @@ in
stable name (currently: `services.hyperhive.matrix.serverName`
derives from this, defaulting to
`matrix.''${services.hyperhive.domain}` when `serverName` is
null). No default subsystems that opt to require it assert
non-null in their own config and fail eval with a helpful
message if it's missing. Exposed to agents as
null). **Required** when `services.hyperhive.enable` eval fails
with a helpful message if it's unset (it's baked into matrix on
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
`hive-ag3nt::identity::hive_domain()` for `<name>@<domain>`
qualified labels.
@ -828,31 +831,51 @@ in
config.services.hyperhive.swarm.wireguard.listenPort
];
assertions =
lib.optionals config.services.hyperhive.swarm.wireguard.enable [
{
assertion = config.services.hyperhive.swarm.wireguard.privateKeyFile != null;
message = ''
services.hyperhive.swarm.wireguard.enable requires
services.hyperhive.swarm.wireguard.privateKeyFile to be set.
Generate a key: wg genkey > /etc/wireguard/hive.key
'';
}
{
assertion = config.services.hyperhive.swarm.wireguard.address != "";
message = ''
services.hyperhive.swarm.wireguard.enable requires
services.hyperhive.swarm.wireguard.address to be set
(e.g. "10.100.0.1/24").
'';
}
]
++ lib.optionals config.services.hyperhive.otel.enable [
{
assertion = config.services.hyperhive.otel.endpoint != "";
message = "services.hyperhive.otel.enable is true but services.hyperhive.otel.endpoint is empty.";
}
];
assertions = [
{
# `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;
message = ''
services.hyperhive.swarm.wireguard.enable requires
services.hyperhive.swarm.wireguard.privateKeyFile to be set.
Generate a key: wg genkey > /etc/wireguard/hive.key
'';
}
{
assertion = config.services.hyperhive.swarm.wireguard.address != "";
message = ''
services.hyperhive.swarm.wireguard.enable requires
services.hyperhive.swarm.wireguard.address to be set
(e.g. "10.100.0.1/24").
'';
}
]
++ lib.optionals config.services.hyperhive.otel.enable [
{
assertion = config.services.hyperhive.otel.endpoint != "";
message = "services.hyperhive.otel.enable is true but services.hyperhive.otel.endpoint is empty.";
}
];
systemd.services.hive-c0re = {
description = "hyperhive coordinator daemon";