feat(nix): require swarm.domain and hiveName

Neither has a fallback worth having: a guessed swarm domain is a wrong
hostname that evaluates cleanly and deploys, which is worse than an
eval failure naming the one line an operator has to write. Upgrading
past this sets both, once.

Requiring them also makes the hive domain fully derived rather than
merely derivable — `<hiveName>.<swarm.domain>` now always resolves, so
an operator writes the swarm's address and this hive's label and never
writes the hive domain at all.

`hiveName` stops being display-only in the process: it is the leftmost
label of the domain the hive is addressed by, which the option text and
docs now say.

Each of the three required options asserts separately, so a missing one
names itself. A missing `swarm.domain` legitimately fails two of them —
its own, and `domain`, which can no longer derive — and nix reports all
failing assertions together, so the operator sees the whole set rather
than one at a time.
This commit is contained in:
atlas 2026-08-05 15:07:11 +02:00 committed by mara
commit fbf3757551
3 changed files with 63 additions and 34 deletions

View file

@ -19,31 +19,37 @@ the additional config needed when the swarm spans multiple hosts.
```nix
services.hyperhive = {
domain = "pr1ma.example.com"; # machine-addressable DNS domain
hiveName = "pr1ma"; # human display name (optional)
swarm.domain = "example.com"; # required — the swarm's DNS domain
hiveName = "pr1ma"; # required — this hive's label in it
# domain = "pr1ma.example.com"; # derived from the two above
swarm.name = "constellat1on"; # shared swarm display name (optional)
swarm.domain = "example.com"; # the swarm's DNS domain
};
```
`domain` is required whenever hyperhive is enabled — eval fails with a
hint if it is unset. It drives `HYPERHIVE_HIVE_DOMAIN` in every
container so agents can form qualified labels
(`iris@pr1ma.example.com`).
`swarm.domain` and `hiveName` are **required** whenever hyperhive is
enabled; eval fails with a hint naming each. Neither is defaulted,
because a guessed value here is a wrong hostname that evaluates cleanly
and deploys — an eval failure asking the operator to write the address
down is the cheaper outcome. **Upgrading past this release means setting
both once.**
You can also *not* write it: with `swarm.domain` and `hiveName` set,
`domain` defaults to `<hiveName>.<swarm.domain>`, since every hive in a
swarm occupies its own sub-domain of it. That is a default and not a
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.
`domain` is required too, but you no longer have to *write* it: it
defaults to `<hiveName>.<swarm.domain>`, since every hive in a swarm
occupies its own sub-domain of it. A hive that pins `domain` explicitly
keeps exactly the value it has today — that's why this is a default and
not a rename: 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` does not is the whole distinction — one names this hive, the
other names the group it belongs to.
`domain` drives `HYPERHIVE_HIVE_DOMAIN` in every container so agents can
form qualified labels (`iris@pr1ma.example.com`).
`swarm.name` is purely display — it surfaces in the dashboard chrome
header and per-agent system prompts, and federated hives at different
domains can share one. `hiveName` surfaces in the same places but is
*not* only display: it is the leftmost label of the hive's domain. That
`swarm.name` sits under `swarm` and `hiveName` does not is the whole
distinction — one names this hive, the other names the group it belongs
to.
See `docs/conventions.md` § Hive identity for the env-var chain
and `qualify()` / `qualified_label()` semantics.

View file

@ -178,6 +178,29 @@ in
`<hiveName>.<swarm.domain>`.
'';
}
{
assertion = config.services.hyperhive.swarm.domain != null;
message = ''
hyperhive requires services.hyperhive.swarm.domain to be
set the DNS domain of the swarm this hive belongs to,
of which this hive occupies one sub-domain. There is no
fallback: a guessed value would be a wrong hostname that
evaluates cleanly and deploys. Set it
(`services.hyperhive.swarm.domain = "example.com";`)
with `hiveName` it also derives
`services.hyperhive.domain` for you.
'';
}
{
assertion = config.services.hyperhive.hiveName != null;
message = ''
hyperhive requires services.hyperhive.hiveName to be set
it is this hive's label within the swarm, and the leftmost
part of the domain it is addressed by
(`<hiveName>.<swarm.domain>`), not only a display name.
Set it (`services.hyperhive.hiveName = "pr1ma";`).
'';
}
];
# Virtual bridge — each agent container attaches a veth pair (isolation

View file

@ -85,11 +85,12 @@ in
`services.hyperhive.hiveName` and a hive needs no domain of its
own.
A swarm needs this set somewhere to address its hives uniformly;
it is left nullable so an existing single-hive deployment that
pins `services.hyperhive.domain` directly keeps evaluating
untouched. The only thing eval insists on is that the hive ends
up with a domain, by either route.
**Required** when `services.hyperhive.enable`, and deliberately
not defaulted: there is no fallback worth having. A guessed
swarm domain is a wrong hostname that evaluates cleanly and
deploys, which is worse than an eval failure telling an
operator to write down the one address their swarm answers to.
Upgrading past this costs one line, once.
'';
};
@ -105,14 +106,13 @@ in
example = "pr1ma";
description = ''
Human-readable name of this single-host hive instance.
Distinct from `services.hyperhive.domain` (the machine-
addressable DNS name): the domain may carry the hive name as
its leftmost label by convention, but this option is the
canonical readable identity. Exposed to agents as
`HYPERHIVE_HIVE_NAME`; surfaced in the dashboard chrome and
per-agent system prompt when set. Null falls back to the
default behaviour (chrome shows the domain, prompt doesn't
mention a hive name).
**Required** when `services.hyperhive.enable`. Distinct from
`services.hyperhive.domain` (the machine-addressable DNS name)
but no longer merely cosmetic: a hive occupies
`<hiveName>.<swarm.domain>`, so this is the label the hive is
*addressed* by as well as the one it is called. Exposed to
agents as `HYPERHIVE_HIVE_NAME`; surfaced in the dashboard
chrome and per-agent system prompt.
'';
};