From c3d8367b335097ccf80ce1d8714bf213c677c522 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 4 Nov 2026 17:32:21 +0100 Subject: [PATCH] Designs 25, 51: write what review round 1 settled (acted key, ask lifetime, loopback bootstrap, shared idle drop, shared-digest tag, forge account removal) Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig --- 03-DESIGN/01-to-be/25-the-bus-on-nats.md | 10 +++++++-- .../51-the-registries-keep-what-is-named.md | 21 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) 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 07399487..7bb21f4e 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 @@ -938,8 +938,14 @@ channel's `decided` for the asker that raised the ask (ADR 0259 §6; ADR 0620 § hears its own `decided` through `consumes` on a durable consumer and runs its pass over the waiting `recreate` and `drop` requests when one arrives, so a warranted `drop` acts within seconds of the operator's answer, and one given while the process was down is heard when it is back. **A warrant acts once** (ADR 0259 §6): before it acts, the -process claims the warrant's ask id in its own state by a compare-and-set, and a request naming an ask it already -acted on is refused, deleting nothing and saying which act that warrant already performed. `create` and `apply` need no warrant, since they only make or grow what an accepted manifest +process claims the warrant's ask id by writing the key `acted.` in its own state `requests` (no new state), +created by compare-and-set after the snapshot and before any deletion, and a request naming an ask it already +acted on is refused, deleting nothing and saying which act that warrant already performed. **An ask lasts 12 hours**, +shorter than the 24 hours `requests` keeps a request: a request whose ask ended unanswered is ended and said, and a +warrant is not acted on once its ask ended; the tool raises the ask before it hands the request over. A request +that cannot act yet says why in its field Waiting, and a hand act the process could not record is written on the +request in its field Unrecorded. The tool `nats_requests` reads the waiting and ended requests and the warrants +spent, and drops a waiting request by hand, recorded as a hand act. `create` and `apply` need no warrant, since they only make or grow what an accepted manifest asks for, and the process refuses either for an entry no accepted manifest asks for. A tool acts only for a caller whose role grants it; the process records each act as a hand act (`mesh-hand-acts`) and answers what it did. What stands between the tool runner's account and the process's delete power is that check of the warrant, so its tests 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 f2a6cfbd..a2c14905 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 @@ -141,7 +141,12 @@ the verb. own object store `incoming`, asked for as bus state in its manifest (design 25 § 12) with a cap of 8 GiB, the most the objects template allows (design 25 § 12.1), and no lifetime, since that template keeps for good; the holder counts its fill against the cap its binding carries, never a number of its own. The holder itself drops a transfer with no part - for 24 hours and deletes its parts (ADR 0611 §3), so an abandoned transfer does not stay. The holder hashes every part and refuses one whose bytes do not + for 24 hours and deletes its parts (ADR 0611 §3), so an abandoned transfer does not stay. **Both are mesh-sdk's + `parts.Receiver`, shared by every holder** (ADR 0611 §3), never copied into a holder: an expiring key per open + transfer, in a state of the holder with a key lifetime, is armed when a transfer is opened or opened again, and its + expiry (an event, never a timer) drops the transfer with its parts, or arms it again for the rest of the day if a + part came; a key that cannot be written fails the opening loudly. The cap is read once from the binding's fill and + kept; only where no binding is read does the holder state the 8 GiB it asked for. The holder hashes every part and refuses one whose bytes do not match its digest. At 80 % of the cap it writes a finding (cleared below 80 %); at the cap it refuses a new transfer with `refused` naming the cap. Its tool `registry_incoming` lists open transfers and the fill, and drops one by hand. - **The holder asks the builder**, through `builder_versions`, whether the name, version and digest are recorded, and @@ -163,6 +168,10 @@ the verb. want whose build carries it reaches a node only once that node's engine states the capability to read both forms and both seat names; the assigner holds the node's want meanwhile and names the capability as the reason, and a node away keeps its want and catches up on return (ADR 0612 §2, made general by ADR 0614 §4). +- **The forge's accounts and teams are what the catalog declares.** The forge module removes, at each start and + when its teams change, the teams and the accounts of the retired per-node package-reading form that nothing + declares any more; one the forge refuses to delete because it owns something has its login prohibited. How it is + checked: after a delivery the forge module's team and account tools list none of them. - **No build module holds a registry's write credential** (ADR 0605 §5). The npm write token goes. The image push credential and the artifact store's write binding that ADR 0605 §5 revokes do not exist today: the store takes writes from any process on the mesh network, so the rule protects nothing until its write side is closed. So @@ -438,7 +447,10 @@ modules' manifests for such an edge. The done keys written in the new form stay revert and are not built again for their form; each still carries every form a counted node-engine states, the oldest in its single reference, so a node is held from them only when its engine reads none of those forms (ADR 0624 §1-3). **On a fresh mesh** the foundation's bootstrap (research 075) pushes the holders' own images -with a one-off credential of the bootstrap, discarded once the holders serve `publish`. +to the store on its node's loopback, with no credential, as the publish contract allows for a write that reaches the +store from its own node, and records their references under the seat's reach. No one-off credential exists: the +node-engine writes no push credential and the holder's front keeps no bootstrap token. How the rest of the bootstrap +goes is research 075's. ### Acceptance tests @@ -451,7 +463,10 @@ test). - **Builder.** A branch pushed with no ask publishes nothing; a lone pull request's check publishes nothing; a group introducing a new package takes `0.1.0-.1`; the checker's `tag-wanted` yields `numbered` and `published`, and members are built only after `published`; no `published` in 10 minutes fails the check naming the package; - `builder_untag` removes a branch's tagged versions with `removed`; a `remove` while the holder is down is retried and + `builder_untag` removes a branch's tagged versions with `removed`; a tagged version whose digest another tag names + keeps its tag on the store pinned today (a registry that cannot remove a tag alone), `removed` is said with that + reason and the builder records it gone, and its bytes go with the other tag's removal, the move to a registry that + removes a tag alone being the next milestone's; a `remove` while the holder is down is retried and past 15 minutes writes its finding; a late `published` after the bound writes the done key; `builder_publish_again` after the build's file is gone builds again under the same number; with the seat's holder stopped at a first claim nothing is numbered and the finding names it; two merges claimed in reverse order are numbered in merge order; a