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
Contributor

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

  • The switch (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, --provider and the outside-issued form), secret ask / accept --at-desk, secret issued and secret rotate take 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.
  • The vault's path, never a clear value through the controller. Each intake verb is two steps: the vault answers a key it made for that one call, then the controller carries what was sealed to it.
    • 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.
    • The hand-act log stays the controller's, as before.
  • The vault's seat (internal/catalogue/seats.go) promises accept, secret-ask, issued, rotate, each optional until the vault that runs serves it (design 33 §7). No input takes a value.
  • Asked in the controller's own name (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 like AsksIssued, so the installer's first user list is unchanged (TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose passes 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 on mesh.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.
  • Every existing desk, issued and secret test passes unchanged.

Deliberately left

  • Turning the switch on per module, and the node asking the vault: V4 (issue 647).
  • The secrets themselves moving in: V3 (issue 676). The vault's names are own/<node>/<module>/<name> and provision/<provider node>/<provision>.
  • plex's own tool: unchanged.
  • The live check that the controller's composed grant reaches the vault's subject is seen in the lab rehearsal.

Reviewer's checklist

  1. Does what issue 675's Expected says, as amended by its decision note: the four verbs reach the vault, only for a module filled the new way. Nothing outside it. Yes.
  2. The Done-when proof exists as new tests, listed above. They fail without the code: they reference the new functions, and a mutation that drops the issued route fails TestAnIssuedValueForAProviderFilledTheNewWayGoesToTheVault. No existing test was changed.
  3. Nothing composes differently for a module that has not moved: the switch is false for all, every today path is the old code moved into acceptKept / rotateKept, and the installer's user list test passes unchanged. Yes.
  4. No secret in a log, event, bucket, fixture or commit: the tap test proves it for accept; the test values are made up. No database change and no migration. Yes.
  5. Strict parsers: the seat promises the verbs here, and the catalogue manifest that serves them (mesh-catalog#302) merges after this. Yes.
  6. gofmt -l cmd internal examples is empty and go 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.
  7. Words: config value, walk, delivery, node-engine; internal names glossed. Yes.
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 - **The switch** (`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, `--provider` and the outside-issued form), `secret ask` / `accept --at-desk`, `secret issued` and `secret rotate` take 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. - **The vault's path, never a clear value through the controller.** Each intake verb is two steps: the vault answers a key it made for that one call, then the controller carries what was sealed to it. - `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. - The hand-act log stays the controller's, as before. - **The vault's seat** (`internal/catalogue/seats.go`) promises `accept`, `secret-ask`, `issued`, `rotate`, each optional until the vault that runs serves it (design 33 §7). No input takes a value. - **Asked in the controller's own name** (`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 like `AsksIssued`, so the installer's first user list is unchanged (`TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose` passes 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 on `mesh.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`. - Every existing desk, issued and secret test passes unchanged. ## Deliberately left - Turning the switch on per module, and the node asking the vault: V4 (issue 647). - The secrets themselves moving in: V3 (issue 676). The vault's names are `own/<node>/<module>/<name>` and `provision/<provider node>/<provision>`. - plex's own tool: unchanged. - The live check that the controller's composed grant reaches the vault's subject is seen in the lab rehearsal. ## Reviewer's checklist 1. Does what issue 675's Expected says, as amended by its decision note: the four verbs reach the vault, only for a module filled the new way. Nothing outside it. Yes. 2. The Done-when proof exists as new tests, listed above. They fail without the code: they reference the new functions, and a mutation that drops the issued route fails `TestAnIssuedValueForAProviderFilledTheNewWayGoesToTheVault`. No existing test was changed. 3. Nothing composes differently for a module that has not moved: the switch is false for all, every today path is the old code moved into `acceptKept` / `rotateKept`, and the installer's user list test passes unchanged. Yes. 4. No secret in a log, event, bucket, fixture or commit: the tap test proves it for accept; the test values are made up. No database change and no migration. Yes. 5. Strict parsers: the seat promises the verbs here, and the catalogue manifest that serves them (mesh-catalog#302) merges after this. Yes. 6. `gofmt -l cmd internal examples` is empty and `go 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. 7. Words: config value, walk, delivery, node-engine; internal names glossed. Yes.
mesh-admin added 4 commits 2026-10-14 19:15:18 +00:00
ADR 0349 clauses 8 to 10 make accept, secret-ask, issued and rotate the
vault's. A module still filled the old way gets its secrets only from the
declaration the controller seals, so forwarding its verbs would report
success and change nothing on its machine: the switch sends a module's
verbs to the vault only once its secrets are filled the new way, and is
off for every module until V4.

What the controller carries it cannot open: the vault makes a key for each
call; the terminal seals an accepted value to it, and the desk's prompt and
a provider's tool seal theirs to it. The vault's seat promises the four
verbs, optional until the vault that runs serves them, and the controller
asks them in its own name, granted from the records as the issued tools
are, so the installer's first user list is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The vault takes a value only from the controller, which it knows from the
subject that names its caller. The grant is composed from the records, as
the issued tools' is, so the installer's first user list is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Prove the vault's path of each secret verb, and today's for a module filled the old way (issue 675)
mesh/delivery-group group pkg/57-v2-vault-verbs rejected: a member's own check failed
mesh/merge-gate head 65531d737514 merged into trunk fcdecb436117 — pass: [release feat/57-config-and-provisioning, judged by its controller 39cc132d5d0f] t…
mesh/repo-check head 65531d737514 merged into trunk fcdecb436117 — fail: [release feat/57-config-and-provisioning, judged by its controller 39cc132d5d0f] i…
mesh/delivery stopped: the pull request closed unmerged
65531d7375
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Contributor

Delivery novox/mesh-controller@65531d737514 — stopped since 2026-10-14T19:30:29Z

Delivery 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@65531d7375

Transitions

  • 2026-10-14 19:15 (new) → proposed (announced): novox/mesh-controller#337's head announced
  • 2026-10-14 19:20 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
  • 2026-10-14 19:20 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed
  • 2026-10-14 19:30 rejected → stopped (closed): the pull request closed unmerged

The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.

<!-- mesh-delivery:view --> **Delivery** `novox/mesh-controller@65531d737514` — **stopped** since 2026-10-14T19:30:29Z **Delivery plan** — builds nothing: the change touches no module of the mesh's graph **Group** `pkg/57-v2-vault-verbs`, in order: novox/mesh-catalog@eb958f668ecd → novox/mesh-controller@65531d737514 **Transitions** - 2026-10-14 19:15 (new) → proposed (announced): novox/mesh-controller#337's head announced - 2026-10-14 19:20 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit - 2026-10-14 19:20 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed - 2026-10-14 19:30 rejected → stopped (closed): the pull request closed unmerged The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
Author
Contributor

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.

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.
Author
Contributor

Merge check at 65531d73
Judged: head 65531d737514 merged into trunk fcdecb436117; read beside it: mesh-catalog 1a2c917abfdb, mesh-controller-main c2ec0a601acb, mesh-host 53fd32618916, mesh-tools d0dcae53a8c0

  • mesh/merge-gate: PASS — [release feat/57-config-and-provisioning, judged by its controller 39cc132d5d0f] the change touches no module of the mesh's graph
  • mesh/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).

--- judged for the release branch feat/57-config-and-provisioning by its controller at 39cc132d5d0f, with mesh-host's validator of feat/57-config-and-provisioning at 53fd32618916; read beside it: mesh-catalog feat/57-config-and-provisioning at 1a2c917abfdb, mesh-controller-main main at c2ec0a601acb, mesh-host feat/57-config-and-provisioning at 53fd32618916, mesh-tools main at d0dcae53a8c0
--- its merge-check.sh (go toolchain)
ok  	github.com/novox/mesh-controller/cmd/mesh-builder	1.096s
ok  	github.com/novox/mesh-controller/cmd/mesh-controller	206.314s
ok  	github.com/novox/mesh-controller/examples/objectstore-provisioner	1.041s
ok  	github.com/novox/mesh-controller/examples/postgres-provisioner	1.049s
ok  	github.com/novox/mesh-controller/examples/redis-provisioner	1.039s
ok  	github.com/novox/mesh-controller/examples/route-proxy	1.215s
ok  	github.com/novox/mesh-controller/internal/artifacts	1.093s
?   	github.com/novox/mesh-controller/internal/beside	[no test files]
--- FAIL: TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose (0.76s)
    genesis_template_test.go:29: judged against /var/lib/build-agent/workspace/check/mesh-host as cloned beside this check
    genesis_template_test.go:48: the installer's user list lets the controller publish [$KV.mesh-controller_assignments.> $KV.mesh-controller_declared-config.> mesh.seat.mesh-controller.event.assignment-changed mesh.seat.mesh-controller.event.declared-config-changed], which it does not derive
FAIL
FAIL	github.com/novox/mesh-controller/internal/broker	3.648s
ok  	github.com/novox/mesh-controller/internal/builder	43.000s
ok  	github.com/novox/mesh-controller/internal/catalogue	9.329s
ok  	github.com/novox/mesh-controller/internal/conditions	2.727s
ok  	github.com/novox/mesh-controller/internal/envfile	1.064s
ok  	github.com/novox/mesh-controller/internal/facts	1.063s
ok  	github.com/novox/mesh-controller/internal/identity	5.105s
ok  	github.com/novox/mesh-controller/internal/inventory	38.012s
ok  	github.com/novox/mesh-controller/internal/lease	17.735s
ok  	github.com/novox/mesh-controller/internal/licences	4.276s
ok  	github.com/novox/mesh-controller/internal/licences/adapters	1.062s
ok  	github.com/novox/mesh-controller/internal/link	59.430s
ok  	github.com/novox/mesh-controller/internal/lint	2.666s
ok  	github.com/novox/mesh-controller/internal/outward	1.093s
ok  	github.com/novox/mesh-controller/internal/overlay	1.081s
ok  	github.com/novox/mesh-controller/internal/secrets	1.579s
ok  	github.com/novox/mesh-controller/internal/store	3.584s
ok  	github.com/novox/mesh-controller/internal/testbus	1.263s
ok  	github.com/novox/mesh-controller/internal/token	1.016s
FAIL
--- what failed, picked from the whole of its output (the whole is in the build's log)
--- FAIL: TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose (0.76s)
    genesis_template_test.go:29: judged against /var/lib/build-agent/workspace/check/mesh-host as cloned beside this check
    genesis_template_test.go:48: the installer's user list lets the controller publish [$KV.mesh-controller_assignments.> $KV.mesh-controller_declared-config.> mesh.seat.mesh-controller.event.assignment-changed mesh.seat.mesh-controller.event.declared-config-changed], which it does not derive
FAIL	github.com/novox/mesh-controller/internal/broker	3.648s
**Merge check** at `65531d73` Judged: head `65531d737514` merged into trunk `fcdecb436117`; read beside it: mesh-catalog `1a2c917abfdb`, mesh-controller-main `c2ec0a601acb`, mesh-host `53fd32618916`, mesh-tools `d0dcae53a8c0` - `mesh/merge-gate`: **PASS** — [release feat/57-config-and-provisioning, judged by its controller 39cc132d5d0f] the change touches no module of the mesh's graph - `mesh/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`). ``` --- judged for the release branch feat/57-config-and-provisioning by its controller at 39cc132d5d0f, with mesh-host's validator of feat/57-config-and-provisioning at 53fd32618916; read beside it: mesh-catalog feat/57-config-and-provisioning at 1a2c917abfdb, mesh-controller-main main at c2ec0a601acb, mesh-host feat/57-config-and-provisioning at 53fd32618916, mesh-tools main at d0dcae53a8c0 --- its merge-check.sh (go toolchain) ok github.com/novox/mesh-controller/cmd/mesh-builder 1.096s ok github.com/novox/mesh-controller/cmd/mesh-controller 206.314s ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.041s ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.049s ok github.com/novox/mesh-controller/examples/redis-provisioner 1.039s ok github.com/novox/mesh-controller/examples/route-proxy 1.215s ok github.com/novox/mesh-controller/internal/artifacts 1.093s ? github.com/novox/mesh-controller/internal/beside [no test files] --- FAIL: TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose (0.76s) genesis_template_test.go:29: judged against /var/lib/build-agent/workspace/check/mesh-host as cloned beside this check genesis_template_test.go:48: the installer's user list lets the controller publish [$KV.mesh-controller_assignments.> $KV.mesh-controller_declared-config.> mesh.seat.mesh-controller.event.assignment-changed mesh.seat.mesh-controller.event.declared-config-changed], which it does not derive FAIL FAIL github.com/novox/mesh-controller/internal/broker 3.648s ok github.com/novox/mesh-controller/internal/builder 43.000s ok github.com/novox/mesh-controller/internal/catalogue 9.329s ok github.com/novox/mesh-controller/internal/conditions 2.727s ok github.com/novox/mesh-controller/internal/envfile 1.064s ok github.com/novox/mesh-controller/internal/facts 1.063s ok github.com/novox/mesh-controller/internal/identity 5.105s ok github.com/novox/mesh-controller/internal/inventory 38.012s ok github.com/novox/mesh-controller/internal/lease 17.735s ok github.com/novox/mesh-controller/internal/licences 4.276s ok github.com/novox/mesh-controller/internal/licences/adapters 1.062s ok github.com/novox/mesh-controller/internal/link 59.430s ok github.com/novox/mesh-controller/internal/lint 2.666s ok github.com/novox/mesh-controller/internal/outward 1.093s ok github.com/novox/mesh-controller/internal/overlay 1.081s ok github.com/novox/mesh-controller/internal/secrets 1.579s ok github.com/novox/mesh-controller/internal/store 3.584s ok github.com/novox/mesh-controller/internal/testbus 1.263s ok github.com/novox/mesh-controller/internal/token 1.016s FAIL --- what failed, picked from the whole of its output (the whole is in the build's log) --- FAIL: TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose (0.76s) genesis_template_test.go:29: judged against /var/lib/build-agent/workspace/check/mesh-host as cloned beside this check genesis_template_test.go:48: the installer's user list lets the controller publish [$KV.mesh-controller_assignments.> $KV.mesh-controller_declared-config.> mesh.seat.mesh-controller.event.assignment-changed mesh.seat.mesh-controller.event.declared-config-changed], which it does not derive FAIL github.com/novox/mesh-controller/internal/broker 3.648s ```
Author
Contributor

Verdict: CHANGES at 65531d7375

Reviewed 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.sh against 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:

  1. Point (1) of the lead's decision ("a test proves an unmoved module's verb still takes today's path") is proven only for the parts, not for the four commands. I changed the wiring so every module goes to the vault, at secret.go:112, :133 and :520, desk_secret.go:287 (d.vault = theVault(ctx) without the switch) and issued.go:273 (ofTheVault: func(string) bool { return true }), and go 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 --provider decides by the consumer's module but 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 insight on ADR 0349, or an issue tied to issue 569). A controller that is compromised can still pass its own key as seal_to to 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: secretsOfTheVault is 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 only mesh.seat.mesh-vault.call.<verb>.controller for the verbs the holder serves, and not get. The installer's controller gets no vault grant (TestTheControllerMayAskTheVaultInItsOwnName).

Verdict: CHANGES at 65531d7375140f97b5b45ab0930574cd03c011e5 Reviewed 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.sh` against 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: 1. Point (1) of the lead's decision ("a test proves an unmoved module's verb still takes today's path") is proven only for the parts, not for the four commands. I changed the wiring so every module goes to the vault, at secret.go:112, :133 and :520, desk_secret.go:287 (`d.vault = theVault(ctx)` without the switch) and issued.go:273 (`ofTheVault: func(string) bool { return true }`), and `go 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 --provider` decides by the consumer's `module` but 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 `insight` on ADR 0349, or an issue tied to issue 569). A controller that is compromised can still pass its own key as `seal_to` to 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: `secretsOfTheVault` is 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 only `mesh.seat.mesh-vault.call.<verb>.controller` for the verbs the holder serves, and not `get`. The installer's controller gets no vault grant (TestTheControllerMayAskTheVaultInItsOwnName).
Author
Contributor

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 head 65531d73 is merged into that branch as "Bring in V2's controller half (issue 675)"; review comment 12438's change is being made there.

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 head 65531d73 is merged into that branch as "Bring in V2's controller half (issue 675)"; review comment 12438's change is being made there.
mesh-admin closed this pull request 2026-10-14 19:27:18 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-controller#337