types: let nix own the reserved-name blacklist
One list, in nix/reserved-names.nix, handed to everything that needs it as HIVE_RESERVED_NAMES. Keeping it current becomes a config change rather than a rebuild, and hive names and agent names -- one namespace going forward -- are checked against the same file: swarm-otel.nix's hand-written reservedOwners is gone. Whitespace-separated rather than JSON, deliberately, unlike the structured env vars beside it. Every entry is an Ident ([a-z0-9-]), so whitespace cannot occur inside a name and the encoding is provably lossless; JSON would mean either a parser dependency in a crate whose purpose is to have none, or a copy of the parse in every consumer. An UNSET variable is not "nothing is reserved". Both creation sites log an error and return a warning saying the check did not run, so a misconfigured deployment says so instead of silently accepting every name. A blank value folds into unset: nix always renders a non-empty list, so present-but-empty is a rendering fault, not a declaration. Two guards whose subject moved out of their own file now assert their own case is still in it, because a guard that can be retired by an edit elsewhere is not a guard: - swarm-otel.nix asserts reserved-names.nix still contains its swarmTierName. - hive-sh4re's sentinel drift test PANICS when the variable is missing rather than skipping -- a drift test that quietly does nothing still reports green. checks.nix and devshell.nix both export it so CI and a local cargo test agree. Verified as a pair: with the variable set, 8 tests pass; with it unset, exactly the 4 drift tests fail and the unrelated ones still pass.
This commit is contained in:
parent
7bb68fe819
commit
27932ec631
10 changed files with 326 additions and 87 deletions
|
|
@ -758,16 +758,35 @@ async fn create_agent(
|
|||
//
|
||||
// Collected rather than logged-and-dropped — see `CreateAgentResponse`.
|
||||
let mut warnings = Vec::new();
|
||||
if hive_types::is_reserved_name(&agent) {
|
||||
// A protocol literal: the message layer already produces this name
|
||||
// as a sender or recipient, so wakes from the component and
|
||||
// messages from the agent become the same broker row.
|
||||
let detail = format!(
|
||||
"agent name {agent:?} is a reserved protocol name — messages from this agent will be \
|
||||
indistinguishable from hyperhive's own; this will become an error"
|
||||
);
|
||||
tracing::warn!(agent = %agent, "create_agent: reserved name");
|
||||
warnings.push(detail);
|
||||
// The blacklist comes from nix via `HIVE_RESERVED_NAMES` — one file, read
|
||||
// by this daemon, by hive-c0re and by the swarm collector's own owner
|
||||
// assertion. An UNSET variable means this process was never told, which
|
||||
// is not the same as "no name is reserved": staying quiet there would be
|
||||
// a check that reports clean because it could not run.
|
||||
let raw = hive_types::reserved_names_raw();
|
||||
match raw.as_deref().map(hive_types::parse_reserved_names) {
|
||||
None => {
|
||||
tracing::error!(
|
||||
var = hive_types::RESERVED_NAMES_ENV,
|
||||
"create_agent: reserved-name check could not run — variable not set"
|
||||
);
|
||||
warnings.push(format!(
|
||||
"the reserved-name check did not run: {} is unset, so {agent:?} was accepted \
|
||||
without being checked against the protocol literals",
|
||||
hive_types::RESERVED_NAMES_ENV
|
||||
));
|
||||
}
|
||||
Some(reserved) if hive_types::is_reserved_name(&agent, &reserved) => {
|
||||
// A protocol literal: the message layer already produces this
|
||||
// name as a sender or recipient, so wakes from the component and
|
||||
// messages from the agent become the same broker row.
|
||||
tracing::warn!(agent = %agent, "create_agent: reserved name");
|
||||
warnings.push(format!(
|
||||
"agent name {agent:?} is a reserved protocol name — messages from this agent will \
|
||||
be indistinguishable from hyperhive's own; this will become an error"
|
||||
));
|
||||
}
|
||||
Some(_) => {}
|
||||
}
|
||||
|
||||
let hive = hive_types::Ident::parse(&req.hive)
|
||||
|
|
|
|||
Loading…
Reference in a new issue