Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
403 commits
Select commit Hold shift + click to select a range
33d18ac
test(platform-wallet-storage): adversarial recheck of #4113 union/con…
lklimek Jul 13, 2026
7b56929
fix(platform-wallet-storage): reject conflicting keys at one node-key…
lklimek Jul 13, 2026
ad0164c
docs: design for asset-lock proof blob rehydration fix (#4133)
lklimek Jul 15, 2026
8f9c5f7
fix(platform-wallet-storage): tighten secrets/ error diagnostics & lo…
lklimek Jul 15, 2026
59f65e7
fix(platform-wallet-storage): log SqlitePersister open() and delete d…
lklimek Jul 15, 2026
081d055
fix(platform-wallet): retry transient persister failures in register_…
lklimek Jul 15, 2026
f7ab81f
fix(platform-wallet-storage): surface provider node keys and guard xp…
lklimek Jul 15, 2026
38ea7c9
fix(platform-wallet-storage): close error-handling gaps in sqlite sch…
lklimek Jul 15, 2026
da92ee9
docs(platform-wallet): make store()'s transient-failure retry contrac…
lklimek Jul 15, 2026
8417dc8
fix(platform-wallet-storage): rehydrate asset-lock proof blobs via wi…
lklimek Jul 15, 2026
ae01482
fix(platform-wallet): release wallet-event adapter on failed load; ty…
lklimek Jul 15, 2026
bdc7bf5
fix(platform-wallet-storage): route third from_script site through Ad…
lklimek Jul 15, 2026
95742a0
test(platform-wallet-storage): fully-populate both proof variants; dr…
lklimek Jul 15, 2026
66cea08
revert(platform-wallet-storage): drop the V004 migration — no pre-rel…
lklimek Jul 15, 2026
2878bd5
docs(dpp): pin the internally-tagged serde/bincode hazard at its defi…
lklimek Jul 15, 2026
40c08c5
merge: fold in secrets/ error-handling-coverage fixes (PR #3968)
lklimek Jul 15, 2026
fde795b
merge: fold in sqlite/schema/ error-handling-coverage fixes (PR #3968)
lklimek Jul 15, 2026
ee2b5d7
merge: fold in persister/orchestration-layer error-handling-coverage …
lklimek Jul 15, 2026
d210cae
Merge branch 'feat/platform-wallet-storage-rehydration' of https://gi…
lklimek Jul 15, 2026
d18020f
test(platform-wallet,dpp): QA-002/003/004 — honest Drop-release seman…
lklimek Jul 15, 2026
c992523
Merge remote-tracking branch 'origin/v4.1-dev' into feat/platform-wal…
lklimek Jul 15, 2026
a111e37
fix(platform-wallet-storage): resolve v4.1-dev merge fallout
lklimek Jul 15, 2026
1ce14ec
fix(platform-wallet-storage): resolve v4.1-dev merge fallout (content)
lklimek Jul 15, 2026
884a6cd
Merge remote-tracking branch 'origin/feat/platform-wallet-storage-reh…
lklimek Jul 15, 2026
77278e7
fix(platform-wallet-storage): lift provider node keys onto the persis…
lklimek Jul 15, 2026
fd26d4e
test(platform-wallet-storage): regenerate V001 fixture, fix remaining…
lklimek Jul 15, 2026
3f2092c
fix(platform-wallet-storage): fail loud on unread FFI provider node keys
lklimek Jul 15, 2026
b7f3af9
Merge remote-tracking branch 'origin/feat/platform-wallet-storage-reh…
lklimek Jul 15, 2026
7956bb8
style(platform-wallet-storage): fix rustfmt violation in sqlite_versi…
lklimek Jul 15, 2026
b361e11
fix(platform-wallet-storage): persist typed public keys on core addre…
lklimek Jul 15, 2026
a536a26
chore(platform-wallet): rustfmt reflow of changeset re-export list
lklimek Jul 15, 2026
769deaf
docs(qa): mark qa-review-4113.md superseded by the #4127 pivot
lklimek Jul 15, 2026
83a28f7
fix(platform-wallet-storage): reject conflicting typed pool-key writes
lklimek Jul 15, 2026
3c26fc1
refactor(platform-wallet): share platform-node pool-insert logic
lklimek Jul 15, 2026
42da594
fix(platform-wallet-storage): reject untyped/malformed typed pool-key…
lklimek Jul 20, 2026
04c71e2
fix(platform-wallet): restore used platform-node pool bookkeeping on …
lklimek Jul 20, 2026
25e50bb
Merge branch 'v4.1-dev' into feat/platform-wallet-storage-rehydration
lklimek Jul 21, 2026
91cd3e3
fix(platform-wallet-storage): persist provider key accounts and platf…
Claudius-Maginificent Jul 21, 2026
8eacd6b
merge: forward-port outstanding PR #4117 review-feedback fixes onto P…
claude Jul 21, 2026
1980a10
build(deps): pin rust-dashcore to the dash-evo-tool integration branch
claude Jul 21, 2026
c01f74f
fix(wallet): migrate address pool state bookkeeping
lklimek Jul 21, 2026
69b4803
fix(wallet): reserve platform receive addresses
lklimek Jul 21, 2026
f376d32
merge: reconcile with origin/feat/platform-wallet-storage-rehydration…
claude Jul 21, 2026
1ce7be0
Merge remote-tracking branch 'origin/v4.1-dev' into merge-base/3968-v…
lklimek Jul 21, 2026
be76265
build(deps): refresh lockfile for rust-dashcore pin
lklimek Jul 21, 2026
fabcbf0
style(wallet): format merge resolutions
lklimek Jul 21, 2026
267599d
fix(wallet-storage): remove stale merge import
lklimek Jul 21, 2026
1662b3a
test(wallet): migrate payment checks to address state
lklimek Jul 21, 2026
6304208
fix(platform-wallet-storage): persist AddressState::Reserved timestamp
lklimek Jul 21, 2026
fe71552
fix(platform-wallet): retry transient startup load, fix stale used-bo…
lklimek Jul 21, 2026
a864315
fix(platform-wallet-ffi): dedicated transient/fatal codes for persist…
lklimek Jul 21, 2026
9fcee37
fix(platform-wallet-storage): parent-dir permission gate, shared id32…
lklimek Jul 21, 2026
2c9996a
Merge branch 'fix/3968-wallet-review-findings' into fix/3968-storage-…
lklimek Jul 21, 2026
154b696
Merge branch 'fix/3968-ffi-review-findings' into fix/3968-storage-rev…
lklimek Jul 21, 2026
904e549
Merge remote-tracking branch 'origin/v4.1-dev' into fix/3968-storage-…
lklimek Jul 21, 2026
ebbd15c
Merge remote-tracking branch 'origin/v4.1-dev' into fix/3968-storage-…
lklimek Jul 22, 2026
40fedf1
fix(platform-wallet-storage): gate identity BLOB columns before mater…
lklimek Jul 22, 2026
74d4fee
docs(platform-wallet-storage): disclose vault-header corruption ambig…
lklimek Jul 22, 2026
ed74114
fix(platform-wallet-storage): make connection-mutex poisoning permane…
lklimek Jul 22, 2026
032f791
test(platform-wallet-storage): exercise account-zero fallback through…
lklimek Jul 22, 2026
9d7cfea
refactor(platform-wallet-storage): drop dead core_utxos.account_index…
lklimek Jul 22, 2026
2830822
docs(platform-wallet-storage): fix stale capability rationale, disclo…
lklimek Jul 22, 2026
5e20040
fix(platform-wallet-storage): require minimum passphrase length
lklimek Jul 22, 2026
0cc257f
docs(platform-wallet-storage): clarify floor-target and passphrase-gu…
lklimek Jul 22, 2026
cb0f647
docs(platform-wallet-storage): resolve V001-mutability contradiction …
lklimek Jul 22, 2026
c19a4db
fix(platform-wallet-storage): correct CLI exit-code classification
lklimek Jul 22, 2026
e4bbd96
docs(platform-wallet-storage): strip ephemeral review-finding IDs fro…
lklimek Jul 22, 2026
9964031
fix(platform-wallet-storage): exclude plain readers during restore, h…
lklimek Jul 22, 2026
63e160b
feat(platform-wallet-storage): persist shielded viewing keys natively
lklimek Jul 22, 2026
e75f259
feat(platform-wallet): add delete_wallet to PlatformWalletPersistence…
lklimek Jul 22, 2026
be89caa
chore(deps): bump rust-dashcore pin to dash-evo-tool branch head (18c…
lklimek Jul 23, 2026
4a1ba64
Merge remote-tracking branch 'origin/v4.1-dev' into merge/v4.1-dev-in…
lklimek Jul 23, 2026
e9c9b74
fix(platform): reconcile confirmed UTXO height after wallet restart (…
Claudius-Maginificent Jul 24, 2026
3bd0cc5
Merge remote-tracking branch 'origin/v4.1-dev' into feat/platform-wal…
lklimek Jul 24, 2026
0e644e8
Merge branch 'feat/platform-wallet-storage-rehydration' of https://gi…
lklimek Jul 24, 2026
288a6ca
Merge remote-tracking branch 'origin/v4.1-dev' into feat/platform-wal…
lklimek Jul 24, 2026
3636aff
Merge remote-tracking branch 'origin/v4.1-dev' into feat/platform-wal…
lklimek Jul 27, 2026
0ed8b4d
Merge remote-tracking branch 'origin/v4.2-dev' into feat/platform-wal…
lklimek Jul 28, 2026
debf67b
Merge remote-tracking branch 'origin/v4.2-dev' into feat/platform-wal…
lklimek Jul 28, 2026
4ca05f5
chore(deps): update rust-dashcore dash-evo-tool branch
lklimek Jul 30, 2026
a15b680
fix(platform-wallet): thread AssetLockFundingAccount/drain into build…
lklimek Jul 30, 2026
a18bd15
test(platform-wallet): scope broadcaster mutex guard to satisfy clipp…
lklimek Jul 30, 2026
762c66c
fix(platform-wallet-storage): stop one bad script row from bricking a…
lklimek Jul 31, 2026
65bdbb1
fix(platform-wallet-storage): park duplicate-index identities instead…
lklimek Jul 31, 2026
d78c4bd
docs(platform-wallet): document the parked-identity exception to the …
lklimek Jul 31, 2026
3cab9f5
Revert "docs(platform-wallet): document the parked-identity exception…
lklimek Jul 31, 2026
a402a88
Revert "fix(platform-wallet-storage): park duplicate-index identities…
lklimek Jul 31, 2026
6cb7f97
Revert "fix(platform-wallet-storage): stop one bad script row from br…
lklimek Jul 31, 2026
eec7c4d
fix(platform-wallet): derive spent UTXO scripts from the input's address
lklimek Jul 31, 2026
8c5ca08
fix(platform-wallet-storage): name auto-backups after their source da…
lklimek Jul 31, 2026
4b92230
fix(platform-wallet-storage): enforce key/identity co-ownership at th…
lklimek Jul 31, 2026
ae42330
fix(platform-wallet-storage): narrow identity_keys key to (identity_i…
lklimek Aug 1, 2026
0b5e2e1
feat(platform-wallet-storage): allow NULL identity_keys.wallet_id, gu…
lklimek Aug 1, 2026
3eb021a
feat(platform-wallet-storage): add load_unowned_identities accessor
lklimek Aug 1, 2026
c33807b
test(platform-wallet-storage): pin the unowned-scope guards nothing held
lklimek Aug 1, 2026
5931df7
chore(deps): update rust-dashcore dash-evo-tool branch
lklimek Aug 1, 2026
9d0dd5a
Merge remote-tracking branch 'origin/v4.2-dev' into feat/platform-wal…
lklimek Aug 20, 2026
026b1cb
chore(platform-wallet-storage): drop changes outside the storage crate
lklimek Aug 20, 2026
c5ff761
fix(platform-wallet): make the Drop-backstop wait valid on a multi-th…
lklimek Aug 20, 2026
69d21e3
test(platform-wallet): assert synchronous persister release on the gr…
lklimek Aug 20, 2026
69ed03b
revert(platform-wallet): stop reserving in next_unused_receive_address
lklimek Aug 20, 2026
125aff1
feat(platform-wallet-storage): add LoadPolicy, LoadCtx, and recovery-…
lklimek Aug 20, 2026
16a93e3
feat(platform-wallet-storage): make a recovery-mode persister read-only
lklimek Aug 20, 2026
9160fc4
refactor(platform-wallet-storage): thread &LoadCtx through the load r…
lklimek Aug 20, 2026
a5f054c
feat(platform-wallet-storage): fail closed on chain-lock and core-tx …
lklimek Aug 20, 2026
6bc2c64
feat(platform-wallet-storage): fail closed on an undecodable shielded…
lklimek Aug 20, 2026
7645953
feat(platform-wallet-storage): fail closed on orphaned identity rows
lklimek Aug 20, 2026
0296a7b
feat(platform-wallet-storage): fail closed on rehydration derivation …
lklimek Aug 20, 2026
386d1bb
feat(platform-wallet-storage): count the two ambiguous sites and prob…
lklimek Aug 20, 2026
3690837
docs(platform-wallet-storage): document the load policy across rustdo…
lklimek Aug 20, 2026
278b5c3
fix(platform-wallet-storage): stop inventing a derivation index for t…
lklimek Aug 20, 2026
d2e90d3
docs(platform-wallet-storage): state the load contract once, where it…
lklimek Aug 20, 2026
984007a
docs(platform-wallet-storage): mark the gap-limit derivation site as …
lklimek Aug 20, 2026
7fff2d3
fix(platform-wallet-storage): cap the implied work of a rehydration g…
lklimek Aug 20, 2026
06a1408
docs(platform-wallet-storage): reunite the address-reuse regression t…
lklimek Aug 20, 2026
92f6f04
refactor(platform-wallet-storage): split the stringly-typed rehydrati…
lklimek Aug 20, 2026
90df897
fix(platform-wallet-storage): put the remedy in the message the user …
lklimek Aug 20, 2026
1f411d9
fix(platform-wallet-storage): count tombstoned orphan rows one per row
lklimek Aug 20, 2026
c1fde0c
fix(platform-wallet-storage): make a tolerated site one joinable log …
lklimek Aug 20, 2026
8f18e94
fix(platform-wallet-storage): make one incident greppable under one name
lklimek Aug 20, 2026
c73f44d
refactor(platform-wallet-storage): give LoadDegradation's invariants …
lklimek Aug 20, 2026
a9ef3b6
refactor(platform-wallet-storage): stop exporting a type no caller ca…
lklimek Aug 20, 2026
a416a86
test(platform-wallet-storage): pin the unimplemented-table probe to t…
lklimek Aug 20, 2026
743b7ca
docs(platform-wallet-storage): say that a point read's tally is dropped
lklimek Aug 20, 2026
b4b540a
docs(platform-wallet-storage): mark the two unseedable sites NOTE, no…
lklimek Aug 20, 2026
1958a27
fix(platform-wallet-storage): cost an empty address pool as empty
lklimek Aug 20, 2026
f3ac199
fix(platform-wallet-storage): count every address a degraded site aff…
lklimek Aug 20, 2026
6bf10b8
test(platform-wallet-storage): pin the three snapshot promises nothin…
lklimek Aug 20, 2026
72395da
fix(platform-wallet-storage): reject duplicate (wallet_id, identity_i…
Claudius-Maginificent Aug 21, 2026
993584a
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Aug 21, 2026
05f6616
fix(platform-wallet-storage): let a store() own the flush of its own …
lklimek Aug 21, 2026
616963e
fix(platform-wallet-storage): keep pending writes when a delete abort…
lklimek Aug 21, 2026
7031fae
fix(platform-wallet-storage): judge identity slots on the state a cha…
lklimek Aug 21, 2026
2148788
docs(platform-wallet-storage): document that store_flush_seam is not …
lklimek Aug 21, 2026
86b4dd1
Merge remote-tracking branch 'origin/feat/platform-wallet-storage-reh…
lklimek Aug 21, 2026
17c022a
fix(platform-wallet-storage): purge legacy empty-script spent UTXO rows
lklimek Aug 21, 2026
4784de0
docs(platform-wallet): correct the derive_spent_utxos field notes
lklimek Aug 21, 2026
c86d237
Merge remote-tracking branch 'origin/v4.2-dev' into feat/platform-wal…
lklimek Aug 25, 2026
53c3d2d
fix(platform-wallet): keep the shielded changeset slot in every featu…
lklimek Aug 25, 2026
378d45a
fix(platform-wallet): surface unclean worker shutdown on rehydration …
lklimek Aug 25, 2026
4f0fd09
fix(platform-wallet-storage): drop the stale wallet_meta module decla…
lklimek Aug 25, 2026
cfc5c10
fix(platform-wallet): use dash-spv's own acceptance timeout instead o…
lklimek Aug 25, 2026
4dbf38f
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Aug 25, 2026
396977b
Merge branch 'fix/platform-wallet-broadcast-acceptance-timeout' into …
lklimek Aug 25, 2026
92f9681
fix(platform-wallet-storage): resolve two silent regressions from the…
lklimek Aug 26, 2026
aaab997
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Aug 27, 2026
e250391
fix(platform-wallet-storage): close six read-path and verification ga…
lklimek Aug 27, 2026
a844aec
docs(platform-wallet-storage): correct the duplicate-slot load claim
lklimek Aug 27, 2026
1fc9b11
refactor(platform-wallet-storage)!: delete removed identities instead…
lklimek Aug 27, 2026
21484ce
Merge branch 'feat/platform-wallet-storage-rehydration' into chore/pw…
lklimek Aug 27, 2026
3f40708
fix(platform-wallet-storage): stop secret drop aborting on a shared l…
lklimek Aug 31, 2026
082f203
fix(platform-wallet-storage)!: give every secret its own guarded page…
lklimek Aug 31, 2026
62ee946
fix(platform-wallet-storage)!: close the memsec rework's review findings
lklimek Aug 31, 2026
67d4ef3
feat(platform-wallet-storage): let SecretString be edited in place
lklimek Aug 31, 2026
4a51102
Merge remote-tracking branch 'origin/v4.2-dev' into feat/platform-wal…
lklimek Sep 1, 2026
707ade4
fix(platform-wallet): move Drop impl above the test module
lklimek Sep 1, 2026
5ed3c58
fix(platform-wallet): retry a transient identity-scan verdict persist
lklimek Sep 1, 2026
8c141ba
fix(platform-wallet-storage): clear four clippy denials in test code
lklimek Sep 1, 2026
1931a76
feat(platform-wallet-storage): persist and restore the identity-scan …
lklimek Sep 1, 2026
a88b949
docs(rs-platform-wallet-ffi): fix non-ancestor merge SHAs in error-co…
lklimek Sep 1, 2026
6bc43a8
docs(rs-platform-wallet-storage): reconcile SecretStoreError enumerat…
lklimek Sep 1, 2026
7e1c9c4
docs(rs-platform-wallet-storage): fix identity_keys PK/FK/nullability…
lklimek Sep 1, 2026
3a4e2c9
docs(rs-platform-wallet-storage): reconcile SCHEMA.md gap disclaimer,…
lklimek Sep 1, 2026
0d88d9c
docs(rs-platform-wallet-storage): rename secret-serde to serde in SEC…
lklimek Sep 1, 2026
aa3b7fb
fix(platform-wallet-storage): refuse a host whose pages blow the lock…
lklimek Sep 1, 2026
3df58dd
refactor(platform-wallet-storage)!: drop three redundant Cargo features
lklimek Sep 1, 2026
135ebad
fix(platform-wallet): derive the shield-capacity regression fixture f…
lklimek Sep 1, 2026
efab0da
fix(platform-wallet-storage): raise the assumed page size to 16 KiB a…
lklimek Sep 1, 2026
68cb256
docs(rs-platform-wallet-storage): restate the locked-memory budget at…
lklimek Sep 1, 2026
b51cddc
chore(platform-wallet-storage): trim PR to storage-crate-only scope
lklimek Sep 2, 2026
c34e707
chore(platform-wallet-storage): drop asset-lock size gate, now its ow…
lklimek Sep 2, 2026
ec90c66
Merge the trimmed 'feat/platform-wallet-storage-rehydration' into cho…
lklimek Sep 2, 2026
8fc62e0
docs(platform-wallet-storage): correct SCHEMA/SECRETS/README against …
lklimek Sep 3, 2026
1479d14
refactor(platform-wallet)!: drop delete_wallet from the persistence t…
lklimek Sep 3, 2026
ef32f6f
fix(platform-wallet-storage)!: rename retired Domain labels with a V0…
lklimek Sep 3, 2026
b9901bb
docs(platform-wallet-storage): state the database trust model and dro…
lklimek Sep 3, 2026
31eb272
Merge branch 'fix/3968-domain-label-rename' into chore/3968-integrate
lklimek Sep 3, 2026
e8df5ba
Merge branch 'docs/3968-schema-doc-accuracy' into chore/3968-integrate
lklimek Sep 3, 2026
d338055
fix(platform-wallet-storage): reject foreign-owned vaults and make se…
lklimek Sep 3, 2026
6ad7104
docs(platform-wallet-storage): fix the manifest feature wiring and st…
lklimek Sep 3, 2026
2b36843
fix(platform-wallet-storage): stop URI filename smuggling and harden …
lklimek Sep 3, 2026
07b1c1a
Merge branch 'fix/3968-secrets-hygiene' into chore/3968-integrate
lklimek Sep 3, 2026
3e75327
Merge branch 'fix/3968-misc-hygiene' into chore/3968-integrate
lklimek Sep 3, 2026
8c838bd
Merge branch 'docs/3968-schema-doc-accuracy' into chore/3968-integrate
lklimek Sep 3, 2026
201eaf3
fix(platform-wallet-storage): separate the fused load sites and stop …
lklimek Sep 3, 2026
dd60d32
Merge branch 'fix/3968-load-policy-cluster' into chore/3968-integrate
lklimek Sep 3, 2026
e280ffa
fix(platform-wallet-storage): tolerate an undecodable provider-pool s…
lklimek Sep 3, 2026
add5926
Merge branch 'fix/3968-load-policy-cluster' into feat/platform-wallet…
lklimek Sep 3, 2026
771a9e5
docs(platform-wallet-storage): correct apply_persisted_core_state cha…
lklimek Sep 4, 2026
cab6960
test(platform-wallet-storage): cover LoadSite::RehydrationMaintainGap…
lklimek Sep 4, 2026
36dc213
refactor(platform-wallet-storage): move rehydration engine out of util
lklimek Sep 4, 2026
2969cf7
refactor(platform-wallet-storage): wire up sqlite::rehydrate module
lklimek Sep 4, 2026
90a232d
fix(platform-wallet-storage): expose LoadSite explanations and render…
lklimek Sep 4, 2026
7e2698a
fix(platform-wallet-storage): wipe the Argon2 block matrix instead of…
lklimek Sep 4, 2026
bde4ce1
fix(platform-wallet-storage): pin the Tier-2 read ceiling to wire-sta…
lklimek Sep 4, 2026
0c52823
fix(platform-wallet-storage): stop rekey silently downgrading a harde…
lklimek Sep 4, 2026
e92b951
style(platform-wallet-storage): rustfmt the rekey header-ratchet test
lklimek Sep 4, 2026
122f167
fix(platform-wallet-storage): zeroize scheme-0 plaintext on every fai…
lklimek Sep 4, 2026
144a962
fix(platform-wallet-storage): close the write-path gaps that make a w…
lklimek Sep 4, 2026
7c5837e
merge: expose LoadSite explanations and render the CLI's full error c…
lklimek Sep 4, 2026
a6fb87c
merge: close the write-path gaps that make a wallet file un-loadable
lklimek Sep 4, 2026
84b20ff
merge: correct the chainlock rustdoc, cover the gap-limit site, move …
lklimek Sep 4, 2026
acf4c77
merge: wipe the Argon2 matrix, decouple the read ceiling, stop rekey …
lklimek Sep 4, 2026
35516cb
style(platform-wallet-storage): drop ephemeral review-finding IDs fro…
lklimek Sep 4, 2026
f7d7874
merge: bring feat/platform-wallet-storage-rehydration up to date with…
lklimek Sep 4, 2026
a32f408
fix(platform-wallet-storage): guard rehydration gap-limit input and e…
lklimek Sep 4, 2026
155a017
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Sep 4, 2026
8b635ac
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Sep 7, 2026
25fa274
Merge remote-tracking branch 'origin/v4.2-dev' into feat/platform-wal…
lklimek Sep 7, 2026
eafcff3
fix(platform-wallet-storage): stop reusing published migration versions
lklimek Sep 7, 2026
b3bba39
fix(platform-wallet-storage): restore published migrations and append…
lklimek Sep 7, 2026
ed1d93e
fix(platform-wallet-storage): admit the pre-split standard label inst…
lklimek Sep 7, 2026
894ac00
test(platform-wallet-storage): pin that a legacy standard row is not …
lklimek Sep 7, 2026
68bc412
fix(platform-wallet-storage): reconcile the pre-split standard row in…
lklimek Sep 7, 2026
9b32f1c
docs(platform-wallet-storage): state the reconciliation's real cost p…
lklimek Sep 7, 2026
28837e3
fix(platform-wallet-storage): isolate a failed wallet from the rest o…
lklimek Sep 7, 2026
9992476
fix(platform-wallet-storage): put the identity-key and contact reader…
lklimek Sep 7, 2026
33fb59c
fix(platform-wallet-storage): count the tables load() abandons instea…
lklimek Sep 7, 2026
095cf6d
fix(platform-wallet-storage): degrade balance-bearing rows by wallet,…
lklimek Sep 7, 2026
27cc030
fix(platform-wallet-storage): re-arm the compile-time guard on the ac…
lklimek Sep 7, 2026
c9c40d3
docs(platform-wallet-storage): name the subsystem and the constants t…
lklimek Sep 7, 2026
2cf9b46
test(platform-wallet-storage): name the colliding keys instead of dum…
lklimek Sep 7, 2026
23399c3
fix(platform-wallet-storage): restore InstantSend locks at load inste…
lklimek Sep 7, 2026
ef89a2b
refactor(platform-wallet-storage): make the public surface match what…
lklimek Sep 7, 2026
08252d1
fix(platform-wallet-storage): close four at-rest and open-path gaps i…
lklimek Sep 7, 2026
dbb8583
test(platform-wallet-storage): drop test-case IDs whose document the …
lklimek Sep 7, 2026
4e3a774
Merge fix/3968-round5 (2cf9b46773) into fix/3968-round5-wave3
lklimek Sep 7, 2026
5ec4761
Merge fix/3968-round5-wave3 into fix/3968-round5
lklimek Sep 7, 2026
41a2b2b
fix(platform-wallet-storage): make the secure-delete guard check the …
lklimek Sep 7, 2026
a3722d8
Merge wave 3's secure-delete guard fix into fix/3968-round5
lklimek Sep 7, 2026
64f763c
chore(ci): mark the dependency-audit gate as unreachable from pull re…
lklimek Sep 7, 2026
c887ef7
chore(platform-wallet-storage): merge v4.2-dev into rehydration branch
lklimek Sep 8, 2026
5690a07
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Sep 8, 2026
84d5335
test(platform-wallet-storage): make lock refusal coverage deterministic
lklimek Sep 8, 2026
a1efa24
test(platform-wallet): move platform-node pool entry tests to a follo…
lklimek Sep 8, 2026
4af855d
fix(wallet-storage): preserve legacy state during atomic migrations
lklimek Sep 8, 2026
c3cb94c
chore: merge latest PR branch into migration fixes
lklimek Sep 8, 2026
c01d229
refactor(wallet-storage): own provider rehydration helpers
lklimek Sep 8, 2026
459e062
Merge branch 'v4.2-dev' into feat/platform-wallet-storage-rehydration
lklimek Sep 9, 2026
8fab915
chore: cargo fmt
lklimek Sep 9, 2026
ec1e26f
fix(platform-wallet): align disabled shielded changeset traits
lklimek Sep 9, 2026
827d759
fix(platform-wallet-storage): reject unknown pool account labels
lklimek Sep 9, 2026
ee41927
refactor(platform-wallet-storage): use Zeroizing for Argon2 memory
lklimek Sep 9, 2026
31c8f94
chore(platform-wallet-storage): merge v4.2-dev persistence updates
lklimek Sep 9, 2026
2deb2d4
chore(platform-wallet-storage): reconcile hard delete with updated st…
lklimek Sep 9, 2026
7869aa3
chore(platform-wallet-storage): merge latest typed persistence base i…
lklimek Sep 9, 2026
2ff29d1
Merge v4.2-dev after squash merge of #3968
lklimek Sep 9, 2026
be4f6c6
test(platform-wallet-storage): retain identity test rename after squa…
lklimek Sep 9, 2026
e8904f8
fix(platform-wallet-storage): preserve identity lifecycle boundaries
lklimek Sep 9, 2026
9756bae
test(platform-wallet-storage): cover pragma-independent identity cleanup
lklimek Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions packages/rs-platform-wallet-storage/SCHEMA.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Schema evolution is version-gated by refinery. Every read-write connection turns
- **metadata-version rows** (`meta_data_versions`) carry a `wallet_id` column and are cleaned directly by `cascade_meta_data_versions_on_wallet_delete`.
- **identity-scoped meta** (`meta_identity`, `meta_token`) carries no `wallet_id` — only `identity_id` (+ `token_id`). It is cleaned by `cascade_meta_on_identity_delete` (AFTER DELETE ON `identities`), which fires for the wallet's own identities when the FK cascade removes them on a wallet delete.

Deleting an `identities` row — on its own, or cascaded from a wallet delete — additionally fires `cascade_children_on_identity_delete` (V018), which brooms `identity_keys`, `contacts`, `ignored_senders`, and `pending_contact_crypto` by the deleted `identity_id`. That trigger exists because no live foreign key reaches those rows in every case: `identity_keys`' FK to `identities` is compound (`wallet_id, identity_id`), and SQLite's default MATCH SIMPLE skips FK enforcement entirely once ANY column of the child key is NULL, leaving it dormant for an out-of-wallet identity; `contacts` and `ignored_senders` use `owner_id`, while `pending_contact_crypto` uses `owner_identity_id`, with no FK to `identities`. Keying the broom on the identity id alone covers the wallet-owned case too, as an idempotent overlap with the live cascade.

Manual flushes preserve removal/re-addition boundaries as ordered segments inside one transaction. Removal sweeps the previous incarnation before the later segment recreates the identity and its new children; mixed child writes in the removal's own segment are swept with it.

### Orphan metadata and future garbage collection

Any `meta_*` row whose parent object does not exist — because it was never created, or because it was removed via a path the cascade does not cover — may persist indefinitely. This is an accepted limitation that applies to all metadata types and scopes. Examples:
Expand Down Expand Up @@ -128,7 +132,6 @@ erDiagram
BLOB wallet_id FK "NULL = orphan identity (no parent wallet yet)"
INTEGER identity_index "BIP-32 index; NULL for out-of-wallet identities"
BLOB entry_blob "bincode-encoded IdentityEntry"
INTEGER tombstoned "0 | 1 (logical delete)"
}

IDENTITY_KEYS {
Expand Down Expand Up @@ -357,6 +360,8 @@ SQL lookups without blob decoding.

### `pending_contact_crypto`

- Identity cleanup: `cascade_children_on_identity_delete` deletes rows by `owner_identity_id`, using `idx_pending_contact_crypto_owner(owner_identity_id)`.

Deferred, signer-dependent contact cryptography operations. The owner,
contact, and operation kind form the deduplication key; `payload` carries the
public-only ciphertext and key-index data needed when a signer becomes
Expand Down Expand Up @@ -468,8 +473,18 @@ matching upstream's "no-op until a chainlock has been applied".

Platform identities, wallet-parented or orphan. `wallet_id` is nullable:
NULL means the identity was written before a parent wallet was registered
(orphan-to-parented promotion via COALESCE on upsert). `tombstoned = 1`
marks a logical delete; the row is retained for cascade integrity.
(orphan-to-parented promotion via COALESCE on upsert).

Removal (`IdentityChangeSet.removed`) is a physical `DELETE`, scoped to
the flush wallet, and it is terminal: every dependent row goes with it
(see [How integrity is kept](#how-integrity-is-kept)), so re-adding the
same `identity_id` later starts from a blank identity rather than
inheriting the removed one's keys, contacts, or balances. The writer runs
in two halves for this reason — `apply_upserts` sits with the other
identity writers, `apply_removals` runs last in the transaction, after
every identity-scoped child writer, so a changeset carrying both an
upsert and a removal for one identity commits instead of pulling the FK
parent out from under its own child inserts.

- PK: `identity_id`.
- FK: `wallet_id → wallets(wallet_id) ON DELETE CASCADE` (nullable).
Expand Down Expand Up @@ -508,6 +523,7 @@ trigger; an applied migration is never edited.
- PK: `(identity_id, key_id)`.
- FK: `wallet_id → wallets(wallet_id) ON DELETE CASCADE` (nullable; belt-and-braces — already implied by the compound FK below).
- FK: `(wallet_id, identity_id) → identities(wallet_id, identity_id) ON DELETE CASCADE` (compound; a key may only be filed under the wallet that owns its identity).
- Trigger cleanup: `cascade_children_on_identity_delete` brooms by `identity_id`, closing the dormant case.
- Index: `idx_identity_keys_wallet_identity(wallet_id, identity_id)`.

### `contacts`
Expand All @@ -527,6 +543,8 @@ cleared on a superseding rotation.

- PK: `(wallet_id, owner_id, contact_id)`.
- FK: `wallet_id → wallets(wallet_id) ON DELETE CASCADE`.
- Trigger cleanup: `cascade_children_on_identity_delete` brooms by `owner_id` — there is no FK to `identities`.
- Index: `idx_contacts_owner(owner_id)`, the broom's access path (`owner_id` is not the leading PK column).
- `state` CHECK: sourced from `sqlite::schema::contacts::CONTACT_STATE_LABELS`.

### `ignored_senders`
Expand All @@ -537,6 +555,8 @@ deleted; `ignored_at` records when the mute was applied.

- PK: `(wallet_id, owner_id, sender_id)`.
- FK: `wallet_id → wallets(wallet_id) ON DELETE CASCADE`.
- Trigger cleanup: `cascade_children_on_identity_delete` brooms by `owner_id` — there is no FK to `identities`.
- Index: `idx_ignored_senders_owner(owner_id)`, the broom's access path.
- No enum-domain CHECK column.

### `platform_addresses`
Expand Down Expand Up @@ -826,3 +846,4 @@ table-rebuild migration, as V004 does.
| V015 | `V015__purge_legacy_empty_script_spent_utxos.rs` | Deletes legacy `core_utxos` rows matching `spent = 1 AND length(script) = 0 AND is_sweep_placeholder = 0`, left by a producer that fabricated an empty script for a spend of an output the wallet never recorded. One such row rejects the load of the whole file, since `load_used_addresses` decodes every stored script with no load-policy escape hatch. Balance-neutral: the balance readers select `spent = 0` only. |
| V016 | `V016__identity_keys_null_scope_requires_existing_identity.rs` | Recreates the `identity_keys` null-scope trigger pair (see Triggers above) to also reject a NULL-scoped key naming an identity that does not exist at all, closing the gap where V008's guard caught only the wallet-owned case. |
| V017 | `V017__identity_scan_state.rs` | Adds `identity_scan_states` (one row per wallet: the last gap-limit identity-scan verdict — `complete`, `probed_from`/`probed_through`, `unlocated_gap`) and `identity_scan_failed_indices` (indices probed without an answer, cascading from the verdict row via `wallet_id`). Purely additive; an upgraded database reads back "no verdict recorded" for every wallet until the next scan (dashpay/platform#4365). |
| V018 | `V018__identity_hard_delete.rs` | Retires identity tombstoning. Adds `cascade_children_on_identity_delete` (brooms `identity_keys` / `contacts` / `ignored_senders` / `pending_contact_crypto` by the deleted identity id, covering the rows no live FK reaches) plus its access-path indexes `idx_contacts_owner`, `idx_ignored_senders_owner`, and `idx_pending_contact_crypto_owner`; purges every already-tombstoned identity and its dependents; drops `identities.tombstoned`. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//! Retire identity tombstoning: a removed identity is deleted outright.
//!
//! The `tombstoned` flag kept a logically-deleted row on disk so its
//! dependents were not wiped, at the cost of a permanent divergence: the
//! in-memory `IdentityManager` drops the whole `ManagedIdentity` on
//! removal, so a re-added identity was empty in memory while the next
//! `load()` handed it the removed one's keys back.
//!
//! Deleting the row instead needs a broom for the dependents no foreign
//! key reaches:
//!
//! - `identity_keys`' FK to `identities` is compound
//! (`wallet_id, identity_id`), and SQLite's MATCH SIMPLE skips FK
//! enforcement entirely once ANY child key column is NULL — so for an
//! out-of-wallet identity (`wallet_id IS NULL` on both sides) the
//! cascade is dormant and its keys would survive the delete.
//! - `contacts`, `ignored_senders`, and `pending_contact_crypto` carry
//! identity owners but no FK to `identities`. Orphan contacts fail a
//! strict load; orphan ignored-sender rows are omitted by the loader,
//! and the deferred-crypto queue has no production reader.
//!
//! `token_balances`, `dashpay_profiles` and `dashpay_payments_overlay`
//! need nothing new: their FK column is `identity_id NOT NULL`, so it is
//! never dormant. `meta_identity` / `meta_token` keep riding V001's
//! `cascade_meta_on_identity_delete`, which this migration leaves alone.
//! V017's `identity_scan_states` / `identity_scan_failed_indices` are
//! wallet-scoped (FK to `wallets`, no `identity_id`), so a scan verdict
//! outliving one identity is the intended reading: it records how far the
//! wallet's index space was probed, not which identities came back.

pub fn migration() -> String {
"\
CREATE TRIGGER cascade_children_on_identity_delete
AFTER DELETE ON identities
FOR EACH ROW
BEGIN
DELETE FROM identity_keys WHERE identity_id = OLD.identity_id;
DELETE FROM contacts WHERE owner_id = OLD.identity_id;
DELETE FROM ignored_senders WHERE owner_id = OLD.identity_id;
DELETE FROM pending_contact_crypto WHERE owner_identity_id = OLD.identity_id;
END;
Comment thread
lklimek marked this conversation as resolved.

-- Owner columns follow wallet_id in these primary keys. Owner-leading
-- indexes avoid scanning each child table once per cascaded identity.
CREATE INDEX idx_contacts_owner ON contacts(owner_id);
CREATE INDEX idx_ignored_senders_owner ON ignored_senders(owner_id);
CREATE INDEX idx_pending_contact_crypto_owner ON pending_contact_crypto(owner_identity_id);

-- Purge what earlier schemas only flagged. Spelled out per table rather
-- than left to the cascade and the trigger above, so the outcome does
-- not depend on the migrating connection's `foreign_keys` pragma.
DELETE FROM identity_keys
WHERE identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM contacts
WHERE owner_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM ignored_senders
WHERE owner_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM pending_contact_crypto
WHERE owner_identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM token_balances
WHERE identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM dashpay_profiles
WHERE identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM dashpay_payments_overlay
WHERE identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM meta_identity
WHERE identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM meta_token
WHERE identity_id IN (SELECT identity_id FROM identities WHERE tombstoned = 1);
DELETE FROM identities WHERE tombstoned = 1;

ALTER TABLE identities DROP COLUMN tombstoned;
"
.to_string()
}
8 changes: 4 additions & 4 deletions packages/rs-platform-wallet-storage/src/sqlite/backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,8 +724,8 @@ mod tests {
conn.execute_batch("PRAGMA foreign_keys = OFF;").unwrap();
conn.execute(
"INSERT INTO identities \
(identity_id, wallet_id, identity_index, entry_blob, tombstoned) \
VALUES (?1, ?2, NULL, ?3, 0)",
(identity_id, wallet_id, identity_index, entry_blob) \
VALUES (?1, ?2, NULL, ?3)",
rusqlite::params![&[0x1Au8; 32][..], &[0x2Bu8; 32][..], vec![0u8; 4]],
)
.unwrap();
Expand Down Expand Up @@ -770,8 +770,8 @@ mod tests {
identity_id[..8].copy_from_slice(&(i as u64).to_le_bytes());
tx.execute(
"INSERT INTO identities \
(identity_id, wallet_id, identity_index, entry_blob, tombstoned) \
VALUES (?1, ?2, NULL, ?3, 0)",
(identity_id, wallet_id, identity_index, entry_blob) \
VALUES (?1, ?2, NULL, ?3)",
rusqlite::params![&identity_id[..], &[0x2Bu8; 32][..], vec![0u8; 4]],
)
.unwrap();
Expand Down
Loading
Loading