diff --git a/03-DESIGN/01-to-be/00-work-breakdown.md b/03-DESIGN/01-to-be/00-work-breakdown.md index 243517a..3812141 100644 --- a/03-DESIGN/01-to-be/00-work-breakdown.md +++ b/03-DESIGN/01-to-be/00-work-breakdown.md @@ -2,7 +2,7 @@ layer: to-be status: designed code: [hal] -updated: 2026-08-23 +updated: 2026-08-29 decisions: [02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md] --- diff --git a/03-DESIGN/01-to-be/01-end-to-end-testing.md b/03-DESIGN/01-to-be/01-end-to-end-testing.md index ad240bf..192379e 100644 --- a/03-DESIGN/01-to-be/01-end-to-end-testing.md +++ b/03-DESIGN/01-to-be/01-end-to-end-testing.md @@ -2,7 +2,7 @@ layer: to-be status: in-progress code: [mesh-lab] -updated: 2026-08-23 +updated: 2026-08-28 decisions: - 02-DECISIONS/0016-the-lab.md - 02-DECISIONS/0016-the-lab.md diff --git a/03-DESIGN/01-to-be/02-scenario-declaration.md b/03-DESIGN/01-to-be/02-scenario-declaration.md index 5127dda..ce3b7c5 100644 --- a/03-DESIGN/01-to-be/02-scenario-declaration.md +++ b/03-DESIGN/01-to-be/02-scenario-declaration.md @@ -2,7 +2,7 @@ layer: to-be status: in-progress code: [mesh-lab] -updated: 2026-08-25 +updated: 2026-08-28 decisions: - 02-DECISIONS/0016-the-lab.md - 02-DECISIONS/0016-the-lab.md diff --git a/03-DESIGN/01-to-be/03-scenario-lifecycle.md b/03-DESIGN/01-to-be/03-scenario-lifecycle.md index 21343f4..7a0ecc7 100644 --- a/03-DESIGN/01-to-be/03-scenario-lifecycle.md +++ b/03-DESIGN/01-to-be/03-scenario-lifecycle.md @@ -2,7 +2,7 @@ layer: to-be status: in-progress code: [mesh-lab] -updated: 2026-08-25 +updated: 2026-08-28 decisions: - 02-DECISIONS/0016-the-lab.md - 02-DECISIONS/0016-the-lab.md diff --git a/03-DESIGN/01-to-be/04-lab-installation.md b/03-DESIGN/01-to-be/04-lab-installation.md index d756022..30410d1 100644 --- a/03-DESIGN/01-to-be/04-lab-installation.md +++ b/03-DESIGN/01-to-be/04-lab-installation.md @@ -2,7 +2,7 @@ layer: to-be status: designed code: [mesh-lab] -updated: 2026-08-24 +updated: 2026-08-28 decisions: - 02-DECISIONS/0016-the-lab.md - 02-DECISIONS/0010-delivery.md diff --git a/03-DESIGN/01-to-be/05-the-node-host.md b/03-DESIGN/01-to-be/05-the-node-host.md index e45d6a2..057043f 100644 --- a/03-DESIGN/01-to-be/05-the-node-host.md +++ b/03-DESIGN/01-to-be/05-the-node-host.md @@ -2,7 +2,7 @@ layer: to-be status: in-progress code: [mesh-host] -updated: 2026-08-30 +updated: 2026-08-31 decisions: - 02-DECISIONS/0019-how-this-repository-works.md - 02-DECISIONS/0004-a-node-and-how-it-joins.md @@ -190,6 +190,19 @@ Raising the substrate needs six shapes in the host's vocabulary, and **all six a | `container` | **built** | pinned by digest ([ADR 0006](../../02-DECISIONS/0006-the-substrate-and-the-control-plane.md)); identified by a label carrying a digest of the declaration that made it, because a runtime normalises what it is given and that is indistinguishable from drift | | `action` | **built** | bundle-only ([ADR 0005](../../02-DECISIONS/0005-the-node-host.md)); verify is mandatory and is the idempotency check as well as the read-back | +**A service says what it must reflect, and that is declared state rather than a command.** +`restart-on` names files whose change means the unit must be restarted — because a running service +does not re-read its configuration, and replacing a file, finding the service already running and +doing nothing leaves a machine behaving the way it did before while every check passes. A *command* +to restart would be an action, and the link may not carry one, so this is the shape that rule +leaves rather than a way around it. + +**It may name a file another module put there**, written `.`. The case that needed it: +a resolver restarting when the mesh rewrites the names, which are computed by the mesh and belong +to its module rather than to the daemon's. Without it the daemon serves the names it started with +for ever — every machine that joined afterwards unreachable by name, and every check passing. An +unqualified name still means *my own*, so the common case reads as it always did. + **An action's verify is the definition of what the action is for**, and the action's own idea of being finished must be the same one. *Written 2026-08-31, after this went wrong.* If an action waits on one test and its verify reads back another, the two can disagree — and then the action diff --git a/03-DESIGN/01-to-be/07-the-substrate.md b/03-DESIGN/01-to-be/07-the-substrate.md index 70c3660..9c1beab 100644 --- a/03-DESIGN/01-to-be/07-the-substrate.md +++ b/03-DESIGN/01-to-be/07-the-substrate.md @@ -5,7 +5,7 @@ code: - mesh-host examples/substrate-first-node.lock - mesh-host internal/apply - mesh-lab test/integration/mesh.test.ts (a bare machine becomes a mesh) -updated: 2026-08-30 +updated: 2026-08-31 decisions: - 02-DECISIONS/0004-a-node-and-how-it-joins.md - 02-DECISIONS/0005-the-node-host.md diff --git a/03-DESIGN/01-to-be/08-connectivity.md b/03-DESIGN/01-to-be/08-connectivity.md index 5180bd0..627fae0 100644 --- a/03-DESIGN/01-to-be/08-connectivity.md +++ b/03-DESIGN/01-to-be/08-connectivity.md @@ -420,17 +420,28 @@ tmpfiles — is shaped that way. Until there is one, a module ships a unit that the better shape: how a machine enforces rules is a fact about the machine, and the mesh has no business depending on what a distribution happens to package. -**One thing is derived from what is assigned and not yet from the overlay's shape**, and it is -stated here rather than discovered: **a hub's own listening port.** A hub accepts inbound -connections from every node at other sites; a node that is not a hub dials out and needs nothing -open, because a reply to a flow it started is already accepted. So the two want different rules on -an identical module — and `listens` is a static field on a manifest, while the overlay module's -resources are computed per node. +**One rule is derived from the overlay's shape rather than from what is assigned: a hub's own +listening port.** A hub accepts inbound connections from every node at other sites; a machine that +is not a hub dials out and needs nothing open, because a reply to a flow it started is already +accepted. The two want different rules on an *identical module*, so `listens` — a static field — +cannot say it. The machine a static answer gets wrong is the one facing the public internet, which +is the machine that most needs filtering. -A machine that is not a hub is therefore correct today, and **a hub would have its own port closed -by a rule set derived this way.** The fix is that a computed module contributes listens the way it -contributes resources; until it exists, the firewall belongs on machines that are not hubs, and -this paragraph is the reason rather than an oversight to find later. +*Recorded as a gap on 2026-08-31 and closed the same day.* **A computed module now contributes +listens the way it contributes resources.** The port comes from the endpoint, which is where the +interface takes its `ListenPort` from — one source, so a rule set cannot open a port the interface +is not on. It is open to *everywhere* deliberately: a node at another site is not on the private +network until this port lets it on, so restricting it to the mesh would be a rule that can never +be satisfied by the thing it exists for. + +**A generator that cannot say what a machine opens is refused, not read as silence.** Closing a +port on the evidence of a failure to look is how a machine is severed by a fault somewhere else — +and the machine it would sever is the hub, whose only route to being repaired is the network it +just closed. + +*Checked by filtering the hub and then requiring the mesh to keep working: a declaration still +reaches the other machine, and the other machine still reaches the hub. A rule file that looks +right and a mesh that has stopped are exactly what that guards against.* **And it is enforced, which is what separates this from `scope:`.** Checked on two real machines: two ports opened, one declared, and from the other machine the declared one answers and the diff --git a/03-DESIGN/01-to-be/09-the-node-lifecycle.md b/03-DESIGN/01-to-be/09-the-node-lifecycle.md index 3bb36f2..d4772c2 100644 --- a/03-DESIGN/01-to-be/09-the-node-lifecycle.md +++ b/03-DESIGN/01-to-be/09-the-node-lifecycle.md @@ -8,7 +8,7 @@ code: - mesh-host packaging/nox-mesh-host-network.sh - mesh-control internal/token - mesh-control internal/inventory/nodes.go -updated: 2026-08-27 +updated: 2026-08-31 decisions: - 02-DECISIONS/0004-a-node-and-how-it-joins.md - 02-DECISIONS/0005-the-node-host.md diff --git a/03-DESIGN/01-to-be/10-delivery.md b/03-DESIGN/01-to-be/10-delivery.md index 1f6db5a..5d0073b 100644 --- a/03-DESIGN/01-to-be/10-delivery.md +++ b/03-DESIGN/01-to-be/10-delivery.md @@ -5,7 +5,7 @@ code: - mesh-control internal/builder - mesh-control cmd/mesh-control (build, build --behind, push, status) - mesh-control internal/inventory/builds.go -updated: 2026-08-28 +updated: 2026-08-31 decisions: - 02-DECISIONS/0010-delivery.md - 02-DECISIONS/0009-modules-and-the-graph.md