Repository navigation
test: add native USDT recovery fault fixture - #180
ben-kaufman wants to merge 3 commits into
Conversation
talosmachina
left a comment
There was a problem hiding this comment.
1 finding (1 P2). Adds a loopback RPC/VSS fixture with fault injection and an append-only event ledger for the native USDT recovery tests; no Rust changes. Reviewed 3c6cbca, full tier.
What I checked, and 4 candidates I ruled out
Read in full: provider.mjs, control.mjs, provider.test.mjs, README.md, package.json, package-lock.json, .gitignore
Ran: npm ci --ignore-scripts, npm run check, npm test on Node 24: 1/1 pass. Reproduced the finding against a live fixture on a scratch port.
Cross-checked: how the bitkit-android#1681 test drives /control (mode with advance, faultMode read back).
CI: green (usdt-tests, SwiftPM manifest, Scripts/Cargo/Android manifests). CI does not run the fixture's npm test.
Ruled out
- Lockfile pulls from an unexpected source: all 9 packages resolve from registry.npmjs.org with integrity hashes;
ethers6.17.0 pinned exactly. - Server reachable off-box: binds
127.0.0.1only. - Path traversal through the case id:
load()requires^[a-z0-9-]{1,64}$before touching the filesystem. - Second, different operation accepted on resubmission: a resubmitted hash must deep-equal the stored payload, and the companion test asserts exactly one operation.
Merge confidence: 4/5, one P2 in the fault-injection control path; the rest is covered by the fixture's own test and the companion runs.
Companion: synonymdev/bitkit-ios#1118
Companion: synonymdev/bitkit-android#1681
Description
Add a loopback RPC/VSS fixture so both apps can exercise actual native signing, encrypted recovery uploads and restart/restore without funds. It injects rejected writes or committed writes with lost acknowledgements, records every submission attempt before validation, and preserves an independent original-operation oracle. Native tests must acknowledge their own recovery record before submitting the same signed operation.
Preview
N/A — test infrastructure, no UI changes.
QA Notes
Setup
Follow the pinned recipe. Use Node 22+, locked dependencies, a dedicated simulator/emulator with no application wallet, and the companion app branches. The recipe starts a loopback-only server and runs prepare, resume and restore in separate native test processes. Never fund the public fixture mnemonic or reset an existing wallet.
Verified
npm run checkandnpm testpassed. The black-box guard test proves rejected invalid submissions are counted, the original oracle cannot be replaced, and evidence/token survive server restart.9a763eb4; Android as2d8f87470.cargo fmt --check, CI-scope Clippy andgit diff --checkpassed. All 94 Clippy warning blocks match unchanged Core production; this PR changes no Rust code. Final companion gates passed 2,889 iOS unit tests and 4,602 Android unit tests with clean native format/lint reports.Native evidence used Core
c393f8e0, Paykite79b7bbband Pubky65a331e0built locally; it is not proof of released dependency adoption. The initial native protocol evidence used fixture3c6cbca9. Review repair16e67c7dnow validates and persists the entire control update before changing live state; mixed-field rejection and disk-write failure tests fail before the repair and pass after it. Independent re-review found no remaining actionable issue. Commit96420950runs the fixture syntax and regression tests in hosted CI.Limits
This fixture does not execute deployed contracts, validate LNURL signatures or test the complete UI/Paykit journey. Android exercises the recovery store directly; iOS exercises the BackupService handler. The complete-wallet assertion preserves sentinel bytes, not a full-wallet migration. The unused Pubky 503 endpoint is not outage-integration evidence. Existing component tests cover migration/concurrent state changes separately. One iOS test launch was rejected by Simulator before execution and a later restore was interrupted by the chat shutdown; the final fresh rejected-backup sequence passed all phases.
Models used
gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)