Hive-scoped identifiers are built by joining a hive name with fixed words — `hive-<name>`, `hive-<name>-agent` — so a hive called `foo-agent` produces exactly the id hive `foo`'s agent containers produce. The queue's responder resolves it as the agents, and that hive silently receives an agent grant instead of its own; a NATS denial reaches a client as a timeout, so nothing names the cause. Equality cannot see this: the two NAMES differ, only the composed strings collide. Deliberately a second file rather than three more entries in `reserved-names.nix`. That list is matched by equality against a whole name and every entry is a value some component emits; applying containment to it would refuse `forgeworks` and `operator-hq` for failures that do not exist. The two lists differ in subject (hive-only vs both), matcher (substring vs equality) and admission rule, and each file's header says so. No Rust change: `HIVE_RESERVED_NAMES` answers "may an AGENT be called this", which stays an equality question — an agent name is never composed into these identifiers. Measured against the predicate rather than assumed: pr1ma=ok alpha=ok forgeworks=ok operator-hq=ok foo-agent=REFUSED beehive=REFUSED swarm=REFUSED myswarmx=REFUSED The four `ok` cases are the control: `forgeworks` and `operator-hq` are exactly what a merged list would have refused.
45 lines
2.4 KiB
Nix
45 lines
2.4 KiB
Nix
# Words no HIVE name may CONTAIN — a substring blacklist, and the second half
|
|
# of `./reserved-names.nix`.
|
|
#
|
|
# Two files rather than one list, because the two differ in every dimension
|
|
# that matters and folding them would silently widen one of them:
|
|
#
|
|
# | | `reserved-names.nix` | this file |
|
|
# |---|---|---|
|
|
# | subject | agent AND hive names | hive names only |
|
|
# | match | equality | substring |
|
|
# | why | the name IS a value some component emits | the word is a fixed SEGMENT of a derived identifier |
|
|
#
|
|
# ⚠️ That last row is the whole argument. `hive-<name>` and `hive-<name>-agent`
|
|
# are built by composing a hive name with these words, so a hive called
|
|
# `foo-agent` produces an id another hive's AGENTS also produce — the composed
|
|
# strings collide even though the names do not. Equality cannot see that; only
|
|
# containment can.
|
|
#
|
|
# ⇒ And it is why the sender words (`operator`, `system`, `forge`, …) are NOT
|
|
# here: those are compared against a whole name, never embedded in one, so
|
|
# applying containment to them would refuse `forgeworks` for no failure that
|
|
# exists. `reserved-names.nix`'s own rule — an entry must name a real failure,
|
|
# not a word that looked risky — governs this file too.
|
|
#
|
|
# Read by `host-modules/swarm-otel.nix`, which owns the hive-roster assertion.
|
|
# Deliberately NOT exported to the Rust side: `HIVE_RESERVED_NAMES` answers
|
|
# "may an AGENT be called this", which stays an equality question.
|
|
[
|
|
# `hive-<name>` — every hive's own OIDC client id (`swarm-authelia.nix`'s
|
|
# `hiveClientPrefix`), and the string the queue's auth-callout responder
|
|
# strips to decide which hive a connection is.
|
|
"hive"
|
|
# `hive-<name>-agent` — the client its agent containers present
|
|
# (`agentClientSuffix`). A hive named `foo-agent` mints exactly the id hive
|
|
# `foo`'s agents do, and the responder resolves it as the agents: that hive
|
|
# silently receives an agent grant instead of its own, and a NATS denial
|
|
# arrives as a timeout, so nothing names the cause.
|
|
"agent"
|
|
# Already in `reserved-names.nix` as an exact match, listed again here for
|
|
# the wider rule: the swarm collector names components `<kind>/<owner>` with
|
|
# the hive name as owner, and a name merely CONTAINING it is not a collision
|
|
# today — but `swarm` is the one word this swarm composes identifiers from
|
|
# everywhere, so the operator's rule covers it and the two files agree.
|
|
"swarm"
|
|
]
|