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.
76 lines
3.7 KiB
Markdown
76 lines
3.7 KiB
Markdown
---
|
|
status: accepted
|
|
date: 2026-08-25
|
|
deciders: jochen
|
|
reconstructed: false
|
|
---
|
|
|
|
# 36. A node is a managed machine, and disconnection is a situation
|
|
|
|
## Context
|
|
|
|
[Research 006](../01-RESEARCH/006-mesh-from-scratch/00-overview.md) left open: *"does an
|
|
unprivileged node earn a place in the inventory, or only a presence? Decides whether 'node'
|
|
means one thing or two."*
|
|
|
|
The question came from requirement 6 — *Arch Linux only for now; ideally any device, including
|
|
phones, on lighter terms* — and from the observation that some machines cannot be fully
|
|
managed. A phone will not run the host. A laptop is absent for days.
|
|
|
|
The question assumed the answer was a **class**: full nodes and lesser ones, with the
|
|
inventory recording the first and merely acknowledging the second.
|
|
|
|
## Considered options
|
|
|
|
1. **Two classes — nodes and presences.** An unprivileged device gets a lighter record and a
|
|
reduced contract. Rejected: it makes "node" mean two things, so every context that reasons
|
|
about nodes acquires a branch, and the branch is invisible in the type. The mesh already has
|
|
one instance of this shape and it is the one this repository keeps writing issues about —
|
|
a declared thing that is only sometimes honoured.
|
|
2. **One class, membership by capability.** Everything is a node; what it can do is a property.
|
|
Chosen.
|
|
|
|
## Decision
|
|
|
|
**A node is a managed machine inside the mesh.** Not a device that is merely known about, not
|
|
an unprivileged something. If the mesh does not manage it, it is not a node — it is a client, a
|
|
peer, or a thing on the network, and those want their own names rather than a weakened version
|
|
of this one.
|
|
|
|
**A disconnected node is still a node, in a different situation.** Reachability is state, not
|
|
class. A node that is switched off, roaming, or behind a connection that has dropped has not
|
|
become a lesser kind of thing; it has a last-known state and a pending set of declarations.
|
|
|
|
The distinction the original question reached for is real, but it is **capability**, not kind —
|
|
what this machine can be asked to do — and that belongs in the host's profile, not in the
|
|
definition of a node.
|
|
|
|
## Consequences
|
|
|
|
- **The inventory has one shape.** No branch, no second record type, no context that must ask
|
|
which kind it is holding.
|
|
- **Local state is structural, not a convenience.** If disconnection is an ordinary situation
|
|
rather than an exception, the host's store is authoritative while disconnected by design —
|
|
it is what makes the situation ordinary. This promotes `store/` from a component to a
|
|
requirement.
|
|
- **Absence is not failure.** A node that has not been seen is in a state, and the mesh must be
|
|
able to say which. Anything that treats unreachable as broken will be wrong most of the time
|
|
about a laptop.
|
|
- **Devices that cannot be managed do not become nodes by being lenient about the word.** A
|
|
phone that cannot run the host is not a node under this record. Whether the mesh should reach
|
|
such devices at all, and as what, is not decided here and needs its own record if it is
|
|
wanted.
|
|
- **The reduced-contract idea is not lost, it is relocated.** What a given node can be asked to
|
|
do is its profile — the host's capability detection — and varies per machine without varying
|
|
what a node is.
|
|
|
|
## References
|
|
|
|
- [Research 006](../01-RESEARCH/006-mesh-from-scratch/00-overview.md) — the open question, and
|
|
requirement 6 that raised it.
|
|
- [ADR 0015](0015-mesh-brokers-nodes-host-agents-think.md) — *nodes host*; this says what a
|
|
node is.
|
|
- [Issue 007](../04-ISSUES/007-an-installed-package-is-not-a-capability/00-report.md) —
|
|
capability as something detected rather than assumed, which is where the reduced contract
|
|
now lives.
|