57/V2: accept, secret-ask, issued and rotate are the vault's verbs (issue 675) #302
Closed
mesh-admin
wants to merge 5 commits from
pkg/57-v2-vault-verbs into feat/57-config-and-provisioning
pull from: pkg/57-v2-vault-verbs
merge into: :feat/57-config-and-provisioning
:main
:fix/47-G-start-2
:feat/47-G-join11
:fix/1966-gate-record-catalog
:pre/registry-milestone
:fix/1748-retake-and-resolver
:pin/sdk1
:fix/check-every-failure
:feat/l5-l7
:feat/l5-l7-a3
:feat/judge-once-pkgs
:fix/turn-handed-on-approve
:fix/checker-full-failure
:revert/774-l3
:fix/check-names-every-conflict
:fix/check-speed
:probe/1126-seed-10
:probe/1126-seed-9
:probe/1126-seed-8
:probe/1126-seed-7
:probe/1126-seed-6
:probe/1126-seed-5
:feat/1126-seed-4
:revert/1126-seed-2
:feat/774-vault-mints
:fix/1901-node-test-cause
:fix/1945-adopt-hashes
:fix/1945-vault-hashing
:feat/try-speed
:fix/1921-every-failure
:feat/r4g-finish-composer
:feat/r4g-finish-1935
:fix/1901
:fix/forge-requires-no-status
:feat/mail-list
:feat/modules-name-no-node
:fix/r4e-r2
:fix/r4e-k2
:fix/r4e-k1
:feat/r4e-leaf
:feat/r4e-buildmods
:feat/r4e-gate
:fix/1106-sdk-member-merges
:feat/r4c5-checker
:fix/xterm-config-defaults
:fix/1165-fill-retry
:feat/r4d-automx-go
:feat/r4d-n8n
:fix/1275-group-merges-whole-or-not
:fix/1129-no-drift-pass
:fix/270-nats-emits-bus-faults
:fix/claude-code-tips-preference
:fix/628-modules-declare-every-package-they-need
:fix/613-home-network-shares
:feat/bus-websocket-listener
:fix/340-tool-servers-only-from-the-terminal
:feat/the-store-collects-nightly-again
:feat/dbus-module
No Reviewers
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
agent-ace
agent-g14
agent-novox
agent-shanks
jschoubben
mesh-tools
miel.truyen
nox-agent
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: novox/mesh-catalog#302
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Design 57's V2 (issue 675; ADR 0349 clauses 8 to 10; ADR 0277 §22–§27 and ADR 0305 with the vault in the controller's place), the vault's half. The controller's half is mesh-controller#337, and it merges first: the vault's manifest now serves
accept,secret-ask,issuedandrotate, which only #337's seat set promises. I checked this: the feat/57 controller's module check refuses this manifest (1 problem), and #337's controller accepts it.What changed (modules/mesh-vault)
intake.go: four verbs of themesh-vaultseat.accept,secret-askandissuedare each two steps of one verb, taken from thecontrollercaller alone, as the runtime proved it. The first step names the secret and answerscallandseal_to, the public half of an X25519 key made for that one call (the NaCl anonymous box the desk and provider tools already seal to). The second step carries the value sealed to that key. The vault opens it with the private half, which is kept in memory only and forgotten once used or after two minutes. The value opens nowhere but here.accept: kept with originaccepted. An accepted provision credential is never remade, and a software-issued value is not taken this way.secret-ask: the ask is recorded in the vault's store (asks.jsonl, bounded as the record of hand-outs is) before the answer that lets a prompt open. One open ask per secret (at most 2 min) and three an hour. Who asked is cut to a name and answered back for the prompt. Every outcome is recorded, andsecret_asksreads the record.issued: kept as the provision's one credential, originissued. The same value again writes nothing and says nothing.rotate: refused for an issued value and for an accepted provision credential. Who asked and who carried the act are both kept (changed-by,changed-via).own/<node>/<module>/<name>andprovision/<provider node>/<provision>.consumers,why,by,viaandconfirmthrough to the custody ledger. An argumentbythat differs from the proven caller is now kept beside it (via: "…, called by <caller>"). The roll of the record of hand-outs is said in the journal. The export's fingerprint andvault_statusare tested.Why the controller carries the call
A desk's prompt and a provider's tool answer the controller alone (the subject that names its caller, issue 365). The vault runs in its machine's tool runner, whose one bus account also carries that machine's agents' calls (issue 569). So the vault cannot ask them in a name of its own, and the controller asks them with the vault's call key and passes the sealed answer on unopened. This is how "the provider's tool answers the vault alone" (clause 10) holds today: the tool still answers only the controller, and the value opens only in the vault.
How it is proven
TestAnAskIsRecordedBeforeThePromptAndTheTypedValueOpensOnlyInTheVault: ADR 0349'ssecret-asktest as far as the vault answers it. The ask is in the store before the prompt; the asker is named as the bus named it; the typed value opens only here; nothing the vault said or wrote holds it.TestAnAskIsBoundedToOneOpenPerSecretAndThreeAnHour.TestAnAskIsTakenFromTheControllerAloneAndOnlySealedToItsCall: other callers are refused and fill no record; a value sealed to another key is refused; a call is answered once; a late call is closed; an empty answer is recorded asempty.TestAnIssuingProviderAnswersOnlyTheControllersCallSealedToTheVault: the issuing provider's test, with a stand-in provider, plus ADR 0305 §13's checks that are the vault's: nothing rewritten for a value held, a change kept as a new generation,rotaterefused,acceptrefused for it, the value in nothing said.TestAnAcceptedValueOpensInTheVaultAloneAndIsNotRemade,TestRotateKeepsWhoAskedAndWhoCarriedIt,TestTheNamesOfWhatIsTakenIn,TestTheVerbsTakeTheirCallerFromTheRuntime.TestTheRetirementToolsPassTheActThrough,TestARolledRecordOfHandOutsIsSaid,TestTheExportsFingerprintAndVaultStatus: the V1 follow-ups.Deliberately left
Reviewer's checklist
everything()scans what the vault published and every file it wrote. Test values are made up, there is no bucket, and the store is files. Yes.servesare promised by mesh-controller#337's seat, which merges first. No new manifest field. Yes.gofmt -l .andgo vet ./...in modules/mesh-vault are clean, andgo test -race ./...passes.MESH_GATE=<controller built from #337> MESH_CHECK_CHANGED=modules/mesh-vault/module.json sh merge-check.shexits 0 (words, agent home, secrets, predefined keys and paths checks pass; long-running resources without health: 66, as kept; modules/mesh-vault tested). Yes.Delivery
novox/mesh-catalog@eb958f668ecd— stopped since 2026-10-14T19:35:38ZDelivery plan — builds nothing: the change touches no module of the mesh's graph
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
eb958f66Judged: head
eb958f668ecdmerged into trunk1a2c917abfdb; read beside it: mesh-controllerfcdecb436117, mesh-controller-mainc2ec0a601acb, mesh-host53fd32618916, mesh-toolsd0dcae53a8c0mesh/merge-gate: PASS — [release feat/57-config-and-provisioning, judged by its controller fcdecb436117] the change touches no module of the mesh's graphmesh/repo-check: FAIL — [release feat/57-config-and-provisioning, judged by its controller fcdecb436117] its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25Run by the build seat on novox as
build-1792005372951451506(builds --log build-1792005372951451506).Verdict: APPROVE at
eb958f668eReviewed together with mesh-controller#337 (65531d737514), as package V2 of release 57 (issue 675). This pull request merges only after #337, and #337 needs a change in its tests first (my verdict there). Nothing in this pull request has to change.
Checks I ran:
MESH_CHECK_MODULES=modules/mesh-vault MESH_CHECK_BASE=feat/57-config-and-provisioning MESH_GATE=<controller built from #337> sh merge-check.shexited 0, and the vault's tests passed. With the feat/57 controller as MESH_GATE the check exits 1, because that controller refuses the newserves, as expected. gofmt -l printed nothing, go vet passed, and go test -race -count=3 passed.To check that the tests guard the rules, I changed the code and confirmed each test fails. Allowing four asks an hour, dropping the one-open-ask rule, letting any caller do the intake steps, and opening the prompt without recording the ask first: each change fails the matching test in intake_test.go. The ask record and both bounds are in the vault's store (asks.jsonl, synced) before the key the prompt seals to is answered (ADR 0277 §24-§27). V1's four follow-ups are correct (followups_test.go). The tools pass by, via, confirm and consumers through, and an unproven
bykeeps the proven caller invia. A roll of the hand-out record is logged and counted, and the count now covers only hand-outs (store.go). The export's fingerprint and vault_status are tested.Should (can follow):
rotatetakes any proven bus caller. It does not go through the controller's switch, so it is not blocked for a module that has not moved, and it does not ask for thewhyof the hand-act log. The store is empty until V3, so this harms nothing today. Before V3, limit it to the controller (or require a why), so that rotating an unmoved module's secret in the vault cannot drift from the value the controller holds.recordAskruns withoutStore.asksMu, so two writers can roll asks.jsonl at the same time. Take the lock around the append.issuedmay replace an accepted value, and write down which.Closed unmerged: feature 57 is now built on one feature branch,
57-config-and-provisioning, in every repository, pushed and opened as one pull request per repository when every issue is done (the operator's rule, 2026-10-14). This headeb958f66is on that branch (V2's catalogue half, issue 675).Pull request closed