H1 (review r2): the foundation host is the entry that claims the seat node-engine, not a module named mesh-host

Builds: design 47 G §527, §634
This commit is contained in:
2026-11-12 22:16:27 +01:00
parent 905265a56b
commit 3167f0104f
2 changed files with 19 additions and 2 deletions
@@ -29,6 +29,10 @@ var appliedThrough = map[string]string{
// A variable rather than a constant only so a test can hold both behaviours; nothing else sets it.
var enforceSeatDependencies = true
// nodeEngineSeat is the seat the node-engine's own module claims (design 47 G §508, §527, §634): the
// foundation's host is the entry that claims it, never a module named here.
const nodeEngineSeat = "node-engine"
// foundationModules are the pieces genesis lays before any module exists (novox/hq ADR 0207 §5):
// the host and the private network. Registered as modules so they can be assigned, but what they
// declare is the installation's, not a module's, so it is never judged. The third piece, the
@@ -38,7 +42,6 @@ var enforceSeatDependencies = true
// The private network's module is overlay.Name, written out because the overlay package composes
// on top of this one; its resources are computed, which exempts it by the rule below as well.
var foundationModules = map[string]bool{
"mesh-host": true,
"mesh-wireguard": true,
}
@@ -46,7 +49,7 @@ var foundationModules = map[string]bool{
// module whose resources are computed is the mesh's by construction — the private network's peer
// list and its tools are the controller's, written per node — so it counts whatever its name.
func isFoundation(m mcat.Manifest) bool {
return foundationModules[m.Module] || m.Computed != ""
return foundationModules[m.Module] || m.ClaimsSeat(nodeEngineSeat) || m.Computed != ""
}
// DependsOn is every seat a module needs held on its node: derived from the resource types it
@@ -95,3 +95,17 @@ func TestWithTheSwitchFlippedAnUnmetDependencyRefusesTheNode(t *testing.T) {
t.Errorf("the first pass refused an unmet dependency: %v", err)
}
}
func TestTheFoundationHostIsTheEntryThatClaimsTheNodeEngineSeat(t *testing.T) {
svc := res("service", "x")
// Whatever its name, the entry claiming the seat is the foundation's: nothing to depend on.
engine := withResources(mod("the-engine", nil, nil, nil, mcat.Claim{Name: "node-engine"}), svc)
if got := DependsOn(nil, engine); len(got) != 0 {
t.Errorf("the entry claiming node-engine depends on %v, want nothing (§527)", got)
}
// A module named as the old code named the engine, claiming no such seat, is an ordinary module.
named := withResources(mod("mesh-host", nil, nil, nil), svc)
if got := DependsOn(nil, named); !reflect.DeepEqual(got, []string{mcat.ServiceManagerSeat}) {
t.Errorf("a module merely named mesh-host depends on %v, want the service manager seat", got)
}
}