diff --git a/03-DESIGN/01-to-be/25-the-bus-on-nats.md b/03-DESIGN/01-to-be/25-the-bus-on-nats.md index 44a695ae..e6df2a05 100644 --- a/03-DESIGN/01-to-be/25-the-bus-on-nats.md +++ b/03-DESIGN/01-to-be/25-the-bus-on-nats.md @@ -815,6 +815,15 @@ vault as an own secret: JetStream create and update under modules' names only (s part and the tool runner their first views while the bus module still waits on it. The order of owner before reader is kept by the module graph's served-verb edge for the 19 readers (ADR 0614 §2), and, for the four, whose verb edges lie on cycles the graph leaves out (ADR 0614 §3), by the owner's answer at once and the reader's wait (ADR 0615 §2). +- **The other 19 readers ask the owners' tools, one per bucket they read** (ADR 0615 §1, §2): beside the five above, + each owner serves a first-view tool for every other bucket of its state a reader reads, named for its owner and + the bucket and marked as a read, in the owner's own runtime like the five (ADR 0621 §1). The indexer's seven: + `indexer_predefined` (its bucket `predefined`), `indexer_config_candidates` (`config-candidates`), + `indexer_candidates` (`candidates`), `indexer_packages` (`packages`), `indexer_graph` (`graph`), `indexer_heard` + (`heard`) and `indexer_taken` (`taken`). The assigner's three: `assigner_findings` (`findings`), `assigner_asks` + (`asks`) and `assigner_differences` (`differences`). So the nine buckets of the indexer and the six of the + assigner that the 23 readers read (§ 12.6) each have their owner's tool. Six of these names are today tools of the + status view, which serves them by reading the owner's bucket and is one of the 19 readers. - **Only the owner reaches it** (ADR 0596 §2). The membership grants the owner's account its own entries and no other module's: the new form has no readers. What another module needs of that data it asks through the owner's tools or seat verbs, and what the owner lets others hear is its declared events, subscribed to through @@ -972,7 +981,7 @@ bus state (counted 2026-11-03 02:00). **A correction of fact**: the indexer's an from every manifest on main later that day, is read by 23 modules, 9 buckets of the indexer and 6 of the assigner, not by the 19 the first plan counted; and 151 state entries were counted, not 158 (the template table of § 12.1 keeps the first count, which chose the templates). The owners first gain their events and first-view tools: the indexer -one per bucket its readers read, the assigner the same. Then all 23 readers move in the milestone of ADR 0612, the +one per bucket its readers read, the assigner the same (§ 12.2 lists them). Then all 23 readers move in the milestone of ADR 0612, the four foundation readers included, by the first view of § 12.2 (ADR 0615 §1); their order is the module graph's, not a review reading an owner delivered (ADR 0615 §2). The judge still refuses a moved module's subscription to an event its owner does not declare. Every other reader moves when its module is next touched. These moves are tracked by @@ -986,10 +995,10 @@ issue 1966. | The bus module creates, and the binding follows | live, by tool call: a module asking for a state, a log, objects and a ledger in `requires` receives each binding in its membership, written after `created`, never before; `show` gives each entry's template, settings and fill; a module calling `create` is refused | | The bus module runs whole | one integration test in the nats module's repository that starts the bus module whole against the real bus server: a verdict, then `created`, then the binding in the membership; a restart that catches up a verdict given while it was down; a bucket whose settings differ raises `drifted`, the seat's `apply` of a larger cap clears it with `drift-cleared`; a refused create raises its condition and hands no binding; `recreate` and `drop` without the operator's warrant are refused, and with it act after a stream snapshot; an orphan is listed, raises `orphaned`, and goes only by `drop`; each template at a small cap refuses, events drop the oldest, and `full` is raised at the raise mark and cleared only below the clear mark; `recreated` rewrites the binding and `dropped` removes it; at start the first view from `indexer_bus_state` creates what a verdict given while it was down asked; the older remove tools refuse a new-form entry, naming `drop`'s tool | | A module asking bus state waits for the bus module | the module graph's table test: a manifest with a ledger entry has a requirement edge to the module providing `bus-state`, one without has none (ADR 0614 §5) | -| A foundation part's first view | unit tests of each owner and reader (ADR 0615's How it is checked), as table cases, and these cases of the whole-module integration tests that exist today (mesh-delivery is over its integration budget, so no new test function): the indexer's (`cmd/mesh-delivery-indexer`, its one whole-module test, which the milestone's packages test merges into), the assigner's (`cmd/mesh-delivery-assigner`) and the grants part's (`cmd/mesh-grants`), and the tool runner's in mesh-tools: the owner answers its verb at once from what it holds, with its revision, before its own first view; the reader asks once at start, then only on a gap in revisions; a reader whose owner is down raises its condition only past the bound and never reads the owner's state, and the owner's answer clears it; an empty answer at revision 0 drops no login; an owner's event carries the changed value whole, and a reader applies a put and a delete from the events alone and never asks the verb; a revision lower than the one held makes the reader ask its first view again; an existing waiter on `manifest-accepted` or on the assigner's `put` does not wake on the new families; the read tool shows the revision each reader holds, and the re-read tool asks once and records the hand act; in the +| A foundation part's first view | unit tests of each owner and reader (ADR 0615's How it is checked), as table cases, and these cases of the whole-module integration tests that exist today (mesh-delivery is over its integration budget, so no new test function): the indexer's (`modules/mesh-delivery-indexer`, its one whole-module test, which the milestone's packages test merges into), the assigner's (`modules/mesh-delivery-assigner`) and the grants part's (`modules/mesh-grants`), and the tool runner's in mesh-tools: the owner answers its verb at once from what it holds, with its revision, before its own first view; the reader asks once at start, then only on a gap in revisions; a reader whose owner is down raises its condition only past the bound and never reads the owner's state, and the owner's answer clears it; an empty answer at revision 0 drops no login; an owner's event carries the changed value whole, and a reader applies a put and a delete from the events alone and never asks the verb; a revision lower than the one held makes the reader ask its first view again; an existing waiter on `manifest-accepted` or on the assigner's `put` does not wake on the new families; the read tool shows the revision each reader holds, and the re-read tool asks once and records the hand act; in the | The owners' first views are their own tools, in a runtime of their own (ADR 0621) | cases of the indexer's and the assigner's whole-module integration tests: each first-view tool, called from a reader's account while the node's tool runner is stopped, answers (§1); each answers its granted readers and refuses every other account, the owner's own included (§2); the two runtimes started at the same moment, each asking the other's first view at start, both answer within the first-view bound with their revisions (§3); and the milestone's group passes its merge check with no change to the judge's known fields for these verbs (§4) | assigner's whole-module test, the assigner starts before any new-form bus state exists, with no binding of the bus -module, and the indexer, the grants part and the tool runner each get their first view of it. Live, after the delivery: the indexer's count of `reads` entries on the indexer's and the assigner's state reads 0 | +module, and the indexer, the grants part and the tool runner each get their first view of it. Live, after the delivery: the indexer's `indexer_old_sections`, which the milestone extends to count the `reads` entries on each owner's state, reads 0 for the indexer's state and 0 for the assigner's; and each owner's tool of § 12.2 for the other 19 readers answers what its bucket holds | | A foundation part's first view comes within its bound | live, after the delivery: each reader's read tool (`grants_first_views`, the mesh MCP server's `mesh_first_views`, `indexer_first_views`, `assigner_first_views`) shows, for the indexer's and the assigner's verbs, the time from its ask to the owner's answer under the two-minute bound, and no first-view condition raised by the delivery | | The bus module's first view | cases in the nats module's one integration test: a replayed verdict older than the first view is not applied; an `indexer_bus_state` that does not answer turns the health unhealthy naming it and is asked again on the backoff; a set-aside manifest missing from the first view keeps its `asked` key, an empty `manifest-accepted` removes it; a deleted module's entry, after its empty `manifest-accepted`, is listed by `orphans` and raises `orphaned`, and a set-aside module's entry is neither; `nats_first_view_again` asks at once and records the hand act | | `manifest-accepted` is never lost silently | unit tests of the indexer: a failed publish is published again, and one still failing writes the finding; `indexer_say_accepted` says it again for one module from the verdict held, and refuses a module with no accepted verdict | diff --git a/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md b/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md index f2688589..4bc8d001 100644 --- a/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md +++ b/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md @@ -9,7 +9,7 @@ code: - mesh-delivery modules/mesh-delivery-builder (versions, tag asks), the forge bridge, the indexer, the checker, the assigner - mesh-sdk (the bus helper for sending in parts) - mesh-catalog modules/docker (image pruning) - - mesh-host internal/apply (every new image of a module pulled before any of its containers is replaced) + - mesh-host internal/apply (every new image of a module pulled before any of its containers is replaced; a failed pull applied again when the condition keeper clears the store's holder's condition) updated: 2026-11-04 decisions: - "ADR 0605" @@ -194,8 +194,14 @@ the verb. composition, on the node-engine's verb `compose` naming the module (by hand), or when its liveness judge finds a declared resource missing or down; only a failure of the bus itself is tried again on a clock (a bounded backoff, at most four times before the have says failed). So another module's apply whose pull falls in that window stays - failed, its running containers kept, until one of those: its have says failed naming the image, and `compose` - naming the module is its recovery. + failed, its running containers kept, until one of those: its have says failed naming the image. + **So a pull that falls in the swap is tried again on the store's holder's health, never on a timer**: the + node-engine hears the seat `mesh-conditions`'s `condition-cleared` (ADR 0564 §3) through its manifest's `consumes`, + and when the condition it clears names the store's holder (`distribution`, the holder of the image seats) as not + healthy or its seat as not answering, it applies once more each module whose have says failed naming an image of + that store, one apply per clear, said in its journal. A clear of any other condition starts nothing, and no clock + starts an apply. `compose` naming the module stays, but only as the hand recovery of a pull still failed after + that, recorded as a hand act; it is no step of the delivery. - **The package seats' read sides need no credential** for the mesh's own packages: the forge serves the mesh owner's packages to anonymous reads, so the provisions `npm-package-registry` and `go-package-registry` carry no credential (form none), and mesh-build-node, which held a pair for both writing and installing, requires none (the @@ -463,6 +469,10 @@ test). - **Node-engine, unit** (a case of its apply test, with the runner it already fakes): a module of two containers whose second new image cannot be pulled replaces neither container, says the image, and keeps both running; with both images pullable, both are pulled before the first container is set aside. +- **Node-engine, unit** (a case of its apply test, with the runner and the bus it already fakes): a module whose pull + failed, its have failed naming an image of the store, is applied once more on a `condition-cleared` of the store's + holder's condition, and its new image pulled; a `condition-cleared` of another module's condition applies nothing; + with no clear heard, nothing applies it again, however long the test waits. - **Checker.** A changed build module invoking a verb no running holder serves is not run, and the verdict names the modules composed from their manifests instead, and the verb. - **Vault.** Reverting the milestone's merge mints the build modules' credentials again; the bootstrap's one-off @@ -474,7 +484,9 @@ test). shown by `builder_versions`; a node runs a module from a reference in the new form; a node-engine away across the milestone wakes and applies the new node-engine; the node-engine's apply journal for `distribution` on each node shows every new image pulled before its first container was replaced, and no node's pull of any module failed - during the delivery (each node's haves, none failed naming an image); mesh-build-node installs from a lock file + during the delivery (each node's haves, none failed naming an image), or, where one fell in the swap, its have + turned healthy after the condition keeper cleared the store's holder's condition, the node-engine's journal naming + that clear, and no `compose` was called for it; mesh-build-node installs from a lock file naming the registry's public root with no credential. Go's `direct`: its removal is named on the milestone's issue, and the change that removes it adds to the Go build module's recipe test a case that refuses `direct` in the fetch.