Rename the mesh's seats to mesh-*, keeping their interfaces

novox/hq ADR 0118: the prefix is the reservation rule, so a module
declaring any mesh-* name is refused and there is no reserved-names list to
drift. Ten seats renamed in the table, the manifests that claim them, the
controller's own shipped manifests, and the tests.

Not the migration 0118 expected: a holding is derived at resolution from
manifests and never stored, so nothing recorded points at an old name. A
kept rename table tells a manifest written against one what it became —
kept rather than retired, because a module lives in its own repository and
may be registered long after the catalogue stopped using it.

**A seat is not the interface it delivers.** The git seat became mesh-git
and the git provision did not; likewise the package registry. A blanket
replace renamed both, and the failure read "the package registry is served
on <nil>", which does not say "you renamed an interface". A test now pins
every seat against what it delivers, and that neither name is also the
other.
This commit is contained in:
2026-09-26 23:07:09 +02:00
parent aa74bd86ca
commit 173c8c7c21
11 changed files with 114 additions and 40 deletions
+39
View File
@@ -63,3 +63,42 @@ func TestTheAmqpBrokerDoesNotContendForTheSeat(t *testing.T) {
t.Fatalf("the amqp broker was refused beside the mesh bus: %v", err)
}
}
// **A seat and the interface it delivers are different names, and renaming one must not rename
// the other** (novox/hq ADR 0118). This nearly went wrong: the seats were renamed to the `mesh-*`
// prefix, and a blanket search-and-replace also renamed `npm-package-registry` and `git` where
// they are *provisions* — which a consumer requires and a provider offers. The tests failed with
// "the package registry is served on <nil>", which does not say "you renamed an interface".
func TestRenamingASeatDidNotRenameTheInterfaceItDelivers(t *testing.T) {
for _, pair := range []struct{ seat, delivers string }{
{"mesh-git", "git"},
{"mesh-npm-package-registry", "npm-package-registry"},
{"mesh-artifact-store", "artifact-store"},
{"mesh-store", "postgres-database"},
{"mesh-broker", "mesh-bus"},
} {
s, known := SeatNamed(pair.seat)
if !known {
t.Fatalf("%q is not a seat", pair.seat)
}
if s.Delivers != pair.delivers {
t.Errorf("the %s seat delivers %q, expected %q — renaming the seat moved the "+
"interface with it, and every consumer requiring it would stop resolving",
pair.seat, s.Delivers, pair.delivers)
}
if _, isSeat := SeatNamed(pair.delivers); isSeat {
t.Errorf("%q is both an interface and a seat name; one of the renames was incomplete",
pair.delivers)
}
}
}
// And a manifest written against an old seat name is told what it became, rather than refused as
// unknown — the courtesy the `needs`/`own-secrets` rename already sets.
func TestAnOldSeatNameSaysWhatItBecame(t *testing.T) {
m := Manifest{Module: "old", Claims: []Claim{{Name: "the-catalogue", Scope: ScopeMesh}}}
got := strings.Join(claimProblems(m), "; ")
if !strings.Contains(got, "the-catalogue") || !strings.Contains(got, "mesh-catalog") {
t.Fatalf("the refusal does not name both the old and the new: %q", got)
}
}