ADR 0135 supersedes 0133: a module version prepares its state before it runs

Two faults in 0133, both caught on review. It put the declaration on a container — one resource kind
the host applies — so every author would restate the machine's arrangement and a module's own
lifecycle would be tied to how its artifact happens to run. A module declares entrypoints for its
tools and its provisioner; preparing its state is the same vocabulary and nothing about a runtime.

And it derived the scope from the machine, which the facts already answer: a consumer is a module on
a machine (issue 022, migration 0015), so what the mesh provisions is per consumer. A module on three
machines has three databases, there is no shared state to race over, and the lock obligation 0133
invented was for a situation the mesh does not produce. The level question HAL answered with stages
dissolves — the scope of preparation is the scope of the state, and the mesh knows it.

0133 keeps its reasoning and gains a pointer; design 32 and issue 133 name the live record.
This commit is contained in:
2026-09-28 11:57:16 +02:00
parent 891c7a945e
commit 476cda417d
5 changed files with 175 additions and 17 deletions
+13 -11
View File
@@ -12,7 +12,7 @@ decisions:
- 02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md
- 02-DECISIONS/0083-one-push-leaves-the-mesh-consistent.md
- 02-DECISIONS/0129-a-seat-carries-the-protocol-of-its-role.md
- 02-DECISIONS/0133-a-module-owns-its-migrations-and-the-mesh-owns-when-they-run.md
- 02-DECISIONS/0135-a-module-version-prepares-its-state-before-it-runs.md
- 02-DECISIONS/0134-the-mesh-says-what-it-applied.md
---
@@ -260,13 +260,15 @@ queue.
and publishes it last-per-subject. A node that was away gets exactly the current one, never a
queue of superseded ones, and a replayed older one is refused by sequence.
**A version that needs its store prepared prepares it first.** A container may declare steps to run
before it — the same container, to completion, with different arguments — and the mesh derives them as
run-once resources placed ahead of it, so a schema change and the code that needs it arrive together or
not at all. The module owns what the step does; the mesh owns when it runs, and refuses to start the
container if it failed ([ADR 0133](../../02-DECISIONS/0133-a-module-owns-its-migrations-and-the-mesh-owns-when-they-run.md)).
Per node, because a node converges without waiting on its neighbours; a step that must happen once
mesh-wide belongs to a module holding a seat, which is what one holder on record already means.
**A version prepares its state before it runs.** A module version may declare an entrypoint that brings
its state to the shape that version needs — the same vocabulary as the entrypoints it declares for its
tools and its provisioner, and nothing about how a machine runs it. The mesh runs that entrypoint as it
runs the module's own code, to completion, in the module's own context, and a version whose preparation
did not succeed does not run: the rollout stops at the first machine that did not take it
([ADR 0135](../../02-DECISIONS/0135-a-module-version-prepares-its-state-before-it-runs.md), superseding
[ADR 0133](../../02-DECISIONS/0133-a-module-owns-its-migrations-and-the-mesh-owns-when-they-run.md)).
Once per state, and the mesh derives what a state is: a consumer is a module on a machine, so what the
mesh provisions is per consumer and preparation is too. No level to choose, and no race to lock against.
**Applying is reported to a role.** The host applies and reports to the `mesh-controller` seat —
not to an address it was given at genesis. Held and retried while the store restarts
@@ -469,9 +471,9 @@ billing existing under that name.
- **A manifest holds no subject.** A catalogue test: no manifest contains a string matching the
subject grammar. The rule is worthless if it is followed by convention.
- **A derived step is the container it precedes.** A composition test: the step's image, environment,
volumes and network equal that container's, so the two cannot drift — which is the failure the
hand-written kind has, three times over in the catalogue today.
- **A preparation is given what the module is given.** A composition test: what the preparation
entrypoint receives equals what the module's own code receives, asserted rather than written twice —
which is the drift a hand-written step invites, three times over in the catalogue today.
- **A convergence that changed nothing says nothing.** Two identical reports, one emitted fact: what is
guarded against is a fact per minute per machine, which is a stream nobody reads.
- **Permissions are exactly the three namespaces.** A composition test per module: the derived