Allow progressive insight, and apply two to the bus record

A record can assert a fact that goes stale while the decision it supports
stays right. Superseding for that buries a sound record under a second one
and makes every reader work out which is live. So a correction of fact is
now made in place, marked and dated, with the old wording quoted — bounded
by three conditions and checked by records.py, which fires on an unmarked,
undated or back-dated note. Judgements still supersede.

Applied to 0115: no conformance suite exists to recapture, and the full
genesis bed cannot run until the links exist. Designs 25 and 28 follow.
This commit is contained in:
2026-09-26 18:39:38 +02:00
parent 6ab113e6c6
commit 1c808898a5
7 changed files with 205 additions and 64 deletions
+29 -25
View File
@@ -316,26 +316,20 @@ including the two places their dependencies put a bed later than the step that n
real if the proofs divide with it. A step that cannot name what its bed proves is not a step, and is
divided further before it is started.
**Step 1 — the genesis bed**, a mesh raised on NATS from nothing:
- a node enrols over TLS with a claimed token, and the enrolment user cannot read a declaration;
- a push composes; the store is stopped; the push is held (nak with delay), the store returns, the
push applies, nothing was lost or duplicated;
- a node that was away gets exactly the newest declaration, and a replayed older one is refused
by sequence;
- an upgrade rolls out to two nodes;
- a module's tool is invoked from another node and from a person's client, each with an account
that can invoke it, and refused from one that cannot;
- a module's account cannot publish outside its `emits` nor subscribe outside its `consumes` —
refused by the server;
- a module acks a delivery from its own durable consumer, and is refused acking another module's;
- a user subscribes another module's or person's inbox prefix and is refused by the server, not
by the client's own good behaviour;
- an event whose consumer keeps failing dead-letters after `max-deliver`;
- an enrolment request held by a `nak`-with-delay cycle still reaches the enrolling node's inbox
once the controller answers — proving the reply travels in the payload and not the transport
field a consumer's ack has already claimed;
- the `nats` container is not recreated when only its composed configuration file changes, and
a change to that file is live (a new user can connect, a revoked one cannot) within one
**Step 1 — the genesis-broker bed**, a mesh raised from nothing, the server standing on it. The
mesh does not yet *live* on this bus — nothing speaks it until step 3's implementations exist — so
what this bed proves is the server, its configuration and the permissions, each of which the server
itself enforces and a plain client can therefore check:
- the four streams exist, asserted idempotently on a second start, with the retention of §3;
- every account and permission in the composed file is derived from the manifests' `emits` and
`consumes` and nothing else, with each user's own ack subject and its own inbox prefix;
- a user cannot publish outside its `emits` nor subscribe outside its `consumes` — refused by the
server, not by convention;
- a user cannot ack another user's delivery, and cannot subscribe another's inbox prefix — refused
by the server, not by the client's own good behaviour;
- the monitoring port is refused from anything but the private network;
- the `nats` container is not recreated when only its composed configuration file changes, and a
change to that file is live (a new user can connect, a revoked one cannot) within one
watcher-poll interval, without a restart.
**Step 2 — the adoption bed**, a mesh already running that has never had this server:
@@ -358,14 +352,24 @@ divided further before it is started.
- the shared library gained nothing but the binding: its surface is the protocol and the
primitives, and a helper that arrived with the transport is a review failure, not a detail.
**Step 4 — each converted flow against the behaviour it replaced:**
**Step 4 — the mesh living on it.** The implementations exist from step 3, so this is where a mesh
can first be raised on NATS and run:
- a node enrols over TLS with a claimed token, and the enrolment user cannot read a declaration;
- a push composes; the store is stopped; the push is held (nak with delay), the store returns, the
push applies, nothing was lost or duplicated;
- a node that was away gets exactly the newest declaration, and a replayed older one is refused
by sequence;
- an upgrade rolls out to two nodes;
- an enrolment request held by a `nak`-with-delay cycle still reaches the enrolling node's inbox
once the controller answers — proving the reply travels in the payload and not the transport
field a consumer's ack has already claimed;
- an event whose consumer keeps failing dead-letters after `max-deliver`;
- a module's tool is invoked from another node and from a person's client, each with an account
that can invoke it, and refused from one that cannot;
- a build source's change reaches the builder over the bus, and the build that follows is the one
the change asked for;
- an installation completes over the bus, with the same outcome the path it replaces produced;
- a module's reports arrive, and a node that was unreachable catches up rather than losing them;
- nothing of research 017's observation work is present — no heartbeat semantics, no condition
store — because that design is not written yet and a flow built ahead of it would have to be
rebuilt.
- a node that was unreachable catches up on its reports rather than losing them.
**Step 5 — the cutover bed:** a mesh on AMQP with a predecessor stand-in on the compatibility
broker moves its bus in one rollout; every node reports on NATS afterwards; the stand-in's client
+29 -24
View File
@@ -65,12 +65,12 @@ mirror rather than share (the host imports nothing, by
host's link, and the runtime's client. And a search for conformance fixtures finds none anywhere in
the four repositories: design 22's Phase 1.2 — the suite — has not been built.
> **A correction to ADR 0115, found in the measuring.** That record says step 3's fixtures are
> *recaptured* on NATS. There is nothing to recapture: the suite does not exist. Step 3 **builds**
> it, and its first job is to pin the wire the mesh has before changing it, because a suite written
> only against the new bus certifies whatever the new bus happens to do. The record's decision is
> unaffected; the word was wrong, and is corrected here rather than edited there
> ([`02-DECISIONS/README.md`](../../02-DECISIONS/README.md): a record's meaning is never edited).
> **This corrected the record.** ADR 0115 said step 3's fixtures were *recaptured* on NATS. There
> is nothing to recapture, so step 3 **builds** the suite, and its first job is to pin the wire the
> mesh has before changing it — a suite written only against the new bus certifies whatever the new
> bus happens to do. A fact went stale while the decision stood, which is a **progressive insight**
> ([`02-DECISIONS/README.md`](../../02-DECISIONS/README.md)): it is marked and dated in ADR 0115
> itself rather than left to be discovered here.
## The order the work actually allows
@@ -91,12 +91,12 @@ otherwise would put two beds where they cannot run.** Three edges decide it:
So step 1's bed proves *the server, from genesis, configured* — not a mesh living on it. The full
genesis bed is step 4's, where it can first run.
> **This differs from ADR 0115's check list, deliberately.** That record attributes "a mesh raised
> on NATS from genesis" to step 1. Measuring the dependency showed that bed cannot run until the
> links exist, and a step whose proof cannot run is the exact failure the record was written to
> prevent. The five steps, their names and the single rollout are unchanged; only where two beds
> run has moved. If that reads as a change of meaning rather than a correction of fact, the fix is
> a superseding record, not an edit.
> **This corrected the record too.** ADR 0115 first attributed "a mesh raised on NATS from genesis"
> to step 1. That bed cannot run until the links exist, and a step whose proof cannot run is the
> exact failure the record was written to prevent — so step 1 now ends at the server standing,
> correctly configured and carrying nothing, and the full bed is named under step 4. The five
> steps, their names, their order and the single rollout are unchanged; only where two beds run has
> moved. Marked and dated in ADR 0115 as a progressive insight, with what the record said before.
```
step 1 module, genesis places it ──┐
@@ -132,10 +132,15 @@ paper is wrong until there is a second mesh to find out.
- [ ] 1.6 the genesis-broker bed
**Done when.** A mesh raised from nothing has the server standing with the streams asserted and
every account and permission composed from the manifests; the monitoring port is refused from
anything but the private network; a change to the composed file is live within one watcher interval
without a restart, and the container is not recreated by it. No mesh traffic is on it yet — that is
step 4's bed, not this one's.
every account and permission composed from the manifests; a user cannot publish outside its
`emits`, subscribe outside its `consumes`, ack another user's delivery or subscribe another's inbox
prefix; the monitoring port is refused from anything but the private network; a change to the
composed file is live within one watcher interval without a restart, and the container is not
recreated by it.
**The permission checks belong here rather than later** because the server enforces them itself — a
plain client proves them, no link required — and they are the whole of what ADR 0043 asks for. No
mesh traffic is on the bus yet; that is step 4's bed, not this one's.
## Step 2 — adoption puts it in the seat
@@ -191,14 +196,14 @@ module.
**Why here.** The links exist from step 3, so the flows that are not on the bus at all can move onto
it, and the beds that need a mesh living on NATS can finally run.
- [ ] 4.1 **the full genesis bed** — a mesh raised on NATS from nothing: a node enrols over TLS with
a claimed token and the enrolment user cannot read a declaration; a push is held while the
store restarts and applies after, nothing lost or duplicated; a node that was away gets
exactly the newest declaration and refuses a replayed older one by sequence; an upgrade rolls
out to two nodes; an event dead-letters after `max-deliver`; a module cannot publish outside
its `emits`, ack another module's delivery, or subscribe another's inbox prefix; and an
enrolment held by a `nak`-with-delay cycle still reaches the enrolling node, proving the reply
travels in the payload and not the transport field the consumer's ack has claimed
- [ ] 4.1 **the full genesis bed** — a mesh raised on NATS from nothing and living on it: a node
enrols over TLS with a claimed token and the enrolment user cannot read a declaration; a push
is held while the store restarts and applies after, nothing lost or duplicated; a node that
was away gets exactly the newest declaration and refuses a replayed older one by sequence; an
upgrade rolls out to two nodes; an event dead-letters after `max-deliver`; and an enrolment
held by a `nak`-with-delay cycle still reaches the enrolling node, proving the reply travels
in the payload and not the transport field the consumer's ack has claimed. The server-enforced
permissions were proved at step 1 and are not re-proved here
- [ ] 4.2 a build source's change reaches the builder over the bus, and the build that follows is
the one the change asked for
- [ ] 4.3 an installation completes over the bus, with the same outcome as the path it replaces