Repository navigation
fix: show the SubVault configuration before a CREATE_CHILD approval - #164
Merged
Merged
Conversation
Collaborator
|
Can you ask an agent to create screenshots for the UI changes and link them in the PR? |
Collaborator
Author
mellowcroc
previously approved these changes
Oct 8, 2026
…ddress, shared reservation loader
graikos
force-pushed
the
fix/create-child-config-display
branch
from
October 9, 2026 09:21
27eeb3c to
5c8b5d5
Compare
mellowcroc
approved these changes
Oct 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.





Fixes F-2026-19344.
In short
A
CREATE_CHILDproposal commits to the new SubVault's owners and threshold only through a hash inproposal.data. The contract initializes exactly what was approved, but neither approval surface showed approvers what that was: the web page fetched the owners and threshold, checked their hash, then discarded them and let Approve through while the check was still running; the offline bundle never carried them, so the CLI printedThreshold (unknown)and no owner list. A dishonest root owner could propose a SubVault they alone control and have the others approve it blind.Now both surfaces show the reserved owner list and threshold, verified against
proposal.data, and nothing is approved or exported until they are. The offline request bundle becomes version 2 to carry them; the CLI rejects version 1.Web (
ui/app/transactions/[id]/page.tsx)SubVault Thresholdas "t of n" and the fullSubVault Ownerslist from the reservation whose hash matched the signed data. One loader (lib/child-reservation.ts) serves the page's preflight, its execute path and the offline exporter, and tells four states apart: not indexed yet, invalid (a duplicated or mis-addressed reservation, shown with its reason and blocked, instead of being mistaken for indexer lag), mismatch and match.buildOfflineApproveBundlerefuses to build when the reservation is missing or does not match.Offline bundle and CLI
buildOfflineApproveBundlefetches the child's owncreateChildConfigandcreateChildOwnerevents for aCREATE_CHILDproposal, alongside the account snapshots, checks their hash againstproposal.data, refuses aCREATE_CHILDrecord without a child address, and putschildAddress,childOwnersandchildThresholdin the bundle.OFFLINE_BUNDLE_VERSIONis 2; signed responses stay at 1 (OFFLINE_RESPONSE_VERSION, now beside the request version incontracts/offline-format).OFFLINE_REQUEST_VERSION(2) andSTORE_CHECKPOINT_VERSION(1) live in a new pure module,contracts/offline-format, used by the UI'sOFFLINE_BUNDLE_VERSION, the CLI's version gate andstoresFromOfflineRequest, which used to pin the request version to 1 itself. The checkpoint's own format is unchanged.contracts/srcchanges are plain TypeScript outside the circuit; the VK jobs run on the PR as always.assertCreateChildBundleConfigrequires aCREATE_CHILDapprove or execute bundle to carry a well-formed owner list and threshold that hash, in reserved slot order, toproposal.data, and a bundled child address equal to the proposal's. Missing, malformed, oversized, reordered or swapped configurations abort with no summary and no signature; a numeric type code gets the same check. The summary then prints the checked owners and threshold;handleApproveandhandleExecuterepeat the check for direct callers, and the execute path's former inline copy is gone.Compatibility
Request bundles exported by an older UI are refused with "Unsupported bundle version: 1 (expected 2; export a new request with the current UI)". Pending offline requests must be re-exported; nothing else changes. No contract, proof, schema or signed-response change. A new offline CLI release is needed alongside this UI.
Tests
CREATE_CHILDapproval without its config before rendering a summary;assertCreateChildApprovalConfigaccepts the reserved configuration and rejects missing, empty, out-of-range, invalid-address, reordered, truncated and re-thresholded ones; the summary prints the owners and threshold with no(unknown).1).test:ui: 40 pass locally before the review fixes, and green on CI at9567fa2after them. Two new chainless tests render aCREATE_CHILDapproval with a canonical parent and child; with the reservation indexed the owners, threshold and an enabled Approve appear, and with it unindexed Approve is replaced by the disabled waiting button.offline-cli-e2e.test.ts, SKIP_PROOFS): 14 of 16 passed on the first full run; the two createChild tests failed because the test's hand-built approve bundle predates the config fields. With the bundle carryingchildAddress, the owners in reserved slot order andchildThreshold, the child-lifecycle block passes (8 of 8). CI runs the full file.test:e2e.Docs
Offline audit guide (CLI flow step 1, bundle format reference for version 2, approve extras, threat model), UI audit guide (reservation check and chainless regression), and every other place that still described version 1 requests: the root, desktop and e2e READMEs, the desktop and security audit guides, and the code comments in the worker, the CLI and
ui/lib/offline-format.ts. The signed-response sample in the offline guide said version 2; it is 1.