ADR 0100 accepted; the node host, connectivity, the node lifecycle and raising a mesh amended for a node adopted before it is converged
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-host]
|
||||
updated: 2026-09-21
|
||||
updated: 2026-09-22
|
||||
decisions:
|
||||
- 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md
|
||||
- 02-DECISIONS/0019-how-this-repository-works.md
|
||||
- 02-DECISIONS/0004-a-node-and-how-it-joins.md
|
||||
- 02-DECISIONS/0005-the-node-host.md
|
||||
@@ -130,6 +131,19 @@ the link; never asked downward.
|
||||
[`09-the-node-lifecycle.md`](09-the-node-lifecycle.md)**, in full and in one place. This document
|
||||
is the component; that one is what happens to it.
|
||||
|
||||
## What it finds, on an adopted node
|
||||
|
||||
*2026-09-22, [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md).* A declaration says whether the node is adopted. On an adopted node
|
||||
the host does not replace a file it finds at a declared path: it records what was there — its
|
||||
content, so the original is kept before anything is written — and holds the file as found. A
|
||||
module's files are converged when that module is assigned, because assigning a module is
|
||||
migrating it; the rest when the node is converged. The host's report says which files it is
|
||||
holding rather than converging, so an adopted node never reads as converged. This is the
|
||||
companion the host's ownership rule needed: *never touch what you did not create, unless adoption
|
||||
made it yours — and while the node is adopted, keep it as you found it.* *How it is checked:*
|
||||
unit tests hold the host to keeping a found file on an adopted node and replacing it on a
|
||||
converged one, and the adoption bed asserts a found file byte for byte unchanged.
|
||||
|
||||
## Where a declaration comes from
|
||||
|
||||
One behaviour, two sources
|
||||
|
||||
@@ -7,8 +7,9 @@ code:
|
||||
- mesh-controller internal/identity/authority.go
|
||||
- mesh-host internal/identity/serving.go
|
||||
- mesh-host internal/apply (the service that reflects a rule set)
|
||||
updated: 2026-09-21
|
||||
updated: 2026-09-22
|
||||
decisions:
|
||||
- 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md
|
||||
- 02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md
|
||||
- 02-DECISIONS/0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md
|
||||
- 02-DECISIONS/0005-the-node-host.md
|
||||
@@ -532,6 +533,20 @@ undeclared one does not — then the module is removed and the port closes with
|
||||
rule. *A rule set that is written but never loaded passes every check that reads the file, which
|
||||
is why the check reads packets.*
|
||||
|
||||
### On an adopted node
|
||||
|
||||
*2026-09-22, [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md).* **The firewall found on the machine stays in force**, and the mesh
|
||||
loads no table of its own there — neither genesis's base ruleset nor the derived one. The kernel
|
||||
runs every table at a hook and a drop in any is final, so a second, stricter table would close
|
||||
every port the machine serves. What the mesh needs reachable — its foundation's ports and each
|
||||
migrated module's `listens` — it opens *through the found firewall*, as rules marked as the mesh's,
|
||||
and it removes only rules it marked. Converging the node replaces the found firewall with the
|
||||
derived filter in one step, after previewing which open ports will close. The mesh must speak the
|
||||
found firewall in its own terms; one kind is found on the machines measured, and a machine with
|
||||
another is not covered until someone writes for it. *How it is checked:* the adoption bed asserts
|
||||
the found firewall's rules differ only by the mesh's marked rules, that a second machine enrols
|
||||
through them, and that after the flip the declared port is open and the undeclared one closed.
|
||||
|
||||
## 5 — Certificates
|
||||
|
||||
**Two authorities, kept separate on purpose.**
|
||||
|
||||
@@ -8,8 +8,9 @@ code:
|
||||
- mesh-host packaging/nox-mesh-host-network.sh
|
||||
- mesh-controller internal/token
|
||||
- mesh-controller internal/inventory/nodes.go
|
||||
updated: 2026-08-31
|
||||
updated: 2026-09-22
|
||||
decisions:
|
||||
- 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md
|
||||
- 02-DECISIONS/0004-a-node-and-how-it-joins.md
|
||||
- 02-DECISIONS/0005-the-node-host.md
|
||||
- 02-DECISIONS/0004-a-node-and-how-it-joins.md
|
||||
@@ -282,8 +283,23 @@ runs. Building the start mechanism before deciding that would be building it for
|
||||
|
||||
## Adoption: what happens to what is already there
|
||||
|
||||
Adoption is not a state. It is what the **first apply** does when it is told to own something a
|
||||
machine already has ([research 012](../../01-RESEARCH/012-the-minimum-viable-node/00-overview.md)).
|
||||
**An enrolled node is adopted or converged, and the mesh records which** ([ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md)).
|
||||
This was once said the other way — adoption as only what the first apply does — and a machine
|
||||
being migrated from a mesh already running on it made the middle state last: while its services
|
||||
move one at a time, what it already has must stay in force. So *adopted* is a second axis of an
|
||||
enrolled node, not a step on the path above: a machine in use is enrolled adopted, and stays so
|
||||
until its migration is done and the operator converges it. A machine that was empty is enrolled
|
||||
converged, as before
|
||||
([research 012](../../01-RESEARCH/012-the-minimum-viable-node/00-overview.md)).
|
||||
|
||||
On an adopted node the firewall found there stays in force and the mesh opens what it needs
|
||||
through it ([08-connectivity](08-connectivity.md)); a file found at a path the mesh declares is
|
||||
kept until the module declaring it migrates ([05-the-node-host](05-the-node-host.md)).
|
||||
**Converging is one act per node, previewed**: it lists every port the found firewall allows and
|
||||
whether an assigned module declares it or it will close, then loads the mesh's own filter, retires
|
||||
the found one and converges what was kept. *How it is checked:* a lab bed prepares a machine the
|
||||
way a predecessor leaves one and asserts nothing on it changes until the flip, and that the flip
|
||||
closes exactly what the preview said.
|
||||
|
||||
A candidate machine is not empty. It has a package manager, probably a container runtime,
|
||||
configuration somebody chose. [ADR 0005](../../02-DECISIONS/0005-the-node-host.md)
|
||||
|
||||
@@ -5,8 +5,9 @@ code:
|
||||
- mesh-host cmd/mesh-bootstrap
|
||||
- mesh-host internal/bootstrap
|
||||
- mesh-lab test/integration/whole-mesh-full.test.ts
|
||||
updated: 2026-09-21
|
||||
updated: 2026-09-22
|
||||
decisions:
|
||||
- 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md
|
||||
- 02-DECISIONS/0067-genesis-is-a-pivot.md
|
||||
- 02-DECISIONS/0069-a-module-is-a-repository-and-a-path.md
|
||||
- 02-DECISIONS/0006-the-substrate-and-the-control-plane.md
|
||||
@@ -97,6 +98,20 @@ the temporary one.** The pivot is complete: what raised the mesh is gone, and wh
|
||||
like any other. From here the mesh can build and roll out its own upgrades, including to the thing
|
||||
that runs it.
|
||||
|
||||
### Genesis on a machine in use
|
||||
|
||||
*2026-09-22, [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md).* A control-node that is already running a predecessor mesh is raised
|
||||
**adopted**. The predecessor's control on it is stopped first — the daemons that write its
|
||||
configuration — and its services keep running. **Every port the foundation binds is an input to
|
||||
genesis**, not a constant in the bundle or the catalogue, and genesis checks each is free before it
|
||||
raises anything, refusing with the name of what holds it. On such a machine the store's and the
|
||||
bus's usual ports were free and the registry's, the broker's management port and the private
|
||||
network's port were held. Genesis adopted **does not load the base ruleset**: the machine's own
|
||||
firewall already filters, and the mesh opens its foundation's ports through it
|
||||
([08-connectivity](08-connectivity.md)). *How it is checked:* the adoption bed raises genesis
|
||||
with the registry's port held and asserts the refusal names its holder, then with another port
|
||||
given asserts the foundation comes up and the machine's service is still reachable.
|
||||
|
||||
## After the pivot, and still part of installing
|
||||
|
||||
Genesis ends with a mesh of one that runs, and that is not the same as a mesh that works. What it
|
||||
|
||||
Reference in New Issue
Block a user