Delete go/overlay: no importer is left; the package list, notInSDK and seat-names follow (S-7, ADR 0634 §5; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 17:18:36 +01:00
parent 14f956e4cd
commit 4099164aad
8 changed files with 2 additions and 230 deletions
-65
View File
@@ -1,65 +0,0 @@
package catalogue_test
import (
"encoding/json"
"testing"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/overlay"
)
// The manifests the control plane actually ships, resolved.
//
// Written because the earlier tests built their own manifests and passed while the real one was
// missing a claim — a whole mechanism could have been absent from what ships and every test would
// still have been green.
func provided(t *testing.T) map[string]catalogue.Manifest {
t.Helper()
out := map[string]catalogue.Manifest{}
for _, raw := range []map[string]any{
overlay.Manifest(),
} {
b, err := json.Marshal(raw)
if err != nil {
t.Fatal(err)
}
m, err := catalogue.Decode(b)
if err != nil {
t.Fatalf("a manifest this control plane ships is not valid: %v", err)
}
out[m.Module] = m
}
return out
}
func TestTheControlPlaneShipsNoNetworkingBundle(t *testing.T) {
// ADR 0226: one module for the one private network. A bundle shipped beside it again would be
// a second name every machine carries for the same thing.
shipped := provided(t)
if len(shipped) != 1 {
t.Fatalf("the control plane ships %d modules, want only %s", len(shipped), overlay.Name)
}
if _, ok := shipped["networking"]; ok {
t.Fatal("the retired networking bundle is shipped again")
}
}
// The names-need-addressing test went with the names module: names are a fact now, and a machine
// the mesh cannot place is simply left out of the file (facts_test.go) — which is the same
// protection, enforced where the file is written rather than by a provision refusing.
func withTailscale(shelf map[string]catalogue.Manifest) map[string]catalogue.Manifest {
out := map[string]catalogue.Manifest{}
for k, v := range shelf {
out[k] = v
}
// Deliberately without name-resolution of its own, which is the case that used to install
// both VPNs: the names then needed the mesh's addressing, and only WireGuard has it.
out["tailscale"] = catalogue.Manifest{
Module: "tailscale", Version: "1",
Provides: catalogue.Offers(overlay.Requirement),
Claims: []catalogue.Claim{{Name: overlay.TheNetwork, Scope: catalogue.ScopeNode}},
}
return out
}
-5
View File
@@ -1,5 +0,0 @@
// Package overlay is the private network's names and its manifest: the module the mesh provides for itself, the
// requirement and seat it answers, the interface's name and files, and the mesh's internal names. Its generator, the
// peer graph and the declaration it renders are the node-engine's own (novox/hq ADR 0593 §1, §7), in mesh-host's
// internal/overlay.
package overlay
-39
View File
@@ -1,39 +0,0 @@
package overlay
import (
"os"
"regexp"
"strings"
)
// Names are how one node reaches another by name rather than by address.
//
// novox/hq 08-connectivity: what the host receives is the resolver's configuration, as files,
// listing every peer's internal name and overlay address. Computed centrally for the same reason
// the peer graph is — it needs every node at once.
// SuffixVar lets a mesh choose what its internal names end in.
const SuffixVar = "MESH_INTERNAL_SUFFIX"
// DefaultSuffix is `.internal`, which IANA reserved for exactly this in 2024. A name under it can
// never collide with a public one, so an internal name that leaks into a public resolver fails
// rather than reaching a stranger's machine.
const DefaultSuffix = "internal"
// Suffix is what internal names end in.
func Suffix() string {
if v := strings.TrimSpace(os.Getenv(SuffixVar)); v != "" {
return strings.TrimPrefix(v, ".")
}
return DefaultSuffix
}
// nodeName is what a node may be called, so that it can also be a hostname.
var nodeName = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$`)
// InternalName is a node's name inside the mesh.
func InternalName(node string) string { return node + "." + Suffix() }
// **What remains of a larger file.** The rest wrote /etc/hosts, which the controller no longer
// writes at all (novox/hq ADR 0199): the mesh's resolver answers these names. The naming stays here, because several things compose a node's internal name and one of them
// writing the suffix differently would be a name nothing answers to.
-79
View File
@@ -1,79 +0,0 @@
package overlay
// The private network as a module rather than as code beside the module system.
//
// A machine's peer list is derived from every other machine, so it differs on each one and
// changes when any of them changes — there is nothing that could be written in a manifest. So the
// module says its resources are computed, and this computes them.
//
// What that buys, beyond one mechanism instead of two: **a machine is on the private network
// because it was assigned the module.** Before this, every machine with a key and an address was
// on it, and there was no way to say a machine should stay off.
//
// It is worth saying what is *not* here, because networking looks like it should be foundational.
// The host needs none of this. It has an address and a route to the broker before the mesh exists
// — that is the machine's own networking — and the broker's address is carried in the enrolment
// token rather than resolved. So the private network is something the mesh installs on top, like
// anything else, and a node without it is an ordinary node that nothing reaches directly.
// What a module asks for when it needs machines to reach each other. **This is the name that
// matters** — WireGuard is one way to answer it, and naming the requirement after the answer is
// how a mesh ends up unable to have a second one.
const Requirement = "private-network"
// Name is the module that answers it with WireGuard.
//
// **It writes no names.** A machine's mesh names are answered by the mesh's one resolver (novox/hq
// ADR 0194), and /etc/hosts is the file of one module, the holder of `node-hostname` (ADR 0199,
// ADR 0223): the controller writes into no file another seat's holder owns. If the mesh ever needs a line there, it
// asks that holder to register it. This module asked for a `node-names` fact written into /etc/hosts
// until 2026-10-05; the host gives that region back at the first push without it.
const Name = "mesh-wireguard"
// Addressing is the mesh handing out addresses on the private network itself.
//
// The mesh's resolver answers names from it, which is why it requires this rather than a private
// network in general. A different VPN that hands out its own addresses would come with its own
// names — the mesh has nothing to answer about a machine whose address it did not choose.
const Addressing = "mesh-addressing"
// TheNetwork is what a machine can only have one of.
//
// Providing a private network is not the singular part — a machine could reasonably run two VPNs
// for two different purposes. Being **the** one the mesh runs over is singular, and without
// saying so a person who chose a different VPN can still end up with this one dragged back in by
// something that needed the mesh's own addresses. Which is exactly what happened, once.
const TheNetwork = "the-private-network"
// **A resolver's data went the same way as the names.** Two constants used to sit here — a
// `mesh-resolver` module that would write the machines as wildcards, and a `resolver-data`
// requirement a daemon would ask for. Nothing ever provided or consumed either: a module that
// answers names asks for the `node-zones` fact in its own manifest (catalogue.FactsInto) and
// requires Addressing, since the file is made of the mesh's addresses and means nothing off the
// network. A requirement nothing provides is refused at resolution, so leaving the names here
// would only have documented a mechanism that does not exist.
// Manifest is the module the mesh provides for itself.
//
// It ships with the control plane rather than coming from a repository, because the thing that
// computes it ships with the control plane. That is the only way it is unusual: it is assigned,
// unassigned, resolved and settled exactly like a module somebody wrote.
func Manifest() map[string]any {
return map[string]any{
"module": Name,
"version": "1",
"computed": Name,
"provides": []string{Requirement, Addressing},
"claims": []map[string]any{{"name": TheNetwork, "scope": "node"}},
}
}
// Interface is what the private network is called on a machine, and where the node's own key
// lives. A constant rather than a setting: two nodes disagreeing about the name would produce a
// mesh where each is configured correctly and nothing meets.
const (
Interface = "mesh0"
ConfigPath = "/etc/wireguard/" + Interface + ".conf"
Unit = "wg-quick@" + Interface
DefaultKeyPath = "/var/lib/mesh-host/overlay.key"
)
-30
View File
@@ -1,30 +0,0 @@
package overlay
import (
"encoding/json"
"testing"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// The private network's claim is a seat the mesh defines (novox/hq ADR 0110).
//
// Checked here because this is where the manifest is composed: it ships with the control plane and
// has no module.json for a test reading the catalogue to find. Parsed with the real parser, so a
// set that forgot this seat refuses the control plane's own module here rather than on a machine.
func TestThePrivateNetworksClaimIsASeatTheMeshDefines(t *testing.T) {
for _, composed := range []map[string]any{Manifest()} {
raw, err := json.Marshal(composed)
if err != nil {
t.Fatal(err)
}
// Decoded here; the indexer's judge judges it (mesh-delivery's judge tests hold it to every rule).
if _, err := catalogue.Decode(raw); err != nil {
t.Errorf("%s, composed by the control plane, does not decode: %v", composed["module"], err)
}
}
seat, defined := catalogue.SeatNamed(TheNetwork)
if !defined || seat.Scope != catalogue.ScopeNode {
t.Fatalf("%s is not a node seat the mesh defines: %+v", TheNetwork, seat)
}
}
-9
View File
@@ -1,9 +0,0 @@
package overlay
import (
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/seatlist/seatlisttest"
)
// The seats the tests judge against are given to catalogue as a host gives the ones it read from the bus (ADR 0635 §1).
func init() { catalogue.UseSeats(catalogue.SeatsFromDefinitions(seatlisttest.Definitions())) }
+2 -2
View File
@@ -25,7 +25,7 @@ import (
var meshSDKPackages = []string{
".", "announce", "announcetest", "buscalls", "buscompose", "busstate", "busretry", "calladdress", "catalogue",
"declaration", "forgekey", "health", "internal/beside", "keys", "kvlimit", "membership", "motion",
"objectlink", "outward", "overlay", "pernode", "process",
"objectlink", "outward", "pernode", "process",
"sdkversion", "seal", "seatdef", "seatlist", "seatlist/seatlisttest", "testbus", "views", "views/viewstest",
}
@@ -39,7 +39,7 @@ var clientSeats = []string{"operator-channel", "mesh-vault", "node-engine", "npm
var moduleWord = regexp.MustCompile(`\bmesh-(?:delivery|grants|vault|host|config|provisioner|broker|knowledge|enrolment)\b[-a-z]*|\b(?:indexer|assigner|teller|watchman|checker|builder)(?:-views|_read_)`)
// notInSDK are the packages that moved to a seat's client or contract (ADR 0627 §1, §4) and may not come back.
var notInSDK = []string{"asks", "asker", "publish", "composer", "parts", "provider", "handacts", "channel", "provisions", "buildstep", "delivery"}
var notInSDK = []string{"asks", "asker", "publish", "composer", "parts", "provider", "handacts", "channel", "provisions", "buildstep", "delivery", "overlay"}
// untilTheJoin is what ADR 0627 still moves at the group's join, each `<file>: <what>`, naming what the checks below
// would refuse; it only shrinks. The vault module's name in delivery stays past this milestone's pin
-1
View File
@@ -32,5 +32,4 @@ health/findings.go: mesh-conditions
health/findings.go: mesh-healers
health/findings.go: mesh-self-check
internal/beside/beside.go: mesh-catalog
overlay/overlay.go: the-private-network
seatlist/seatlist.go: mesh-catalog