Order the records the way the system is learned

Jochen asked whether the order made sense. It did not -- it followed when
things happened to be decided, which after consolidation is fictional anyway
since record 5 alone folds decisions taken across a week.

Concretely wrong before: the domain statement sat at 8, after five engineering
rules; the constitution was scattered across 5, 12 and 17; the tiers landed at
15, 16, 21 and 22 with process records in between.

Now it walks: what the mesh is (1-3), its tiers from the bottom up (4-8), what
runs on them and how it gets there (9-10), how it is built (11-16), how it is
checked (17-18), how we work (19-23).

Two things made this safe rather than free. It is a permutation, not a
compaction, so the renames go through temporary names -- otherwise two files
want one slot and one is lost. And the reference rewrite is a single
simultaneous pass, because almost every number moved into a slot another number
was vacating; replacing one at a time would have cascaded and pointed things at
the wrong record while still resolving.

Verified: 284 [ADR NNNN](path) links across the repository, all with matching
text and target.

The ordering principle is now stated in 19 rather than left implicit -- the
repository already said "the numbering is the flow" about its folders, and
there was no reason for the records to be the exception.
This commit is contained in:
2026-08-28 23:30:42 +02:00
parent e1febe8e0f
commit 333356cff3
85 changed files with 471 additions and 465 deletions
@@ -149,7 +149,7 @@ Steps 2 and 3 happen **before there is a mesh to do them**. So provisioning is n
control-plane service that consumers use; it is part of the bootstrap, and part of what the
carried bundle has to be able to express.
**Which strains what a declaration is.** [ADR 0016](../../02-DECISIONS/0016-the-node-host.md)
**Which strains what a declaration is.** [ADR 0005](../../02-DECISIONS/0005-the-node-host.md)
has the host applying *declared state on this machine*. A database inside a running store is not
a file or a unit — and at bootstrap it is, at least, local: the store is on the same machine as
the host applying the bundle.
@@ -158,7 +158,7 @@ Later it is not. A consumer on one node provisioned from a store on another is t
case, and reaching it is not the host's job.
**Resolved as two mechanisms, which is the answer rather than a compromise**
([ADR 0016](../../02-DECISIONS/0016-the-node-host.md)). The host
([ADR 0005](../../02-DECISIONS/0005-the-node-host.md)). The host
runs bootstrap actions locally from the bundle; the control plane provisions across the mesh
afterwards. Different actors, different scopes, different trust paths — so there is no single
operation with a tier boundary running through it.
@@ -279,7 +279,7 @@ of them is work.
| Group | What happens under the rule |
|---|---|
| **The owner and its machinery** — the mesh module, the SDK, the environment and configuration synchronisers, secrets | Nothing. It owns the database. |
| **Node appliers** — the overlay, the shell daemon, the resolver | **Already resolved.** [ADR 0016](../../02-DECISIONS/0016-the-node-host.md) stops the host querying the mesh database, decided for tier reasons with nothing to do with this. |
| **Node appliers** — the overlay, the shell daemon, the resolver | **Already resolved.** [ADR 0005](../../02-DECISIONS/0005-the-node-host.md) stops the host querying the mesh database, decided for tier reasons with nothing to do with this. |
| **Foreign tenants** — the work engine (10 tables), the knowledge base (2), pipeline logs (1) | They need **their own database**. They are not reading the registry; they are storing their own data in it. |
| **Genuine cross-context reads** — the work engine reads `nodes`; two others read a handful | The only ones needing an interface or events. |
@@ -299,7 +299,7 @@ estimate. **The rule holds.**
The remaining cross-context reads need one or the other. **Neither is SQL** — under exclusive
ownership a module runs SQL against its own database and nothing else, whatever transport a
query might travel over. Both options are the mesh's own channel, and both ride the broker
([ADR 0001](../../02-DECISIONS/0001-nodes-communicate-over-a-broker.md)), so the transport is
([ADR 0002](../../02-DECISIONS/0002-nodes-communicate-over-a-broker.md)), so the transport is
not the distinction.
**The distinction is where the answer lives when you need it.**
@@ -312,7 +312,7 @@ not the distinction.
| when the other side is down | you cannot answer | you answer from your copy |
| what you must handle | a round trip that can fail | events you missed while you were down |
**What decides is not taste.** [ADR 0015](../../02-DECISIONS/0015-a-node-and-how-it-joins.md)
**What decides is not taste.** [ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md)
makes disconnection an ordinary situation rather than an exception. So:
> **Anything that must keep working while disconnected cannot use a request** — there is nobody
@@ -354,14 +354,14 @@ proves it cannot be a global rule.
**What happens to a grant when the consumer is removed?** The game is uninstalled. Its database
still exists, holding its data. Dropping it silently is data loss; keeping it forever is a leak.
[ADR 0016](../../02-DECISIONS/0016-the-node-host.md) says
[ADR 0005](../../02-DECISIONS/0005-the-node-host.md) says
the host removes what it applied and no longer declares — but this is not on the host, it is
inside another module's state, and the same reasoning does not obviously carry.
**Where does node-derived configuration come from?** (3) The control plane composes a
declaration, and cannot know this machine's memory. Either the host fills in a blank the
declaration leaves — which makes the host decide something, against
[ADR 0016](../../02-DECISIONS/0016-the-node-host.md) — or the control
[ADR 0005](../../02-DECISIONS/0005-the-node-host.md) — or the control
plane reads the node's inventory first and composes with it. The second is consistent and means
a declaration is composed *per node from what the node reported*, which is a stronger claim than
anything recorded so far.
@@ -419,9 +419,9 @@ But two things differ *between* them, and both matter more than the similarity.
### The broker cannot be managed over the broker
[ADR 0001](../../02-DECISIONS/0001-nodes-communicate-over-a-broker.md) makes the broker the
[ADR 0002](../../02-DECISIONS/0002-nodes-communicate-over-a-broker.md) makes the broker the
channel every node takes work from, and
[ADR 0015](../../02-DECISIONS/0015-a-node-and-how-it-joins.md) makes it the security
[ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md) makes it the security
boundary — everything a node applies arrives through it.
So the module providing the broker is also **the way modules are managed**. A declaration cannot
@@ -430,7 +430,7 @@ reconfigured. Nothing else in the catalogue has that property; the store is cons
control plane but is not how the control plane *reaches* anything.
This is exactly what the carried bundle exists for
([ADR 0015](../../02-DECISIONS/0015-a-node-and-how-it-joins.md)): the broker is raised from
([ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md)): the broker is raised from
what the host carries, before there is a channel, because there is no other way to raise it.
Recorded here because it is a constraint on *one module*, not a general rule, and a schema with
no way to say so hides it.
@@ -439,7 +439,7 @@ no way to say so hides it.
The broker is one per mesh — a single point of failure and a single point of trust, by decision
rather than by accident. The store cannot be: a node that must keep working while disconnected
([ADR 0015](../../02-DECISIONS/0015-a-node-and-how-it-joins.md)) cannot depend on a database
([ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md)) cannot depend on a database
somewhere else.
Same nine properties, opposite answers. Which settles something the cases file left open: **how