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.)
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.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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/hostsis a template on the network module (internal/overlay/generator.go);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/hostspinned byte-for-byte ininternal/overlay/hosts_fact_test.go; the resolver tests compose the real updated dnsmasq manifest and confirm the zones output is unchanged. (The twothe-uplinkseat failures on main are g14's in-flight ADR-0117 landing, unrelated to this change.)