Design 47 says what a node composes from: placement with the node's decided facts and settings layers, and the node's own record (issue 1126, ADR 0549, ADR 0555)

This commit is contained in:
2026-10-26 18:20:51 +01:00
parent 515c405c89
commit 0488bc1801
@@ -4,6 +4,7 @@ status: in-progress
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks]
updated: 2026-10-26
decisions:
- "ADR 0555"
- "ADR 0551"
- "ADR 0550"
- "ADR 0549"
@@ -663,7 +664,7 @@ backup holder backs up nothing, and the have says so.
## Compositions, wants and the apply
*ADR 0360 §8, §9, ADR 0377, ADR 0429 §4, §6, ADR 0539 §9, §14 to §16, ADR 0547 §2 to §9.*
*ADR 0360 §8, §9, ADR 0377, ADR 0429 §4, §6, ADR 0539 §9, §14 to §16, ADR 0547 §2 to §9, ADR 0549, ADR 0555.*
- **Each node composes its own.** For each want `want.<node>.<module>` the node agent composes that module for
its own node with mesh-sdk's composition from the manifest by digest the indexer wrote, the module's resolved
@@ -672,6 +673,36 @@ backup holder backs up nothing, and the have says so.
own composition (adoption, firewall openings, accounts, the resolver, identities and groups) from the same
inputs. Of other nodes it reads only their public records and the manifests wanted on them, which its firewall
and resolver need. Nothing composed crosses the bus, so nothing composed is signed (ADR 0547 §2).
- **What a node composes from, and who writes it.** One composer, mesh-sdk's, has three callers: the node agent for
its own node, the assigner's composition check for every node, and the grants part. Each fills the composition's
input from the bus with its own credential and nothing else (ADR 0547 §2, ADR 0549 §3):
- **placement**, the indexer's state `placement`, one key `placement.<node>` read at each catalogue merge from
the node's placement file and said by `placement-changed` (ADR 0549 §2);
- **the node records**, the node-engine's state `records`, one key `record.<node>` written by that node's own
agent and said by `node-record-changed` (ADR 0555 §3);
- **the manifests**, the indexer's `modules.<module>` and its manifests by digest, or the digest the composing
node's want names where it runs another build; the private network's manifest comes with mesh-sdk;
- **the config values**, mesh-config's resolved state, the composing node's slice alone for a node agent.
- **The placement file.** One file per node in the catalogue, changed only by a pull request and checked before
it merges (ADR 0549 §1, ADR 0555). It holds what a person decides of the node and nothing a machine observes:
- the node's decided facts: its endpoint and site, whether it is the private network's hub, its address on the
private network (a decision written once at enrolment; nothing allocates one at run time), the domain its
routed names are composed under, its operator and agent logins by name with their homes, and whether it is
adopted with the modules taken on it. No secret and no key material;
- its modules in the order the composition reads them, each with its host ports by the port the software
listens on, its bindings by provision, and its settings placement (`places`, `accesses`, `networks`,
`endpoints`, `expose`, `reach`, `ports`) as two layers: the mesh-wide one, repeated in every node's file so a
node reads its own key alone, and the node's own, with a mark when the node has a layer that holds no placement,
since an empty layer still carries the module's config values;
- its pins by provision, and the seats its modules hold.
The catalogue's check refuses a placement naming a module it does not hold or a node not enrolled, two modules
of one node on one host port, a pin, binding or holding naming a provider not placed where it says, a seat held
once for the mesh held twice, two nodes with one address and more than one hub, each named in one answer.
- **The node record.** What the machine observes of itself: its tunnel's public key, its capabilities, the
public halves of its sealing and serving keys, the certificate issued for its internal name, its outward links
and networks, its node-engine's contract, the tunnel found on it, and on the hub alone whether the hub adopted
that tunnel and every peer it carries. Written at start and when an observed fact changes, only when it
differs (ADR 0555 §3).
- **Composed again on events, never on a timer.** A changed input at the same fingerprint (a setting or given
value, a secret rotated or moved, a credential issued, a provider's contribution, a peer added to the hub) is
composed again when its event is heard, and applied as a revision of what runs (ADR 0547 §2).