Answer the last review round of batch 4: the recovery module's acts, order, callers and grants

Its verbs answer on acceptance and its events carry the act's form and fingerprint,
it never restores beside the nightly dump either way, a node-engine may call it only
for a want its node holds, and its grants are listed whole as ADR 0672 has them; the
long form of an invokes entry is read by the second reader release first.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 13:06:14 +01:00
parent 6d0506402d
commit a3d9975e4b
3 changed files with 132 additions and 61 deletions
@@ -5,6 +5,7 @@ design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0672"
- "ADR 0667"
- "ADR 0666"
- "ADR 0660"
@@ -43,17 +44,20 @@ that round are written into the lines they name, here. Questions that an earlier
- §516 **A restore point's bytes, and the forms of `snapshot-kept` and `restore-kept`.** (§551, §554) The seat
`mesh-recovery`'s two verbs (§554) take and answer the forms mesh-contracts' definition gave the seat `mesh-broker`'s,
which move to `mesh-recovery` and which this line makes the design's: `snapshot-kept` takes `module`, `kept` (the
kept data's local name), `form`, `fingerprint`, `why` and `catch-up` as `{tool, arguments}` (§451), and answers
`point` (the module, the kept data, its form, the fingerprint, `snapshot`, `consumers` with each durable consumer's
stream, name and acknowledged sequence, `size` in bytes, `at` and `catch-up`) or `error` alone; `restore-kept` takes
kept data's local name), `form`, `fingerprint`, `why` and `catch-up` as `{tool, arguments}` (§451); its point
(the module, the kept data, its form, the fingerprint, `snapshot`, `consumers` with each durable consumer's
stream, name and acknowledged sequence, `size` in bytes, `at` and `catch-up`) comes on its event `ended` (§554); `restore-kept` takes
`module`, `kept`, `form`, `fingerprint`, `why`, `from-backup` (yes or no) and one of `snapshot` (the restore point's
name), `aside-only` or `discard-aside` (an aside's `id`), and answers `restored`, `aside`, `missing` (true when the
point is not in the recovery module's directory) and `error`. No argument `local-name` or `from` is taken, and a
name), `aside-only` or `discard-aside` (an aside's `id`), and its result (`restored`, `aside`, `missing`, true when the
point is not in the recovery module's directory, and `error`) comes on its event `restored`. Both verbs answer only
`accepted`, `busy` or `error` (§554). No argument `local-name` or `from` is taken, and a
catch-up is never text.
- **Where a point lives.** The recovery module takes a point through the bus's stream snapshot under its own account
(§554), one bus object of the kept data at a time (its stream, or the stream under its bucket or object store),
with ADR 0235 §10's pacing and §11's bounds, and writes it with the point's record in its own data directory,
`points/<module>/<kept>/<form>-<fingerprint>`, each token escaped as a key's name is (§73) and a token that is
with ADR 0235 §10's pacing and §11's bounds, and writes it with the point's record under a temporary name, renamed to its own name only once the point is
whole (as ADR 0235 §2 writes the dump), in its own data directory, `points/<module>/<kept>/<form>-<fingerprint>`;
at its start it removes every point left under a temporary name, so a point cut off by a restart, the bus away or
its bound is never listed nor restored; each token escaped as a key's name is (§73) and a token that is
empty, `.` or `..` refused; that name is the point's `snapshot`.
- **Its copy.** That directory is an item of the recovery module's manifest `data`, backed up by the holder of
`node-backup` on its node as every item is (ADR 0404), which stores the copy and nothing else. When
@@ -62,15 +66,16 @@ that round are written into the lines they name, here. Questions that an earlier
verb always does, takes the point from there and restores it; when no repository snapshot holds it, `restored`
says `failed` with `restore point missing`, and §300 holds the revert.
- **The aside, and a restore that fails.** `restore-kept` sets the live kept data aside by taking a stream snapshot
of each of its bus objects into `aside/<module>/<kept>/<at>` in the same directory (`at` the UTC time written
`20261111T121200Z`, with `-2`, `-3` and on added when that name exists), only then removes the live objects,
of each of its bus objects into `aside/<module>/<kept>/<at>` in the same directory, reads the aside back to check it (`at` the UTC time written
`20261111T121200Z`, with `-2`, `-3` and on added when that name exists), only then removes the live objects (whether that removal needs a person's warrant waits for the operator, ADR 0672
review K3),
restores the point under their names and sets each consumer to its recorded sequence. Each step is written first
in the aside's record (`set aside`, `removed`, `restored`): when a step after the removal fails, `restore-kept`
restores the aside under the live names and sets the consumers back before it answers `failed`, and at its start
the recovery module does the same for every aside whose record ends at `removed`, so a failed or stopped restore
never leaves the kept data gone. The aside's `id` is that directory's name, its `name` the bus name it was live
under, its `size` its bytes on disk; nothing of an aside stays on the bus. `discard-aside` removes that directory
and nothing else. A restore point is removed only as §551 says.
and nothing else, an `id` holding `.`, `..` or `/` refused. A restore point is removed only as §551 says.
This completes §405 and §406. Why: the operator's answer of 12:55 CET (§554) puts the taking and restoring of a
module's kept data on the live bus on a module of its own; the server restores a stream only where no stream of that
@@ -80,10 +85,10 @@ that round are written into the lines they name, here. Questions that an earlier
module, backup holder, bus), a point is taken, its directory removed, brought back with `from-backup` and restored,
the live data's aside listed with its size and the consumer at its recorded sequence; a point missing from both says
`restore point missing`; a restore made to fail after the removal, and one stopped there and started again, leave
the live data as before.
the live data as before; a point cut off half way is removed at start and never listed.
- §517 **The recovery module lists what it holds.** The seat `mesh-recovery`'s read verb `kept-points` (class `read`,
§391's default callers) lists every restore point and aside in its directory with its module, kept data, form,
fingerprint, size and `at`, and its tools are `recovery_kept_points`, which reads the same, and
fingerprint, size and `at`, and the act that runs, with since when and what it waits on (§554); its tools are `recovery_kept_points`, which reads the same, and
`recovery_expire_points`, which runs §551's removal now (class `act`, §391's default callers, written in the
hand-act log). The directory is the one place they are kept, so no copy can list less: the backup holder keeps no
state of them (its `backed-up` lists the recovery module's item as any item, §302), and no `bus-points` state is
@@ -120,7 +125,8 @@ that round are written into the lines they name, here. Questions that an earlier
answers each with `{seq}` or `{error}`, the bundle sends the next only after a `{seq}`, and the answer to the last
is the put's answer; a `seq` that is not one more than the last taken is answered `{error}` naming both, and a put
not sealed within the call's bound is dropped (§345). The tool runner writes each chunk into the store as it takes it, through the
object store's own chunking, holding no more than one chunk in memory, and seals the object on the last.
object store's own chunking, holding no more than one chunk in memory, and seals the object on the last. A put dropped at its bound has its written chunks purged by the tool runner,
which deletes the unsealed object; until then they count against the store's cap.
- **Get.** The tool runner answers the get call `{chunked: <count>, size, digest, call}` (§490), and the bundle asks
each chunk in order by the call `mesh/objects.get-chunk` with `call` and `seq`, answered `{seq, last, data}` or
`{error}`; the bundle checks the whole against `digest`, and a get not completed within the call's bound fails,
@@ -435,7 +441,8 @@ that round are written into the lines they name, here. Questions that an earlier
the subject (§481), refuses an ask whose body names a kind that asker is not a caller of, answering `error` naming
the kind and the asker, and ends it with `step-ended` `failed`. On main's subject `accept.<queue>`, which names no asker and is granted to
the checker and the builder alone (§600), the holder takes only the kinds `build` and `run` and refuses any other,
`step` among them, as above. This amends §338 and §600. Why: §600 puts the queue
`step` among them, as above; the builder's `run` there is taken until the checker's removal (§97), after which
main's subject goes (§483). This amends §338 and §600. Why: §600 puts the queue
in the subject and the kind in the body, so a subject's grant alone cannot hold a caller to its kinds (round 3,
security and upgrade, seams and tools: R1). How it is checked: unit (Go build module), a `step` published from the
indexer's account is answered `error` naming `step` and `indexer`; unit (grants part), each asker's grants are the
@@ -5,6 +5,8 @@ design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0672"
- "ADR 0436"
- "ADR 0667"
- "ADR 0666"
- "ADR 0660"
@@ -35,48 +37,95 @@ are written into the lines of G-12 they name.*
## The recovery module
- §554 **The recovery module takes, sets aside and restores kept data on the live bus.** The operator, 2026-11-11
12:55 CET at lead-47's terminal: a module of its own, on a seat of its own, with an account of its own, owns
snapshotting, setting aside and restoring a module's kept data on the live bus, each act in the hand-act log; the
bus module keeps no restore permission (ADR 0626 §1 stays as it is), the snapshot account stays limited to the
nightly dump (ADR 0626 §2), and the backup holder only stores copies. The record of the recovery module, which
lead-47 proposes to the knowledge base for the operator's Approve, decides the account and its grants; this line
is written to it.
- **Its seat and module.** The seat `mesh-recovery`, held once for the mesh, is defined in mesh-contracts beside
`mesh-broker`, and the module `mesh-recovery`, in mesh-catalog, claims it; its glossary word is the *recovery
module*. It keeps no kept data on the bus, its one store being its data directory (§516), so it is no foundation
part (ADR 0619 §1) and waits on no bus module.
- **Its verbs and callers.** `snapshot-kept` and `restore-kept` (with `aside-only`), class `act`, are called by the
node agent applying a want (`seat:node-engine`, §296, §297) alone; `restore-kept` with `discard-aside` by
`operator` alone; `kept-points` (§517), class `read`, takes §391's default. Each act is written in the hand-act
log of the seat `mesh-hand-acts` first, with the caller the bus proved and `why`; an act whose log write fails
does nothing and answers `error`, naming the log (as §480).
- **Its account.** Composed by the grants part from the seat's definition as the record decides: the bus's stream
snapshot and restore, a stream's deletion and a consumer's creation, only for the bus objects of a module's kept
data (the names a binding or an old section of a catalog graph entry gives), never for the mesh's own streams nor
for any other object; it publishes only on its own seat's subjects and reads no module's data otherwise.
- **Its events.** On `mesh.seat.mesh-recovery.event.`: `ended.<module>.<kept>` (a point taken, with `outcome` `done`
or `failed` and its `error`), `restored.<module>.<kept>` (likewise), `set-aside.<module>.<kept>` (with the aside's
`id` and `size`) and `point-removed.<module>.<kept>` (§551), each filled as §523 has it and kept 90 days (§396).
The node agent's wait for `ended` or `restored` is bounded at 90 minutes (30 for a nightly dump it waits behind,
30 for a point brought back from the backup, 30 for the restore), past which its have says the wait, naming the
seat, and the watchman's `delivery-waits` raises it. This amends §405's 30 minutes.
- **One act at a time, and the nightly dump.** The recovery module runs its acts (`snapshot-kept`, `restore-kept`
and a removal of §551) one at a time, the next waiting within its own bound. The holder of `node-backup` says
`item-started.<node>.<module>` and `item-ended.<node>.<module>` for every item it backs up, declared in its seat's
definition; the recovery module consumes those of the bus module's item and starts no `restore-kept` while the
nightly dump of the bus runs, so the dump never meets a stream a restore removed (ADR 0235 §13). A `snapshot-kept`
may run beside the dump, both paced as ADR 0235 §10 has it, so the server has at most two snapshots at once.
- **Its order and its tools.** The node-engine's `invokes` of `mesh-recovery`'s verbs gives the served-verb edge
(kind 6) from the recovery module to the node-engine, so §298's "the new versions of the `node-backup` holder and
of the bus module run before any module whose kept data's form changes is moved" reads "the new version of the
recovery module". Its tools are named `recovery_`, and its declared health check calls `kept-points`.
- §554 **The recovery module takes, sets aside and restores kept data on the live bus.** The operator,
2026-11-11 12:55 and 13:02 CET at lead-47's terminal: a module of its own, on a seat of its own, with an account of
its own, owns snapshotting, setting aside and restoring a module's kept data on the live bus, each act in the
hand-act log; the bus module keeps no restore permission (ADR 0626 §1 stays as it is), the snapshot account stays
limited to the nightly dump (ADR 0626 §2), and the backup holder only stores copies. ADR 0672 decides the account,
its grants and its callers; this line is written to it.
- **What it alone does.** It alone takes a restore point before a module moves across a `form` change, and alone
restores into the live bus. The bus module's snapshot before its own `recreate` or `drop` (ADR 0595 §5, ADR 0626
§4) and the nightly dump (ADR 0626 §2) stay theirs. The restore ADR 0667 §12 tests of the snapshot `drop` takes is
the recovery module's `recovery_restore` naming that snapshot, which it reads through the bus module's tool
`nats_snapshot_get` (class `read`, callers `holder:mesh-recovery@same-node` alone).
- **Its seat, module and node.** The seat `mesh-recovery`, held once for the mesh, is defined in mesh-contracts
beside `mesh-broker`, and the module `mesh-recovery`, in mesh-catalog, claims it; its glossary word is the
*recovery module*. It runs on the node of the holder of `mesh-broker`, read from the catalog half and the seat
`mesh-module-assigner`'s placements, never a fixed name: G's seed writes its placement there, and the
placement verb refuses to move it while `kept-points` lists a point younger than 90 days, naming them, so its
points and their copies in that node's repository stay together. Its data directory, its manifest's `data` item
`points`, is capped at 10 GiB and measured by the disk readings (ADR 0571 §5): past 80 % it writes the finding
`points-filling`, and a `snapshot-kept` that would pass the cap ends `failed`, naming it, which holds the move as a
failed backup does (§296). Its `findings` state and finding stream are declared as §529's other parts declare
them, so it waits on the bus module for them and is no foundation part (ADR 0619 §1).
- **Its verbs answer at once; the result is the event.** `snapshot-kept` and `restore-kept` answer `accepted` with
the act's `act` id, `busy` with the act that runs (it runs one act at a time and keeps no queue), or `error`, and
nothing more; the point comes on `ended`, the restore on `restored`. A caller told `busy` asks again when it hears
that act's event. The module writes each accepted act in its directory before it answers; at its start an act
accepted and not ended is ended `failed` with `stopped`, so its caller asks again.
- **Its events.** On `mesh.seat.mesh-recovery.event.` and kept last per subject, 90 days (§396): `ended.<module>.<kept>`
and `restored.<module>.<kept>`, each carrying `act`, `module`, `kept`, `form`, `fingerprint`, `snapshot` and
`outcome` (`done` or `failed`, with `error`), `ended` also the point whole; `restore-started.<module>.<kept>` when a
restore begins; `set-aside.<module>.<kept>` and `aside-discarded.<module>.<kept>` with the aside's `id` and
`size`; and `point-removed.<module>.<kept>` (§551). The node agent wakes only on the event whose `form` and
`fingerprint` are its ask's. Its wait for `ended` or `restored` is bounded at 90 minutes (§405), past which its have
says the wait and the watchman's `delivery-waits` raises it.
- **Who calls it.** `snapshot-kept` and `restore-kept` are called by the node-engine holder of the node that holds
the want moving that module (`seat:node-engine`, proved by the bus as that node's account): the recovery module,
which hears `mesh-wants`' `wanted` as §556 reads a stream, answers `error` naming the node unless that node's want
names the module at `fingerprint` (for `snapshot-kept`) or moves it back from `fingerprint` (for `restore-kept`).
`kept-points` takes the default of a read (§391). `aside-only` and `discard-aside` wait for the operator (ADR 0672
review, K3 and K5). Each act is written in the hand-act log of the seat `mesh-hand-acts` first, with the caller the
bus proved and `why`; an act whose log write fails does nothing and answers `error`, naming the log (as §480).
- **The operator's hand tools.** `recovery_take` (take a point of one module and kept data now), `recovery_restore`
(restore one point) and `recovery_retry` (ask again the last failed act of a module and kept data), each of class
`act`, callers `operator` and `sessions` (§391), written in the hand-act log; they skip the want check, since the
operator's call is the reason.
- **Its account.** Composed by the grants part from the seat's definition and the manifest: the bus's stream
snapshot and restore subjects with their chunk subjects, a stream's deletion and a durable consumer's creation,
only for the bus names of a module's kept data; the subjects its seat says and its hand-act log write; its
consumers of `node-backup`'s `item-started` and `item-ended` and of `mesh-wants`' `wanted`, each with the ordered
consumer §556 needs; its calls of `node-backup`'s `restore` as the caller `holder:mesh-recovery@same-node`, which
`node-backup`'s definition names for `restore` and which the backup holder takes only for the recovery module's
own item `points` (the operator, 13:02 CET); and nothing else. The bus names granted are those of every kept data
of every catalog graph entry the catalog half keeps (§443) and of every entry a restore point names (an old
section's name before a form change, a template's binding after), read by the grants part through
`kept-points`; no stream of the mesh's own (`CONTROL`, `NODES`, `EVENTS`, `DEAD_LETTER_NOTICES`, `DEAD_LETTERS`,
`PROV_APPLIED`, `CHECKS_READY`, `CHECKS_OTHER`, every `SEAT_` stream and every `KV_` bucket of a seat) is ever
granted. Restricted streams (ADR 0436) are among the names, as ADR 0672 records.
- **Bus names.** The recovery module turns a module and a kept data into bus names from the catalog graph entry of
the fingerprint it acts at, read by `mesh-catalog`'s `entry` (§443) in its `invokes` (an edge of kind 6): a
template entry's name is `<module>_<local>` (ADR 0595 §1), an old section's its declared name; a point records the
names it took, and a restore uses those.
- **Never beside the nightly dump.** A `snapshot-kept` may run while the dump runs, both paced as ADR 0235 §10 has
it, so the server has at most two snapshots at once. No `restore-kept` starts while the dump runs, and no dump of
the bus starts while a restore runs: the holder of `node-backup` of G says `item-started.<node>.<module>.<item>`
and `item-ended.<node>.<module>.<item>` for every item, kept last per subject, 7 days, and puts off the bus's item
while a `restore-started` of the recovery module has no `restored`; the recovery module learns the bus module and
its node from the seat list's definition of `mesh-broker` and the catalog half's claim of it, never a fixed name.
Both read these streams as §556 has it, so a restart mid-dump or mid-restore misses neither. A blocked act waits,
neither refused nor failing a want: past 60 minutes the recovery module writes `recovery-waits` and the backup
holder `backup-waits`, each naming the item or the act it waits on, and `kept-points` lists the act that runs
with since when and what it waits on. The recovery module consumes the item events that G's backup holder adds,
an edge of kind 6 from that holder to it, so a backup holder of before G, which says none, is never relied on.
- **Its health.** Its declared health check calls `kept-points`, and fails while any aside's record ends at
`removed` (§516), when it also writes the finding `aside-unrestored` naming the module, the kept data and the
aside's `id`.
- **Its order.** The node-engine's `invokes` of its verbs gives the edge of kind 6 from the recovery module to the
node-engine, so §298's first edge reads "the new version of the recovery module" (§555). At a revert of G the
edge runs backward (ADR 0656 §4): the node-engine goes back only after every module it restores there said
`restored` and runs (§298), and the recovery module, new in G, goes only after the node-engine, so it stays while
any restore runs; its data item stays on its node, with its copies.
- **Its tools** are named `recovery_`.
Why: the operator's answer; the seat's placement in mesh-contracts, its callers, its events, its bound and its
order are the design's, from §296 to §303 and §405 as they were. How it is checked: test 36 with the recovery
module; unit (grants part), the recovery module's account holds the grants the record names and no other, and the
bus module's and the snapshot account's hold no restore; whole (recovery module), a `restore-kept` asked while the
bus's item is backed up starts after `item-ended`; an act whose hand-act log write fails does nothing.
Why: the operator's answers; the node, cap, events, answer on acceptance, dump order, health and edges are the
design's (review rounds 1 and 2; ADR 0672). How it is checked: test 36 with the real backup holder and the recovery
module; unit (grants part), the recovery module's account holds exactly the grants above, a call outside its names
refused, both a point's old-section names and a template's binding granted, and the bus module's and the snapshot
account's hold no restore; whole (recovery module), a call from a node holding no such want answered `error`, a
`busy` answer then the act on the other's `ended`, a second form change not woken by the first's `ended`, a dump
asked during a restore starting after `restored`, a restart during the dump starting no restore, an act whose
hand-act log write fails doing nothing, and an unrestored aside failing the health check.
- §555 **What moves to the recovery module.** §296 asks `mesh-recovery`'s `snapshot-kept` and waits for its `ended`,
never the seat `node-backup`; §297 asks its `restore-kept` and waits for its `restored`; §302's `backed-up` lists
the recovery module's data item as any item, and the restore points and asides are listed by `kept-points` (§517),
@@ -85,7 +134,8 @@ are written into the lines of G-12 they name.*
`mesh-broker`, which gains none; the seat `node-backup` gains nothing for kept data on the bus: its `aside` and
`discard-aside`, the arguments `kept`, `form` and `fingerprint` of its `now` and `restore`, and its events
`ended.<node>.<module>.<kept>` and `restored.<node>.<module>.<kept>` go from its definition in mesh-contracts, and
it gains only `item-started` and `item-ended` (§554); §450's `aside` answer is `restore-kept`'s with `aside-only`;
it gains only `item-started` and `item-ended` with their `<item>` token, and names `holder:mesh-recovery@same-node`
among `restore`'s callers for the recovery module's own item (§554); §450's `aside` answer is `restore-kept`'s with `aside-only`;
§406's catch-up is recorded in the point as before. Why: one owner of the acts (§554). How it is checked: unit
(definitions), `node-backup` and `mesh-broker` hold none of the moved verbs; test 36.
@@ -99,7 +149,11 @@ are written into the lines of G-12 they name.*
and its `<module>_first_views` names the stream `waiting`. So read: the node-engine seat's `running`, `composed`,
`wait-held` and `wait-ended` (the last two kept on the stream `running` is kept on, last per subject, a node's
module's newer one by `at` standing), by the assigner (§520), the condition keeper (§541), the builder (§546), the
node-engine and the grants part (§199); and `mesh-healers`' `attempt-changed` by the keeper (§541). This amends
node-engine and the grants part (§199), and the watchman for `delivery-waits` (§541); `mesh-healers'`
`attempt-changed` by the keeper (§541); `node-backup`'s `item-started` and `item-ended` and `mesh-wants`' `wanted`
by the recovery module, and the recovery module's `restore-started` and `restored` by the backup holder (§554). The
grants part grants each such reader, beside its durable consumer, the creation of an ordered consumer on that
stream with no durable name (the bus's consumer-create subject for that stream), from the reader's `consumes`. This amends
§199's "each part's durable consumer starts from the last message per subject". Why: what a part heard must not
depend on when it last restarted (review round 1, health and events 2, with running and testing 3). How it is
checked: whole (assigner, keeper), a restarted assigner holds no want it did not hold before, and a restarted
@@ -120,9 +174,17 @@ are written into the lines of G-12 they name.*
verb's answer, naming it. The delivery plan derives the edge of kind 6 from the holders of that seat to the
consumer, held until the holder runs a build whose catalog graph entry's seat definition (§194) gives the verb's
answer every named field; §374's entry of kind 6 records the verb and its fields, and `outdated` (§375) says it
behind when the delivered version no longer gives them. The grants part's manifest names `mesh-broker`'s `list`
with `fields: [binding]`, and every part of G relying on a field G adds to a served answer names it so in G's
change. Why: the module graph orders a consumer after what it relies on, and a field is part of the contract
behind when the delivered version no longer gives them. Both forms stay: the short string where no field is relied on, the long form
where one is. On main mesh-sdk's manifest reader reads `invokes` as a list of strings, so the long form is read
first by §494's second reader release, merged and delivered before G's merge: its manifest reader takes either
form, and the running checker, the indexer and the grants part, which read manifests through it, are rebuilt with
it by the release's publish (kind 1), as for `max-mib`. That publish rebuilds every module importing mesh-sdk's
`catalogue`, the set the release rebuilds already, so the form adds no rebuild. The consumers of G that name fields:
the grants part, `mesh-broker`'s `list` with `binding`; every reader of `mesh-catalog`'s `revision` through
mesh-sdk's client (the bus module, the status view, the condition keeper, the tool runner, the assigner, the grants
part and the runner), with `none-yet` (§530); the status view, `mesh-catalog`'s `entry` with `manifest-digest`
(§506). The recovery module reads the manifest whole the entry carries (§443), a field of before G. Any other part of G relying on a field G adds to a served answer names it so in G's change, which the
code review checks. Why: the module graph orders a consumer after what it relies on, and a field is part of the contract
(lead-47's question from the operator's "the module graph is for this", 2026-11-11). How it is checked: unit
(manifest validator), a field the definition lacks refused; unit (delivery plan), the grants part ordered after
a bus module whose definition gives `binding`, and not before.
a bus module whose definition gives `binding`, and not before; unit (the release's reader), both forms read.
+2
View File
@@ -5,6 +5,8 @@ design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0672"
- "ADR 0436"
- "ADR 0670"
- "ADR 0668"
- "ADR 0667"