57/V2: The controller's secret verbs go to the vault for a module filled the new way (issue 675) #337
Closed
mesh-admin
wants to merge 4 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/sweep-2026-10-30
:fix/checker-full-failure
:feat/1945-user-list-switch
:fix/1945-mesh-grants-publishes-memberships
:fix/issued-states-follow-the-module
:fix/1945-credential-on-assignment
:fix/r6-mirror-on-change
:fix/store-forge-address
:fix/r6-look-again-after-unlock
:fix/r6-key-waits-said
:fix/1931-reconnects-verb
:fix/forge-requires-no-status
:fix/906-lease-renewal
:feat/r4e-controller
:fix/1106-sdk-member-merges
:fix/1399-person-word-test
:fix/1652-checks-wait
:feat/files-through-the-store-files-verbs
:fix/1649-held-ask-handed-out-twice
:fix/1658-sdk-items
:fix/1334-a-bus-reload-fails-a-tier
:feat/chain-on-the-bus
:fix/701-a-name-nothing-answers-is-not-used
:fix/270-a-dead-bus-watch-is-heard
:fix/630-config-values-from-four-sources
:fix/613-node-smb-server
:feat/328-libraries-and-module-users
:feat/325-identities-and-kept-folders
:feat/bus-view-principal
:test/plan-diff-left-out-line
:fix/the-registry-trust-test-reads-the-runtimes-module
:fix/the-runtime-file-is-the-runtimes
:feat/build-edges-are-recorded
:fix/several-contributions-collide-in-grants-v2
No Reviewers
No labels
Milestone
No items
No Milestone
Assignees
agent-ace
agent-g14
agent-novox
agent-shanks
jschoubben
mesh-tools
miel.truyen
nox-agent
Clear assignees
No Assignees
No due date set.
Dependencies
No dependencies set.
Reference: novox/mesh-controller#337
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), the controller's half. The vault's half is mesh-catalog#302 (the same branch name,
pkg/57-v2-vault-verbs). Merge this one first: the catalogue's vault manifest serves the new verbs, and the controller's module check refuses it until this seat set is merged (checked: the feat/57 controller refuses it, this one accepts it).What changed
cmd/mesh-controller/vault_secrets.go).secretsOfTheVault(module)says whether a module's secrets are filled the new way. It is false for every module until V4 (issue 647).secret accept(own,--providerand the outside-issued form),secret ask/accept --at-desk,secret issuedandsecret rotatetake the vault's path only when it is true; every other module keeps today's path unchanged. This is the release lead's decision on issue 675 (latest note): forwarding a module still filled the old way would report success and change nothing on its machine.accept: the terminal seals the value it read to the vault's call key before anything leaves the process (acceptIntoVault).secret-ask: the vault records the ask and holds its bounds before the prompt; the prompt is asked with the vault's key and the asker as the vault recorded it; the sealed answer goes to the vault unopened; the controller's store is not touched (deskGive.giveToVault).issued: the provider's tool is asked as today (it answers the controller alone) but with the vault's key; nothing is kept, sealed or sent here (issuedTaker.takeIntoVault).rotate: asks the vault, naming who asked.internal/catalogue/seats.go) promisesaccept,secret-ask,issued,rotate, each optional until the vault that runs serves it (design 33 §7). No input takes a value.link.AskMeshSeatToolAs, on the subject that names the caller, issue 365), so the vault knows the controller asks. The grant (broker.VerbsTheControllerAsksTheVault,Principal.AsksTheVault) is composed from the records likeAsksIssued, so the installer's first user list is unchanged (TestTheInstallersFirstUserListIsWhatTheControllerWouldComposepasses untouched).Why the controller carries the call
ADR 0349 clause 10 says the provider's tool answers the vault alone. 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 be told apart on the bus, and cannot call the desk's prompt (ControllerOnly) or a provider's tool in a name of its own. The controller therefore carries each call with a key only the vault holds. The value opens in the vault alone (clause 9, ADR 0277 §23), but the provider's tool still sees the controller as its caller. plex's tool needs no change for this.
How it is proven
TestNoModulesSecretsAreTheVaultsBeforeV4: the switch is off for every module.TestTheSwitchRunsOnePathByTheModulesForm: one path by the module's form, never both.TestAnAcceptedValueCrossesTheBusOnlySealedToTheVault: over a real bus with a tap on>: the vault is asked onmesh.seat.mesh-vault.call.accept.controller, and the value is in no message, no log line and no answer.TestAnAskForAModuleFilledTheNewWayIsTheVaults: vault path (today's record and accept untouched, the prompt names the vault's asker, dismissed is the vault's outcome, the vault's bounds refuse before any prompt) and today's path for a module filled the old way.TestAnIssuedValueForAProviderFilledTheNewWayGoesToTheVault: vault path (no keep, no send, act recorded, same value writes nothing) and today's path with the vault never asked.TestARotationForAModuleFilledTheNewWayIsTheVaults.TestTheVaultsSeatPromisesItsIntakeVerbs,TestAMeshSeatsVerbIsAskedInTheCallersOwnName,TestTheControllerMayAskTheVaultInItsOwnName.Deliberately left
own/<node>/<module>/<name>andprovision/<provider node>/<provision>.Reviewer's checklist
TestAnIssuedValueForAProviderFilledTheNewWayGoesToTheVault. No existing test was changed.acceptKept/rotateKept, and the installer's user list test passes unchanged. Yes.gofmt -l cmd internal examplesis empty andgo vet ./...passes.MESH_TEST_POSTGRES=postgres://postgres@127.0.0.1:55472/postgres?sslmode=disable sh merge-check.sh(throwaway PostgreSQL, race detector on) exits 0, every listed store test PASS. Yes.Delivery
novox/mesh-controller@65531d737514— stopped since 2026-10-14T19:30:29ZDelivery plan — builds nothing: the change touches no module of the mesh's graph
Group
pkg/57-v2-vault-verbs, in order: novox/mesh-catalog@eb958f668e → novox/mesh-controller@65531d7375Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.The vault's half is mesh-catalog#302 (same branch name,
pkg/57-v2-vault-verbs, head eb958f668ecd). Merge this pull request first: mesh-catalog#302's manifest serves the verbs only this seat set promises.Merge check at
65531d73Judged: head
65531d737514merged into trunkfcdecb436117; read beside it: mesh-catalog1a2c917abfdb, mesh-controller-mainc2ec0a601acb, mesh-host53fd32618916, mesh-toolsd0dcae53a8c0mesh/merge-gate: PASS — [release feat/57-config-and-provisioning, judged by its controller 39cc132d5d0f] the change touches no module of the mesh's graphmesh/repo-check: FAIL — [release feat/57-config-and-provisioning, judged by its controller 39cc132d5d0f] its merge-check.sh failed: --- FAIL: TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose (0.76s)Run by the build seat on shanks as
build-1792005341507354695(builds --log build-1792005341507354695).Verdict: CHANGES at
65531d7375Reviewed together with mesh-catalog#302 (eb958f668ecd), as package V2 of release 57 (issue 675). Checks I ran:
MESH_TEST_POSTGRES=postgres://postgres@127.0.0.1:<port>/postgres?sslmode=disable sh merge-check.shagainst a throwaway PostgreSQL over TCP (dynamic_shared_memory_type=mmap), which exited 0: gofmt, vet, the suite under -race and every listed store test passed. I stopped the server afterwards. I also built mesh-controller from this head and used it as MESH_GATE for #302's merge-check, which exited 0 (the feat/57 controller refuses the vault's manifest, so the pair composes only in this order).Must change:
d.vault = theVault(ctx)without the switch) and issued.go:273 (ofTheVault: func(string) bool { return true }), andgo test ./cmd/mesh-controller/still passed. The only test that guards anything is TestNoModulesSecretsAreTheVaultsBeforeV4, which checks the constant and not the commands. That change of the wiring is exactly the failure the decision guards against: an unmoved module's accept, ask, issued or rotate would report success and change nothing on its machine. Add a test for each of the four commands (accept for an own secret, with --provider, and for an outside offer; askAtDesk; secretIssued; secretRotate) that fails when an unmoved module reaches the vault. For example, make the switch and the vault asker injectable at the command level and assert that the vault is never asked.Should (can follow):
2. secret.go:133-143:
accept --providerdecides by the consumer'smodulebut writes the provider's one credential (provisionArgs(*provider, name)). V4 should decide by the provider's module, as the outside-offer branch (secret.go:112) says it does.3. The departure from clause 10 (and clause 9 at the desk) should be written into the record (a knowledge-base
insighton ADR 0349, or an issue tied to issue 569). A controller that is compromised can still pass its own key asseal_toto the desk's prompt or to the provider's tool and open the value. That is no worse than today, but "the provider's tool answers the vault alone" does not hold yet.Verified as correct:
secretsOfTheVaultis a constant false, and no flag, environment variable or setting turns it on. The real-bus tap (>on the publishing connection, so it hears requests and inbox replies) fails when a clear value is added to the first or the second step: I added it to each and the test failed 40 runs out of 40. The controller is granted onlymesh.seat.mesh-vault.call.<verb>.controllerfor the verbs the holder serves, and notget. The installer's controller gets no vault grant (TestTheControllerMayAskTheVaultInItsOwnName).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 head65531d73is merged into that branch as "Bring in V2's controller half (issue 675)"; review comment 12438's change is being made there.