Commit Graph
831 Commits
Author SHA1 Message Date
jschoubben 029ba98527 pernode: the per-node state's rules over any connection, so the runtime and a process read compositions with one copy of them (ADR 0593 §6)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:29:40 +01:00
jschoubben bb59fd8fa3 delivery: a composition's digest leaves its plan out, as a have, a want and the apply name it by its resources (ADR 0593 §6)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:25:13 +01:00
jschoubben ba82dd64b1 delivery and catalogue import neither overlay nor buildcpu, so a change to the network generator or the build share code rebuilds only their own importers (ADR 0593 §1)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:25:11 +01:00
jschoubben acef75d398 membership: an issued state may be one bucket per node, so the runtime reads every node's compositions for a bundle as one state (ADR 0593 §6)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:24:01 +01:00
jschoubben 8dc610c628 process: read a state its owner keeps one bucket per node as one state, so the provisioner, the assigner and the view read every node's compositions (ADR 0593 §6)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:23:27 +01:00
jschoubben b56841596e Delete the Python, Rust and C bindings, the Go example and the TypeScript seal and contracts exports, which nothing imports, in the release's one mesh-sdk change (ADR 0593 §12)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:21:30 +01:00
jschoubben d158ac52da composer: a request carries its composition input as raw JSON, so the shape stays in mesh-sdk while the composer moves to the node-engine (ADR 0593 §7)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:20:05 +01:00
jschoubben 346dd43228 delivery, catalogue: the node-engine's compose-candidate verb, compositions carrying their plan or refusal, the kept import form and a build's imports on its key, so the engine alone composes and the indexer switches form without a rebuild (ADR 0593 §4, §6, §7)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:19:24 +01:00
jschoubben 04d951d9da catalogue: a module's own object bucket, its reader grant and a stream that keeps its history, so the knowledge base can keep its records on the bus (ADR 0592 §5, §6, §9)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:17:14 +01:00
jschoubben 3d87ddcc9a delivery: the indexer's packages state and the imports a build reports, so only the indexer computes a fingerprint over what a module imports (ADR 0593 §2)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:15:35 +01:00
jschoubben 21dd8881ed buildstep: a check ask runs every level and every package after a failure, so one check names every failure
The operator, 2026-11-02: a failed check showed only its first fault; a group's three faults took three runs.
The change's own packages still run first (issue 1289), and nothing after them is skipped.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:13:51 +01:00
mesh-tools d6c87ee1a7 Merge pull request 'compose: an offer of form none composes no credential and holds nothing (issue 1126)' (#159) from fix/1126-provision-credentials into main 2026-11-02 15:31:34 +00:00
jschoubben c459f75730 compose: an offer of form none composes no credential and holds nothing
mesh/delivery merged: source.main moved to novox/mesh-sdk@d6c87ee1a7ae
mesh/delivery-group group fix/1126-provision-credentials merged: every member is merged
mesh/check pass c459f757308a on 036266daff85 | unit 6028 run, 142 kept, 16 skipped | integration 6091 run, 174 kept, 25 skipped | over bound: unit, in…
After the controller, nothing makes a pair row for a new consumer, so a need whose provider offers no credential
(form none) was composed with a stand-in on both ends and the node-engine held the consumer (issue 1126:
mesh-cli on ace, "stands in for the grant of mcp-endpoint"). The vault never mints for form none, so such a need
now composes with no credential: the consumer's need carries none, the provider's grant carries the consumer
and nothing sealed, neither is named foreseen, CredentialsNeeded asks the vault for neither, and no empty grant
file is written.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 15:30:43 +01:00
mesh-tools 036266daff Merge pull request 'Undefine the controller's streams, consumers and lease; provisions carry their plan entry (issue 1126 group B)' (#158) from feat/1126-removal into main 2026-11-02 13:40:48 +00:00
jschoubben abf5eace77 Let the bus tools remove mesh-catalog's and the engines' leftover consumers on EVENTS
mesh/delivery merged: source.main moved to novox/mesh-sdk@036266daff85
mesh/delivery-group group feat/1126-removal merged: every member is merged
mesh/check pass abf5eace7791 on 4a4fac090e9e | unit 6915 run, 1941 kept, 59 skipped | integration 6945 run, 2096 kept, 65 skipped | over bound: unit, …
novox_mesh-catalog follows the ended controller's built-before and each <node>_mesh-host restic's backed-up; no part
composes either and nothing reads them (novox_mesh-catalog 10036 behind, each mesh-host 331 never delivered), so the
removal after the delivery takes them with the controller's (issue 1126).

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 12:25:56 +01:00
jschoubben f569924037 Read past a provision field a later layout adds
Decode refused any field it did not know, so every reader on an older
mesh-sdk refused a key the moment a writer added one (plan, this release).
It now reads past it and drops it; Encode still writes the layout alone, so
no value rides in a provision (issue 1126 review 1).

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 12:18:21 +01:00
jschoubben c94f30d398 Bind a consumer from the plan entry its key carries, not only from the plans
The seat keys a consumer's provisions from its wanted and newest builds but
keeps the plan of its wanted build alone, and the provider helper bound only
from plans: a requirement the newest build adds stayed asked with no word,
and the want waiting for it never moved (mcp-endpoint on ace and shanks).
A provision now carries the plan entry it was composed from; the helper
binds from it where no plan names the key, the plan winning where both do,
and says each key it can bind from neither (issue 1126 review 1).

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 12:17:20 +01:00
jschoubben 729a86b623 Say what the wants' compare and the enrolment tokens answer now, and who composes the bus's users
The upgrade verb's compare answers each node's own composition and the assigner's findings, not
a policy against the controller's; tokens no longer says whether issuing is on, since no lease
gates it; the composed configuration names the grants part, not the controller (ADR 0590).
Issue 1126 B1, B3a.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:48:25 +01:00
jschoubben fb13f3cc7e Drop the keeper's and config's take-over verbs, which chose the controller's sources
ADR 0590 clause 3 ends the take-over and the hand-back, and with them compare: the readers follow
the keeper, and config its own sources, with no switch to ask. Issue 1126 B1.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:38:42 +01:00
jschoubben 66232896f3 Remove the controller from health, hand acts, announcements and the provider
The take-over key chose between the controller's conditions and the keeper's; ADR 0590 clause 3
ends that choice, so readers hear the keeper (KeeperSeat) and the self-check (SelfCheckSeat)
alone and the key, its version and its two sources go. The controller's hand-act log, its
show verb, its kept announcements and its assignments mirror's name go too, and the hand-act
recorder's unread LeaseAway. Issue 1126 B4b.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:37:49 +01:00
jschoubben 8757567a79 Wrap the composition signature's comment
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:36:31 +01:00
jschoubben dcb2e6e966 Remove the controller from the delivery contract, and its command line client and hand composer
The controller ended (ADR 0590): the grants issued are the grants part's alone, so its grant value
is Grant and GrantSource goes; a node trusts the vault's key alone, follows the grants part's
user list alone and composes its own or none; the controller's composed and builds bucket names
go. nox calls seat verbs (ADR 0590 clause 7), so the cli package that spoke to the node-engine's
socket goes, and mesh-hand-compose, which wrote the controller's compositions. A have an engine
from before wrote, composes controller, still reads. Issue 1126 B4a, B6.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:36:26 +01:00
jschoubben ba1e90fb2d Undefine CONTROL and the controller's consumers, its followed events and its lease reading
The controller ended (ADR 0590): nothing consumes what nodes report on CONTROL, so the mesh no
longer declares the stream, which would make it again before its removal; MeshConsumers is empty,
the controller's consumers and the events it followed go, and the lease holder's reading
(LeaseHolder, LeaseHandedAway) with them. Only the consumers' names stay, for the removal of the
leftovers and the watchman's read of whether controller still stands. Issue 1126 B3b.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:33:12 +01:00
jschoubben e240e01d07 Bound an ask's step by how long it stands still, not its age, so a step moving through phases is waited for (issue 1930)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:31:38 +01:00
jschoubben 7b034e1db0 Compose the bus's users without the controller, and grant the removal of its leftovers
The controller ended by its unassignment (ADR 0590): its user, its lease's cut and reads, the
operator's hand path to its compositions and its writers' rows go; an enrolling node enrols
through mesh-enrolment alone; the desk's prompt stays the vault's alone (DeskOnly). The golden
lists are now this composer's own, taken first from the controller's with its user removed.
The bus module's tools may remove the controller's leftovers by name, consumers, CONTROL,
ASSIGNMENTS, its 17 buckets and each node's declaration files' bucket, under the word
controller-leftovers (clause 6). The provisioner client reads placement in place of the
assignments mirror. Issue 1126 B3a, B5.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:31:33 +01:00
jschoubben 49b307a46d Route a call key naming its machine after '@', and refuse a malformed key before publishing
The lease write asked seat:node-service-manager.stop@novox-be through Conn.Call, which published
the '@' inside the subject: nobody served it and the call timed out after 30 s with nothing said
(issue 774 notes 84-87). Every key now parses in one place, calladdress: Call routes '@node' as
CallOn does, and stdio Ask refuses a key the runtime could not route, before anything is sent.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:22:50 +01:00
jschoubben 8295207077 Remove the controller's seat, the lease verbs and placement's adopt and hand-back; refuse any manifest naming the controller
The controller ended by its unassignment (ADR 0590), so its seat, the grants seat's lease write and
hand-back and placement's take-over from it serve nothing. The dependence check becomes strict
(clause 5): a read of the lease, a claim, a require or the module itself is refused like any other
declaration. held and artifacts-gone are the artifact sweep seat's (ADR 0571 §2). Issue 1126 B1, B2.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:20:28 +01:00
mesh-tools 4a4fac090e Merge pull request 'The enrolment seat and node-login rotation contract: a joining machine's first tunnel, add-node and remove-node, two logins per node (issue 774)' (#157) from feat/l3-enrol into main 2026-11-02 07:56:24 +00:00
jschoubben dff0ce2abb Say why LeaseHandedAway and LeaseCut are two fields: the cut precedes the holder's write and outlasts it at a hand-back (issue 774)
mesh/delivery merged: source.main moved to novox/mesh-sdk@4a4fac090e9e
mesh/delivery-group group feat/l3-enrol merged: every member is merged
mesh/check failed (2 tests): integration: mesh-mail-reader/cmd/mesh-mail-reader.TestAcceptanceOneMatteringMailSendsExactlyOneTellNamingIt: timed out w…
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:46 +01:00
jschoubben c816666f83 Name the enrolment an address is reserved for, from its ask, and the issued event's id in one place
ADR 0589 §6: an address key gains the issue's ask and time, written when the ask is raised. The key is written at the
reservation, before the ask, so both are empty then and both set from the ask; one without the other is refused, as
is no node. EncodeEnrolmentAddress takes node, ask and issued. EnrolmentIssuedID builds the enrolment-issued event's
id, enrolment-issued.<node>.<issue time in Unix nanoseconds>, as the holder names it today. Tested as rows of
TestNodeRecord; no new test function (1438 unit tests).

(issue 774, review round 1b)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:36 +01:00
jschoubben 2d717777b1 Carry the machine's tunnel key on its enrolment, so the holder places it on the operator's yes
The operator's decision of 2026-11-02 01:05: the tunnel key is given at issue. Enrolment gains overlay-key, required at
every stage and refused unless it is 32 bytes in base64. Tested as rows of TestNodeRecord; no new test function (1438
unit tests).

(issue 774, review round 1b)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:36 +01:00
jschoubben f913918a60 Take the tunnel key at issue and place a joining node on the operator's yes, so the hub peers it before redeem
The operator's decision of 2026-11-02 01:05: issue requires overlay_key, the machine's tunnel public key; the vault's
enrolment-token tunnel declares all five fields a token needs (hub_key, hub_endpoint, address, key, range). An
add-node is proposed at the yes with the tunnel key alone; the identity keys come whole at redeem or not at all. A new
remove-node, mesh-enrolment's alone on the same warrant and the proposal's one change, takes a joining node running
nothing off placement when its enrolment ends unconfirmed (RemovedNodes names the key the holder deletes; LayChanges
lays nothing for it and refuses a node that runs modules or holds seats). NodeLogin gains Acts, the hand acts that
warranted its rotations. Tested as rows of TestPlacement, TestNodeRecord and the two seat tests; no new test function
(1438 unit tests).

(issue 774, review round 1b)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:36 +01:00
jschoubben 38a0bbca44 Let enrolment-token take the first tunnel, so the token the vault makes carries it as today
Lead's decision on milestone point 7 (a progressive insight of ADR 0587 §3): mesh-enrolment builds the joining
node's first tunnel at issue and passes it to the vault's enrolment-token as `tunnel`, an object of hub_key,
hub_endpoint and address, each required; the vault puts it in the token (delivery.TokenTunnel). Tested as a row of
TestTheVaultsSeatPromisesItsIntakeVerbs; no new test function (1438 unit tests).

(issue 774, review round 1)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:36 +01:00
jschoubben 79ad8b539c Name the expired enrolment's issued event by its id, and carry a node's login fall back in its health report
Blocker 6: enrolment-expired carries the enrolment-issued event's message id (IssuedID), since a bundle's publish
answers no stream sequence and ADR 0587 §2 asks only that the event be named; it gains a codec refusing no event named.
Blocker 7: NodeHealth gains Fallback (node, the login fallen back from, why, at), from which the watchman raises
node-account-fallback (ADR 0583 §6); a fall back naming another node is refused. A token missing its signer now says
the vault's signing key, not the retired word. Tested as rows of TestNodeRecord and the control records test; no new
test function (1438 unit tests).

(issue 774, review round 1)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:36 +01:00
jschoubben 90a5fc5797 Let placement take an add-node with its enrolment's warrant, so one Approve lets a machine join
ADR 0587 §7: at redeem mesh-enrolment proposes one change, the node with its decided fields (the approved address,
never the hub) and the public halves of its keys, carrying the issue's warrant; mesh-placement checks the warrant
names this node and address and that the caller is mesh-enrolment, and writes the key with no ask of its own
(changing ADR 0567 §2 and §5 for this one change by this one caller). The proposal codec refuses an add-node beside
other changes, without a warrant, or whose warrant names another node or address, and a warrant on any other
proposal; AddNodeRefusal adds the caller's check for the assigner; LayChanges adds the node and refuses one placed
already. Tested as rows of TestPlacement's proposal subtest, no new test function.

(issue 774, 774/S42)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 362dddae40 Compose mesh-enrolment's grants: its bucket written by it alone, the vault's enrolment verbs called by it alone
ADR 0587 §1-§3 (changing ADR 0561 §5) make mesh-enrolment the only caller of the vault's enrolment-token and
node-account and a caller of sign, and §2 its bucket enrolments read by it and by the grants part as a named reader.
The holder calls the vault through its manifest's invokes, in its own name, as any caller does; while the vault serves
either enrolment verb every other principal is denied both, however wide its grant (a runtime's or an agent's `*`),
as ControllerOnly denies the desk's prompt. The writers table gains the open enrolments (mesh-enrolment) and the
node-logins (the vault), each one writer; NamedReaders names the grants part for enrolments. Golden lists unchanged.
Tested as a subtest of TestTheCopiedComposerComposesAsTheControllers, no new test function.

(issue 774, 774/S41)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 9169830210 Grant an enrolling node's user the seat's redeem alone, so from the lease write no token reaches the controller
ADR 0587 §4: the grants part composes enrol.<node> granted only to call mesh-enrolment.redeem and to hear its own
inbox; §6: from the lease write the controller's enrolment subject is not served. The enrolment principal now calls
redeem in its own name while the seat's holder serves it, and keeps mesh.control.enrol only until Records says the
lease is handed away (a field the grants part sets and the controller's composer never does). A user left able to
enrol nowhere is refused by name rather than composed empty. Golden lists unchanged. Tested as a subtest of
TestTheCopiedComposerComposesAsTheControllers, no new test function.

(issue 774, 774/S40)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 8c2ce57eee Compose a node's two logins from the vault's node-logins, so a rotation can switch with both loaded
ADR 0583 §1: a node's account rotates between node.<n> and node.<n>--b, each with the node's permissions and its
inbox _INBOX.node.<n>. Records gains NodeLogins (each node's key of node-logins; the context file's NodeRotating,
renamed because a node that rotated and rotates no more logs in as its second login alone), and Users composes one
node user per login: the one in use and, while it rotates, the other. Each login calls in its own name, which is how
the vault tells the login that confirms (§3). While the vault serves rotate-node, each node reads its own node's key
of node-logins alone and may call node-account-confirm in its own name (§1 insight); the grants part is the state's
one named reader. With no rotation every list is the controller's golden one, unchanged. Tested as a subtest of
TestTheCopiedComposerComposesAsTheControllers, no new test function.

(issue 774, 774/S39)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 69270a30d5 Add the vault's rotation verbs and the state node-logins, so a node's account rotates over two logins on one contract
ADR 0583 §1 (insight 2026-11-01) keeps which login a node uses in the vault's state node-logins, one key per node:
the login in use, the one rotating and the stage (begun, ready, confirmed), with the list revision that held both.
§2, §3 and §5 give the vault's seat rotate-node (with the recorded hand act's id), node-account-confirm (the caller
is the proof) and abandon, optional until the vault serves them; the events rotation-begun, node-account-ready,
rotation-done and the engine's finding node-account-fallback are named beside them. The codec refuses a stage without
a rotation and a rotation to anything but the node's other login; an empty rotating reads as none. Tested as rows of
TestNodeRecord and TestTheVaultsSeatPromisesItsIntakeVerbs, no new test function.

(issue 774, 774/S38)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben d7a00e1f26 Add the vault's enrolment verbs to its seat, so mesh-enrolment asks the vault to mint and sign and holds nothing
ADR 0587 §3 and §5 (changing ADR 0561 §5) have the vault make the token and its hash (enrolment-token), answer it
sealed to the operator key for tokens to relay (sealed, §8), drop both at every end (drop), and mint, answer again
and retire a joining node's account (node-account), with mesh-enrolment their only caller; sign names mesh-enrolment
for a joining node's certificate (with the serving key it presented, since the node has no record yet) and for a
redeem answer. Both verbs optional until the vault that runs serves them. Their answers' shapes are in go/delivery.
Tested as rows of TestTheVaultsSeatPromisesItsIntakeVerbs, no new test function.

(issue 774, 774/S37)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 2ee75954ad Move the joining token's shape into mesh-sdk, so the vault that makes it, mesh-cli and the engine read one type
From the lease write the vault makes the token (ADR 0587 §3), mesh-cli opens and prints it, and the node-engine
parses it: three repositories, so the type leaves mesh-host's internal/identity (which keeps an alias) for
go/delivery, field names unchanged from the controller's token issue, the tunnel kept (the lead's settlement 7).
Encode is added, refusing a token with a part missing. The test reads a token the controller's own code made and
encodes it back to the same line. Paid by merging TestGateBuckets into TestKeysOfPlainNamesAreUnchanged.

