Rename mesh-control -> mesh-controller, substrate -> foundation

One name per thing, per the HQ glossary: the module/container/image/binary/repo
becomes mesh-controller, the seat the-controller, and the store+broker pair the
foundation (embedded base bundles, default template and example lock renamed with
their go:embed directives). No behaviour change — a pure vocabulary rename.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
2026-09-16 18:40:40 +02:00
parent 366840fc0d
commit c3b88b9148
77 changed files with 157 additions and 157 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ func TestAModuleThatDoesNotProvideTheStoreStillBuilds(t *testing.T) {
// A mapping that names an address still names the port, and the machine side is still the middle.
//
// The substrate bundle writes "127.0.0.1:5432:5432" today, so the shape is not hypothetical.
// The foundation bundle writes "127.0.0.1:5432:5432" today, so the shape is not hypothetical.
// Found in review: the first cut split on the first colon, read "127.0.0.1" as the machine port,
// failed to parse it, and silently skipped the mapping — which put the filter back on the
// declared port, the exact fault MachineSide was written to end.
+1 -1
View File
@@ -62,7 +62,7 @@ func routeProxy() Manifest {
// A co-located provider's served VALUES reach its consumer, not just its served keys.
//
// The mesh walks a provider on ANOTHER machine and settles what it serves with that node's settings
// layers before offering it (cmd/mesh-control plan.go, theRestOfTheMesh). A provider on the
// layers before offering it (cmd/mesh-controller plan.go, theRestOfTheMesh). A provider on the
// consumer's own machine was never settled at all: resolve.go's servedHere and declaration.go's
// here() both read the manifest and stop there. So a served value the operator supplied — the one
// kind of value a manifest cannot carry, because it is different on every mesh — arrived as the
+5 -5
View File
@@ -89,11 +89,11 @@ type Rendering struct {
// a fact about the mesh, and resolution answers questions about one machine.
Mesh []string
// Substrate is the ports the mesh itself needs reachable on every machine, which no module
// declares because the substrate is not a module (novox/hq 04-ISSUES/051 and 052). The broker
// Foundation is the ports the mesh itself needs reachable on every machine, which no module
// declares because the foundation is not a module (novox/hq 04-ISSUES/051 and 052). The broker
// is the one that matters: a machine dials it to enrol, and a firewall derived only from
// modules closes it.
Substrate []int
Foundation []int
// Names is every machine's internal name and its address, for containers to be given.
//
@@ -213,7 +213,7 @@ func (r Resolution) Declaration(with Rendering) ([]map[string]any, error) {
if err != nil {
return nil, err
}
filtering := AsNftables(rules, with.Mesh, r.PublicDomain != "", with.Substrate)
filtering := AsNftables(rules, with.Mesh, r.PublicDomain != "", with.Foundation)
var out []map[string]any
for _, m := range r.Modules {
@@ -821,7 +821,7 @@ func here(r Resolution, requirement string, with Rendering) (*Needed, error) {
//
// **The one derivation, so the two arrangements cannot disagree.** For a provider elsewhere the
// control plane walks that node, reads its manifest with that machine's port assignments, and
// settles the result with that node's settings layers before offering it (cmd/mesh-control plan.go,
// settles the result with that node's settings layers before offering it (cmd/mesh-controller plan.go,
// theRestOfTheMesh). A provider on the consumer's own machine never passes through that walk, so
// every step of it has to be repeated here — and each step that was not repeated was a promise the
// co-located arrangement quietly broke: first the port (novox/hq 04-ISSUES/038), then the settled
+5 -5
View File
@@ -217,10 +217,10 @@ const SSHPort = 22
// `outward` says this machine is reachable from outside the mesh, which is the only thing that
// decides whether ssh is answered there as well as on the private network.
//
// `substrate` is the ports the MESH ITSELF needs reachable, which no module declares.
// `foundation` is the ports the MESH ITSELF needs reachable, which no module declares.
//
// **Everything else in this file is derived from what modules say they listen on, and the
// substrate is not a module** (novox/hq 04-ISSUES/051). So the broker — the port every machine
// foundation is not a module** (novox/hq 04-ISSUES/051). So the broker — the port every machine
// dials to enrol and to receive every declaration it is ever sent — was absent from the ruleset,
// and nothing noticed: a mesh of one never dials its own broker across the network. The first
// machine to join a firewalled anchor is refused by the packet filter during enrolment, before
@@ -229,7 +229,7 @@ const SSHPort = 22
// It is a floor for the same reason ssh is. A machine nobody can reach is a machine nobody can
// repair; a machine the mesh cannot reach is a machine the mesh cannot manage. Neither is a thing
// any module asks for, and neither may be derived away.
func AsNftables(rules []Rule, mesh []string, outward bool, substrate []int) string {
func AsNftables(rules []Rule, mesh []string, outward bool, foundation []int) string {
var b strings.Builder
b.WriteString("# Computed by the mesh from what is assigned to this node.\n")
b.WriteString("# Edits are lost on the next declaration; change a module's listens instead.\n\n")
@@ -297,9 +297,9 @@ func AsNftables(rules []Rule, mesh []string, outward bool, substrate []int) stri
// Not narrowed to the private network, because the machines that need this most are the ones
// not on it yet: a node enrols BEFORE it has an address here, over the ordinary network, and a
// rule allowing only the private network would close the door being knocked on.
if len(substrate) > 0 {
if len(foundation) > 0 {
b.WriteString("\n\t\t# the mesh's own — never derived, never closed\n")
for _, port := range substrate {
for _, port := range foundation {
b.WriteString(fmt.Sprintf("\t\ttcp dport %d accept\n", port))
}
}
@@ -7,7 +7,7 @@ import (
// The mesh's own ports survive a ruleset derived from modules that do not mention them.
//
// **The firewall is computed from what modules declare they listen on, and the substrate is not a
// **The firewall is computed from what modules declare they listen on, and the foundation is not a
// module** (novox/hq 04-ISSUES/052). So the broker's port — the one every machine dials to enrol
// and to receive every declaration it is ever sent — was absent from every ruleset the mesh ever
// generated, and nothing caught it: a mesh of one never dials its own broker across the network,
@@ -37,12 +37,12 @@ func TestTheBrokersPortIsOpenedThoughNoModuleDeclaresIt(t *testing.T) {
// And a mesh that was never told about a broker still gets a ruleset, rather than an empty one or
// a panic. A control plane in that state cannot issue tokens either, which is where it surfaces.
func TestNoBrokerMeansNoSubstrateRuleRatherThanNoRuleset(t *testing.T) {
func TestNoBrokerMeansNoFoundationRuleRatherThanNoRuleset(t *testing.T) {
out := AsNftables(nil, []string{"10.42.0.1"}, false, nil)
if !strings.Contains(out, "table inet mesh") {
t.Fatalf("no ruleset at all:\n%s", out)
}
if strings.Contains(out, "never derived, never closed\n\t\ttcp dport") {
t.Fatalf("a substrate rule was written for a mesh with no broker:\n%s", out)
t.Fatalf("a foundation rule was written for a mesh with no broker:\n%s", out)
}
}
+1 -1
View File
@@ -706,7 +706,7 @@ func ParseManifest(raw []byte) (Manifest, error) {
// that provides the store and also builds something asks the mesh to put an artifact into the
// thing that artifact is needed to create.
//
// It is the question the substrate record asks of every candidate — can it grant itself the
// It is the question the foundation record asks of every candidate — can it grant itself the
// thing it provides? The store cannot create its own database, the broker cannot create its
// own virtual host, and a registry cannot grant itself a repository. Such a module names its
// image, exactly as the bundle names the three a first node starts from.
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings"
"testing"
"github.com/novox/mesh-control/internal/catalogue"
"github.com/novox/mesh-control/internal/overlay"
"github.com/novox/mesh-controller/internal/catalogue"
"github.com/novox/mesh-controller/internal/overlay"
)
// The manifests the control plane actually ships, resolved.