Repository navigation
fix: rebase SND-003 onto PR893 + QA-campaign fix batches #894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 35 commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
99980f5
fix(migration): prompt for wallet passwords before completing migration
lklimek f99630b
fix(migration): free the password prompt from the SPV overlay, add a …
lklimek 03d4c31
Merge branch 'fix/migration-prompt-ux' into feat/migration-password-p…
lklimek 8c6a96a
wip(migration): headless fail-fast, legacy read-only, registration si…
lklimek 5873570
fix(shielded): gate fund-moving shielded tasks at the backend chokepoint
lklimek 0362aa0
fix(dashpay): stop erasing accepted accounts, double-submits and sile…
lklimek 8614c6d
fix(wallet): report a corrupted wallet envelope as damage, not a wron…
lklimek f59c81c
fix(dashpay): preserve saved contact details and keep paid actions gu…
lklimek af39624
fix(wallet): unlock a cold-booted protected wallet with its correct p…
lklimek b3e0057
fix(ui): block input outside a non-dismissible modal prompt
lklimek dd347ba
fix(migration): keep wallet work gated while the storage update await…
lklimek 641321b
fix(wallet): collect the redundant legacy seed envelope and stop over…
lklimek 8ea3a14
Merge branch 'fix/dashpay-loss-risks' into integration/review-remedia…
lklimek 37c6813
Merge branch 'fix/shielded-chokepoint' into integration/review-remedi…
lklimek bf5fa3d
Merge branch 'fix/migration-v2-hardening' into integration/review-rem…
lklimek cb4b706
fix(ui): make every passphrase prompt own the interaction surface
lklimek f191629
fix(migration): scope an unlocked seed to the storage update, not to …
lklimek e6dcb76
fix(dashpay): release the request guard when a dispatch is refused pr…
lklimek 7ee54c3
test(backend): pin ShieldedTask inside the wallet-touching migration …
lklimek 555014d
fix(ui): state the disabled-tool reason once, as one translation unit
lklimek 355543b
docs: correct the data-deletion promise and record the migration chan…
lklimek c13d2de
docs(wallet): warn that SecretLease::lease() refcounts per call, not …
lklimek ee2aed5
test(ui): prove the secret prompt's transition-frame click-through
lklimek 3e69b2f
fix(backend): refuse unavailable shielded ops early and scope DashPay…
lklimek 7de49aa
fix(ui): drop the transition-frame click when a passphrase prompt act…
lklimek 3591ea8
test(ui): pin passphrase activation wiring in the real AppState updat…
lklimek d16cb98
fix(wallets): keep dialogs open on trigger clicks
lklimek 1743f7e
build(deps): bump platform to PR3968 tip (d18020f5), pulls in the Ass…
lklimek 52678c4
test(ui): make the opening-click regression test exercise the real guard
lklimek c861b7a
fix(contracts): don't panic when contracts can't load on Update Contr…
lklimek 551315f
fix(dashpay): accept all integer encodings for contact-request key in…
lklimek f99c1e0
fix(mcp): hydrate saved wallets before wallet-facing tools read them
lklimek a40f16a
fix(ui): stop the opening click from immediately cancelling confirmat…
lklimek 6aa8fac
fix(ui): wire missing identity navigation and fix stale post-refresh …
lklimek 82a96ae
fix(backend): stop silent hangs and panics in backend tasks (HANG-CLA…
lklimek 9f64fd5
docs(user-stories): drop transient review-ID citation from UX-001
lklimek ffa7ea0
fix(app): stop migration frame race and preserve vote eligibility acr…
lklimek 0fda1f6
fix(dashpay): make contact-request decline/cancel idempotent
lklimek 68a2090
fix(wallet): fail Clear-Database safely and hydrate legacy wallets fo…
lklimek b633a52
fix(app): correlate task results to their originating operation
lklimek 519690e
fix(wallet): also wipe identity private keys on Clear Database (SEC-001)
lklimek ac69d8b
fix(wallet): report partial failures when Clear Database can't delete…
lklimek 9c9bf1f
test(dashpay): accept both decrypt-failure variants in unreadable-pri…
lklimek 533d121
test(contracts): isolate update_contract_screen degrade test from sha…
lklimek feb2282
fix(wallet): report Clear-Database failure when the identity index ca…
lklimek 8ba5cdb
fix(ui): add Back navigation to the Manage Keys screen (dead-end lock…
lklimek 4c0a1e6
fix(ui): show fee estimate and total before sending Dash (SND-005)
lklimek 6e094f6
fix(dashpay): report the correct cause when Add Contact can't resolve…
lklimek 207dad9
docs: correct SND-005 fee-estimate criterion to match inline pre-send…
lklimek 420198a
fix(ui): guard reusable modal components against opening-frame dismis…
lklimek 3fda14d
fix(ui): guard screen-level popups against opening-frame dismiss (NEW…
lklimek 3132c47
fix(dashpay): show payment-history amount in DASH, not raw duffs (NEW…
lklimek 1896ac7
fix(wallets): confirm single-key removal and refresh asset locks afte…
lklimek c22a508
fix(wallets): restore password-modal focus without leaking background…
lklimek e606874
feat(migration): gate startup migration on a minimum saved-data version
lklimek 6d625ac
test(migration): cover the too-new fail-fast and upper-accept boundary
lklimek c7ebd8a
feat(settings): add developer-only Wipe Platform Data control (NEW-006)
lklimek ef3d5c4
feat(contacts): add View Profile action to Identity Hub contacts (NEW…
lklimek c72658d
fix(wallet): fail-closed on identity-key wipe and surface Clear-Datab…
lklimek aeb81f8
test: serialize DASH_EVO_DATA_DIR mutation with one shared lock
lklimek 3e5e33e
fix(ui): give each modal a unique guard id so popups don't dismiss ea…
lklimek 9bc21d3
fix(ui): move Wipe Platform Data beside its sibling network controls …
lklimek 3b766b0
fix(platform): keep cause-less transition results unconfirmed (#897)
lklimek 0e79a89
docs(qa): PR892 user-story QA campaign — full retest record (175/175 …
lklimek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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
31 changes: 31 additions & 0 deletions
31
docs/ai-design/2026-07-14-migration-password-prompt/design.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Storage Update Password Prompt | ||
|
|
||
| ## Decision | ||
|
|
||
| Older wallet data is copied into the current stores during startup. The event is called a **storage update** in every user-facing surface. The previous SQLite database remains a recovery artifact and is opened read-only. | ||
|
|
||
| ## UI and backend handshake | ||
|
|
||
| The backend copies wallet envelopes and metadata, hydrates the wallets, and registers wallets whose seeds are already available. If protected wallets remain locked, it publishes `MigrationState::AwaitingWalletPasswords` with their seed hashes and waits on `MigrationStatus`'s notification. | ||
|
|
||
| The egui frame loop owns the human interaction. It selects one hash, renders a non-dismissible wallet-specific password prompt, and either unlocks the wallet or records a skip. A successful seed promotion or a skip notifies the backend. A failed promotion remains a typed `TaskError`, closes the in-memory wallet again, and does not notify the backend, so the update cannot report success without the seed landing in the current vault. | ||
|
|
||
| Complete update runs are serialized on `AppContext`. A shared MCP request therefore joins a desktop run instead of creating a second waiter on the password notification. | ||
|
|
||
| Modal state is keyed by wallet seed hash rather than window title. Closing the prompt or switching hashes clears the typed buffer before removing its egui cache entry. | ||
|
|
||
| ## Interactive capability and headless behavior | ||
|
|
||
| `AppContext` starts with `NullSecretPrompt`, whose `SecretPrompt::is_interactive()` capability is false. The desktop boot path installs `EguiSecretPromptHost` before backend construction; standalone MCP and CLI construction do not install it. | ||
|
|
||
| When protected wallets require input, the backend checks this explicit host capability before publishing an awaiting state. Without it, the update immediately returns `MigrationError::InteractivePromptUnavailable`, wrapped by the dedicated actionable `TaskError`. No timeout, environment variable, or inferred delay can turn a headless caller into an interactive one. | ||
|
|
||
| ## Previous database invariant | ||
|
|
||
| Desktop and standalone boot open every existing `data.db` with SQLite's `SQLITE_OPEN_READ_ONLY` flag and do not run the historical schema ladder against it. Only an absent, fresh compatibility database may be created and initialized. Every production migration and protected-key reader also opens the source read-only. Migration code contains no drop, delete, or update path for legacy tables. Idempotency uses per-network completion sentinels in `det-app.sqlite`; it never uses table absence. | ||
|
|
||
| The current vault may contain both the copied recovery envelope and its current raw or password-protected form. Reads prefer the current form, while the recovery envelope remains available. Tests snapshot `data.db` before a complete two-wallet run, unlock one wallet, skip the other, and require byte-for-byte equality afterward. | ||
|
|
||
| ## Registration concurrency | ||
|
|
||
| Upstream wallet registration is single-flight per wallet seed hash. Concurrent callers share a keyed one-shot outcome cell, so one leader reaches upstream and every follower receives the same success or typed error. Completed flights are removed so a later, non-concurrent user retry can try again. Different wallets can register concurrently. |
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOW —
SEC-004is a transient review finding ID. Repository policy keeps ephemeral audit IDs out of committed specifications because they lose meaning outside the originating review artifact. Please remove it or replace it with a durable requirement, issue, or design-document reference.🤖 Co-authored by Claudius the Magnificent AI Agent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verified: confirmed present at docs/user-stories.md:1361 ("...every prompt action (SEC-004)"), a bare transient review-ID reference with no resolvable context in a durable spec doc. Easy fix — tracked, not resolving yet.