(issue 774, 774/S36)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 959f57294a Add the contract of the enrolment state and of redeem, so the holder, the grants part and the engine read one shape
ADR 0587 §2 gives the seat mesh-enrolment the bucket enrolments with keys node.<node> (an Enrolment: node, address,
why, caller, ask, stage, issued, expires, keys digest) and address.<address> (the node's name alone), no secret in
either. The token's life rules (an hour by default, at most a day, §4), the event enrolment-expired's content (§2),
and redeem's call, proof bytes, keys digest and signed answer (§6) live here too, because the holder in
mesh-delivery and the engine in mesh-host both read them. The proof binds the node and its keys, not the token's
secret, which the holder never holds (§1). Tested as rows of TestNodeRecord, no new test function.

(issue 774, 774/S35)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
jschoubben 59b4c7910b Add the seat mesh-enrolment: six verbs and five events, so the module that joins a machine has a role the judge knows
ADR 0587 §1 makes joining a machine a seat held once by the module mesh-enrolment, the vault's only caller for its
enrolment verbs. The seat is in the mesh's own set, its verbs not optional (the seat is new with its holder), and
its events the five that carry no secret. The test is a block in TestHoldingAMeshSeatRequiresServingItsVerbs, no new
test function.

(issue 774, 774/S34)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 01:41:03 +01:00
mesh-tools 5758e9fb57 Merge pull request 'The lease write's contract: the seat mesh-grants, the lease cut, processes follow their membership from state alone (issue 774)' (#156) from feat/l3-removal into main 2026-11-02 00:35:20 +00:00
jschoubben c21d8fd969 Fold the seat mesh-grants' test into the seat-verb test, within the test budget
mesh/delivery merged: source.main moved to novox/mesh-sdk@5758e9fb57ab
mesh/delivery-group group feat/l3-removal merged: every member is merged
mesh/check failed: mesh-build-go: the check of novox/mesh-catalog#590: the ask mvyhumdm860c7f's step on shanks did not end within 30m0s of its start |…
The repository is over its unit budget and a change may not raise the count: the case of the seat mesh-grants
(ADR 0582 clause 1) runs as a subtest of TestTheDeliverySeatPromisesChecks instead of a function of its own.

(issue 774, 774/S1)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:50:37 +01:00
jschoubben bbfda29b49 The watchman hears the lease write's events and the stream ASSIGNMENTS deleted
ADR 0582 clauses 4 and 6 have mesh-grants say lease-altered and removal-failed "as a finding the watchman
raises". WatchmanHears, the one list its grant and its subscriptions come from, gains the seat mesh-grants'
three events and the advisory of ASSIGNMENTS deleted (which, with the controller's consumer deleted that it
hears already, clears a failed removal). Core subjects, read-only, no durable consumer.

Test: rows added to the watchman's subjects in TestTheCopiedComposerComposesAsTheControllers; no new function.

(issue 774, 774/S22)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:37:04 +01:00
jschoubben 3ed41f02d5 The keep list holds the three kept to the write, since this delivery drops every other read of the controller
ADR 0571 §13: the lease write's own delivery drops every entry but the builder's artifacts-gone, the artifact
sweep's collect and the engine's following of the controller's user list. Every module of this group stops
its read, invoke or consume of the controller (pacman, the keeper, mesh-config, the hand-act log's readers, the
watcher, messenger, the assigner, mesh-grants), so the list shrinks to the three and a read put back is
refused in either phase. Supersedes the keep of pacman's read at mesh-delivery 4a84370.

Tests: rows of TestTheLeaseWritesCheckJudgesEveryDependencyOnTheController changed (the keeper's read put back
is refused; the sweep's collect passes); no new test function.

(issue 774, 774/S30)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:33:34 +01:00
jschoubben 09a5eb5783 Delete PlacementProposalChange.BeforeLease: the assigner no longer keeps the controller's assignments in step
It said which placement changes waited for the lease write while the assigner called the controller's assign,
unassign, pin and unpin (ADR 0567 §8). Since the assigner calls no controller verb (774/S25), nothing reads it.

Test: its table in TestPlacement goes with it.

(issue 774, 774/S25)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:32:13 +01:00
jschoubben a4ed4e6742 Stop hearing mesh.assignment: a process follows its membership from the grants part's state alone
ADR 0571 clause 10: the grants part publishes memberships on mesh.assignment until the lease write and stops
then. FollowMembership now reads and watches its own key of the state memberships and nothing else, and refuses
to follow, naming the state, when it cannot read it (there is nothing else to follow, and a silent follow of
nothing is the fault). A module's principal and the runtime lose their subscribe on mesh.assignment; the grants
part's publish grant stays until the write (S21 stops the publishing).

Tests: TestFollowMembershipHearsWhatIsIssuedToTheAccount (integration) edited: no state is a refusal, a
membership put in the state is applied, one published on the subject is not; run locally against its
embedded bus. Rows added to TestTheCopiedComposerComposesAsTheControllers: nobody subscribes mesh.assignment,
and the controller's golden grant of it is the one row the copy now lacks. No new test function.

(issue 774, 774/S5)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:19:15 +01:00
jschoubben d7a008bee5 Move the controller-dependence judge into mesh-sdk, so three repositories run the same lease-write check
ADR 0571 §13 names a test in mesh-catalog, mesh-delivery and mesh-tools that refuses a manifest depending on
the controller beyond the lease and the entries kept. The judge lived in mesh-grants (leasecheck.go); it moves
here whole (the kinds, the phases, KeepList, EndedBy, Dependencies, Judge) with ManifestRefusals(manifests,
phase) for those tests. Kept is renamed KeptDependency (catalogue already has a Kept), and a gap is Unread.
mesh-grants re-exports it in its own commit; the keep list is the one at mesh-delivery 4a84370.

Test: TestTheLeaseWritesCheckJudgesEveryDependencyOnTheController, moved from mesh-grants'
leasecheck_test.go (its manifest rows and the keep-list test, which mesh-grants deletes), with the
conditions row of 774/S4/AC1 added; not a new test.

(issue 774, 774/S4)

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:17:13 +01:00