0036 (accepted): a node is a managed machine, and disconnection is a situation. The open question posed a class distinction — full nodes and lesser presences. There is none. Reachability is state, not kind, which promotes the host's local store from a component to a requirement: it is what makes disconnection ordinary rather than exceptional. The reduced contract the question reached for is real but it is capability, and that belongs in the profile. 0037 (accepted): the host applies, it does not decide. Measured rather than argued — the absorption is smaller than the machinery that already applies state, and eight of ten adapters carry no dependency to move. The two that do open a Postgres connection to the control plane, which inside tier 0 is the one thing the tier rule exists to forbid. So each concern splits: deciding needs every other node and stays in tier 2; applying needs root and locality and goes to tier 0. The host carries ONE concern, of which the six are instances. 0038 (proposed): a node joins by linking first. The operator's two-modes proposal, adopted as intent and corrected as structure. Two modes is two code paths where the first runs once per mesh and rots — and the mesh already has that fault in its worst form, as three hand-run shell scripts. Instead: one behaviour, two sources of declaration. The first node is not a different kind of node, it is a node whose mesh is not up yet, and its specialness is temporary and self-erasing. 0038 also shrinks the migration 0037 called expensive: a joining node never needs mesh-wide state, because the hard part of the overlay is only needed to compute the WHOLE mesh. It needs one peer. The rest arrives. Left open and said so: what may be pushed over the link and how a joining node proves it is entitled to join, and whether one host can raise the substrate alone.
5.1 KiB
status, date, deciders, reconstructed
| status | date | deciders | reconstructed |
|---|---|---|---|
| accepted | 2026-08-25 | jochen | false |
37. The host applies; it does not decide
Context
The skeleton absorbs overlay membership, packet filtering, package management, service supervision, the container runtime and filesystem management into tier 0, and research 006 called this "the skeleton's biggest unproven claim. A binary whose whole argument is that it has no dependencies now carries six concerns."
That claim has now been measured against the monorepo's main:
host-size.md.
The measurement says the question asked about the wrong axis.
Considered options
- Absorb the six concerns as they are. What the skeleton literally proposes. Rejected on evidence: two of the ten modules implementing them open a direct connection to the control plane's database and compute their own configuration. Absorbing those unchanged puts a Postgres client and knowledge of the mesh schema inside tier 0 — an upward dependency, and the tier rule is the whole of the bootstrap argument.
- Leave them as modules. Keeps the tier rule trivially, and keeps the fault that prompted the skeleton: four modules constituting how a node is reachable with no relationship the mesh can see, so one intent is expressed four times (research 005 finding 4 measures this and finds it is the only place in the catalogue where the shape genuinely occurs).
- Split each concern: decide centrally, apply locally. Chosen.
Decision
The host has one concern: apply declared state on this machine. The six are not six concerns it carries; they are instances of the one.
Each divides:
- Deciding — what this node's overlay, names, exposure, filtering, packages and services should be. This needs every other node, and belongs to the control plane.
- Applying — putting that on the machine. This needs root and locality, and belongs to the host.
The host never queries the mesh database. A host that reads the control plane's schema is tier 0 depending on tier 2, and the tiers stop being a bootstrap answer the moment that is permitted once.
Why the evidence supports it
Size was the wrong worry. The ten modules total 2 755 lines. The machinery that already
applies state on a node — meshware, env-sync, config-sync — is 3 059. Everything being
absorbed is smaller than what already exists to apply it. The host is not a new large thing; it
already exists, spread across three core modules and unnamed.
Eight of the ten are already pure appliers. They receive derived state and put it on the machine. Absorbing them moves code that has no dependency to move.
The split has already been happening, unnamed. dnsmasq-app needs the same mesh-wide data
as wireguard and does not query for it. Its own comments record why: the values were
"duplicated by hand on all four nodes" until someone derived them centrally, after a rename
meant editing four override rows nobody knew about. That is this decision, reached once by
fixing a bug.
Consequences
- Two modules must be split before they can be absorbed, and they are the two hardest.
wireguardneeds every node's key, address, site and endpoint reachability;traefikneeds certificates and every node's exposed names. The measurement says the design is right; it does not say the migration is cheap, and this record does not claim it is. - The overlay and firewall modules stop existing as the skeleton says — but the reason is now sharper than "they are host concerns". The host holds membership and applies filtering; the control plane decides policy; swappable backends stay modules.
- Six vocabularies remain. Zero dependencies, but the host must still know what a WireGuard peer, an nftables rule, a package, a unit, a container and a dataset are. That surface is the residue of the original worry and is not measured by anything here.
- A dependency-direction lint is now load-bearing, not a nicety. This record is a rule about direction, and per this repository's own standard a rule states how it is checked: an upward import fails the build. A tier rule enforced by intention is the same as no tier rule.
- What the host carries versus what it finds is still open.
Issue 007 — the
host manages
wg,nft,pacman,docker; it does not contain them, and installed is not the same as usable.
References
host-size.md— the measurement.- Research 005 — reachability as the only measured co-change cluster in the catalogue.
- ADR 0003 — what the control plane decides from.
- ADR 0030 —
mesh-hostas tier 0. - ADR 0008 — the standard the direction lint is held to.