Facts carry the format as a template, so the control plane holds none (ADR 0120) #80

Merged
jschoubben merged 3 commits from feat/roster-facts-are-templates into main 2026-09-26 23:51:23 +00:00
Owner

A roster fact was a name from a closed list, each formatted in Go here (node-names as a hosts file, node-zones as a resolver's zones). Every new consumer meant another formatter in the control plane, in the consumer's own configuration language.

Now a fact is a path + a Go template over the roster view (.Node, .Suffix, .Names = every served name, .Machines = only nodes; entries {Name, FQDN, Address}). The mesh owns the data; the module owns the format:

  • /etc/hosts is a template on the network module (internal/overlay/generator.go);
  • dnsmasq's zones move to dnsmasq (mesh-catalog PR);
  • the controller renders and reads neither. The two Go formatters are deleted.

WireGuard stays a computed generator — the overlay is the substrate delivery rides on, and its config is topology, not a roster projection.

Not backward compatible (schema: string → {path, template}). Lands together with the mesh-catalog PR of the same name — only dnsmasq used facts.

Tests: mechanism locked in internal/catalogue/roster_test.go; /etc/hosts pinned byte-for-byte in internal/overlay/hosts_fact_test.go; the resolver tests compose the real updated dnsmasq manifest and confirm the zones output is unchanged. (The two the-uplink seat failures on main are g14's in-flight ADR-0117 landing, unrelated to this change.)

A roster fact was a name from a closed list, each formatted in Go here (node-names as a hosts file, node-zones as a resolver's zones). Every new consumer meant another formatter in the control plane, in the consumer's own configuration language. Now a fact is a path + a Go template over the roster view (`.Node`, `.Suffix`, `.Names` = every served name, `.Machines` = only nodes; entries `{Name, FQDN, Address}`). The mesh owns the data; the module owns the format: - `/etc/hosts` is a template on the network module (`internal/overlay/generator.go`); - dnsmasq's zones move to dnsmasq (mesh-catalog PR); - the controller renders and reads neither. The two Go formatters are deleted. WireGuard stays a computed generator — the overlay is the substrate delivery rides on, and its config is topology, not a roster projection. **Not backward compatible** (schema: string → `{path, template}`). Lands together with the mesh-catalog PR of the same name — only dnsmasq used facts. Tests: mechanism locked in `internal/catalogue/roster_test.go`; `/etc/hosts` pinned byte-for-byte in `internal/overlay/hosts_fact_test.go`; the resolver tests compose the real updated dnsmasq manifest and confirm the zones output is unchanged. (The two `the-uplink` seat failures on main are g14's in-flight ADR-0117 landing, unrelated to this change.)
jschoubben added 1 commit 2026-09-26 23:34:31 +00:00
A roster fact used to be a name from a closed list, each formatted in Go
here — node-names as a hosts file, node-zones as a resolver's zones. Every
new consumer (ssh's known_hosts, an authorized_keys) meant another formatter
in the control plane, in the consumer's own configuration language.

Now a fact is a path and a Go template over the roster view (this node, the
suffix, and every served name vs the machines). The mesh owns the data; the
module owns the format. /etc/hosts is a template on the network module;
dnsmasq's zones move to dnsmasq. The controller renders and reads neither.

WireGuard stays a computed generator: the overlay is the substrate delivery
rides on, and its config is topology, not a roster projection.

Output is byte-for-byte unchanged, pinned by the hosts golden tests and the
resolver tests that compose the real dnsmasq manifest.
jschoubben added 1 commit 2026-09-26 23:42:03 +00:00
# Conflicts:
#	internal/catalogue/facts.go
#	internal/catalogue/facts_test.go
jschoubben added 1 commit 2026-09-26 23:50:32 +00:00
The merge commit took only the staged index; these reconciliation edits sat
unstaged in the working tree. Integrate the template mechanism with #79's
region write (hq 128): RosterFile gains Shared, FactsInto sets into:block for
a shared fact, /etc/hosts becomes the region form (no floor) and node-names is
marked shared. Without this the merge would have regressed /etc/hosts back to
a whole-file write, replacing the operator's own lines.
jschoubben merged commit ccf50b1269 into main 2026-09-26 23:51:23 +00:00
jschoubben deleted branch feat/roster-facts-are-templates 2026-09-26 23:51:23 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-controller#80