fix(nix): keep the domain-derived defaults total

The required-domain assertion in hive-network.nix could not be reached:
`forge.<domain>` and `matrix.<domain>` are evaluated while the
assertion list is, so an unset domain threw `cannot coerce null to a
string` naming one of those options instead of printing the message
that says which option to set.

Both defaults now fall back to a name under the reserved `.invalid`
TLD, which the assertion refuses to let out the door.
This commit is contained in:
atlas 2026-08-05 14:47:26 +02:00 committed by mara
commit 747f405c6f
4 changed files with 21 additions and 6 deletions

View file

@ -38,10 +38,10 @@ rename — a hive that pins `domain` explicitly keeps exactly the value it
has today, which is the point: re-rooting where a value *comes from*
must not reinterpret the values already deployed.
`hiveName` and
`swarm.name` are purely display — they surface in the dashboard chrome
header and per-agent system prompts. Federated hives at different
domains can share a `swarm.name`; that it sits under `swarm` and
`hiveName` and `swarm.name` are purely display — they surface in the
dashboard chrome header and per-agent system prompts. Federated hives
at different domains can share a `swarm.name`; that it sits under
`swarm` and
`hiveName` does not is the whole distinction — one names this hive, the
other names the group it belongs to.

View file

@ -120,7 +120,9 @@ in
domain = lib.mkOption {
type = lib.types.str;
default = "forge.${hyperhiveDomain}";
# Total on a null hive domain so the required-domain assertion in
# hive-network.nix is the thing that fires; see the comment there.
default = if hyperhiveDomain == null then "forge.invalid" else "forge.${hyperhiveDomain}";
defaultText = lib.literalExpression ''"forge.''${services.hyperhive.domain}"'';
example = "git.example.com";
description = ''

View file

@ -190,7 +190,9 @@ in
gatewayHost = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "matrix.${hyperhiveDomain}";
# Total on a null hive domain so the required-domain assertion in
# hive-network.nix is the thing that fires; see the comment there.
default = if hyperhiveDomain == null then "matrix.invalid" else "matrix.${hyperhiveDomain}";
defaultText = lib.literalExpression ''"matrix.''${services.hyperhive.domain}"'';
example = "matrix.example.com";
description = ''

View file

@ -153,6 +153,17 @@ in
# hyperhive is enabled: the shared-netns mode was removed, so there
# is one mode (private netns behind the bridge).
(lib.mkIf config.services.hyperhive.enable {
# This message is only useful if an operator can actually reach
# it, and an assertion competes with every eager default that
# reads the value it guards: option defaults that interpolate the
# domain (`forge.<domain>`, `matrix.<domain>`) throw while the
# assertion list is being evaluated, so the operator sees
# `cannot coerce null to a string` naming an unrelated option
# instead of the sentence below. Those defaults therefore stay
# total, falling back to a name under the reserved `.invalid` TLD
# (RFC 2606) — a value this assertion then refuses to let out the
# door, and one that fails loudly at resolution rather than
# quietly working if it somehow did.
assertions = [
{
assertion = config.services.hyperhive.domain != null;