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:
parent
747f405c6f
commit
fbf3757551
3 changed files with 63 additions and 34 deletions
|
|
@ -19,31 +19,37 @@ the additional config needed when the swarm spans multiple hosts.
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
services.hyperhive = {
|
services.hyperhive = {
|
||||||
domain = "pr1ma.example.com"; # machine-addressable DNS domain
|
swarm.domain = "example.com"; # required — the swarm's DNS domain
|
||||||
hiveName = "pr1ma"; # human display name (optional)
|
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.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
|
`swarm.domain` and `hiveName` are **required** whenever hyperhive is
|
||||||
hint if it is unset. It drives `HYPERHIVE_HIVE_DOMAIN` in every
|
enabled; eval fails with a hint naming each. Neither is defaulted,
|
||||||
container so agents can form qualified labels
|
because a guessed value here is a wrong hostname that evaluates cleanly
|
||||||
(`iris@pr1ma.example.com`).
|
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` is required too, but you no longer have to *write* it: it
|
||||||
`domain` defaults to `<hiveName>.<swarm.domain>`, since every hive in a
|
defaults to `<hiveName>.<swarm.domain>`, since every hive in a swarm
|
||||||
swarm occupies its own sub-domain of it. That is a default and not a
|
occupies its own sub-domain of it. A hive that pins `domain` explicitly
|
||||||
rename — a hive that pins `domain` explicitly keeps exactly the value it
|
keeps exactly the value it has today — that's why this is a default and
|
||||||
has today, which is the point: re-rooting where a value *comes from*
|
not a rename: re-rooting where a value *comes from* must not reinterpret
|
||||||
must not reinterpret the values already deployed.
|
the values already deployed.
|
||||||
|
|
||||||
`hiveName` and `swarm.name` are purely display — they surface in the
|
`domain` drives `HYPERHIVE_HIVE_DOMAIN` in every container so agents can
|
||||||
dashboard chrome header and per-agent system prompts. Federated hives
|
form qualified labels (`iris@pr1ma.example.com`).
|
||||||
at different domains can share a `swarm.name`; that it sits under
|
|
||||||
`swarm` and
|
`swarm.name` is purely display — it surfaces in the dashboard chrome
|
||||||
`hiveName` does not is the whole distinction — one names this hive, the
|
header and per-agent system prompts, and federated hives at different
|
||||||
other names the group it belongs to.
|
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
|
See `docs/conventions.md` § Hive identity for the env-var chain
|
||||||
and `qualify()` / `qualified_label()` semantics.
|
and `qualify()` / `qualified_label()` semantics.
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,29 @@ in
|
||||||
`<hiveName>.<swarm.domain>`.
|
`<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
|
# Virtual bridge — each agent container attaches a veth pair (isolation
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,12 @@ in
|
||||||
`services.hyperhive.hiveName` and a hive needs no domain of its
|
`services.hyperhive.hiveName` and a hive needs no domain of its
|
||||||
own.
|
own.
|
||||||
|
|
||||||
A swarm needs this set somewhere to address its hives uniformly;
|
**Required** when `services.hyperhive.enable`, and deliberately
|
||||||
it is left nullable so an existing single-hive deployment that
|
not defaulted: there is no fallback worth having. A guessed
|
||||||
pins `services.hyperhive.domain` directly keeps evaluating
|
swarm domain is a wrong hostname that evaluates cleanly and
|
||||||
untouched. The only thing eval insists on is that the hive ends
|
deploys, which is worse than an eval failure telling an
|
||||||
up with a domain, by either route.
|
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";
|
example = "pr1ma";
|
||||||
description = ''
|
description = ''
|
||||||
Human-readable name of this single-host hive instance.
|
Human-readable name of this single-host hive instance.
|
||||||
Distinct from `services.hyperhive.domain` (the machine-
|
**Required** when `services.hyperhive.enable`. Distinct from
|
||||||
addressable DNS name): the domain may carry the hive name as
|
`services.hyperhive.domain` (the machine-addressable DNS name)
|
||||||
its leftmost label by convention, but this option is the
|
but no longer merely cosmetic: a hive occupies
|
||||||
canonical readable identity. Exposed to agents as
|
`<hiveName>.<swarm.domain>`, so this is the label the hive is
|
||||||
`HYPERHIVE_HIVE_NAME`; surfaced in the dashboard chrome and
|
*addressed* by as well as the one it is called. Exposed to
|
||||||
per-agent system prompt when set. Null falls back to the
|
agents as `HYPERHIVE_HIVE_NAME`; surfaced in the dashboard
|
||||||
default behaviour (chrome shows the domain, prompt doesn't
|
chrome and per-agent system prompt.
|
||||||
mention a hive name).
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue