cashu-cdk-seller: corrections for advisor findings F1-F6 - #988
cashu-cdk-seller: corrections for advisor findings F1-F6#988maxy-player wants to merge 17 commits into
Conversation
…ema correction, v0.5.8 image not published
…ld.rs needs it even without grpc)
…int now boots and serves /v1/info
…, failed payment, restart, loopback)
…eds check_payment_state=Unpaid too
…ce), live readiness blocked on human credential provisioning
…h knowledge, test state out of /work, locked deps and digest-pinned bases
…predicates, full-residual-spend after mint restart
|
Someone is attempting to deploy a commit to the MakePrisms Team on Vercel. A member of the Team first needs to authorize it. |
…hells too (/etc/profile clobbered it)
…build at image build time
…3/F5 (offline compile, knowledge paths, state isolation, 39/10 gate)
…oning path (claude setup-token -> daemon env -> per-job placeholder)
… recovery branches to complete value, quoted fees not derived, check reserved
…nded-reserve counterexample and proves the corrected oracles reject it
…ovenance bounds, non-root bound-workdir recipe, human-only selected-field VPS setup; bound AUTH claims and cross-link both ways
|
Focused-review corrections F4/F5/F6 — seller-local, Three commits on top of
Predicate regression result — PASS, 10 oracle requirements across 3 fixtures. It builds a real wallet with 42 of 43 sats stranded in Reserved, then requires the shipped oracles to accept it and the corrected oracles to reject it. Both defects reproduce: the old drain oracle reports "fully drained" with 42 sats reserved, and the old derived-fee conservation relabels the shortfall as a fee. Evidence: Image No corrected full-gate assertion count is quoted anywhere: the corrected gate has more assertions than 39 and I deliberately did not run it for a number, so the addendum tells the reader to run it and read the output instead. Not done, not claimed: the seat still refuses to advertise without a model credential ( |
Correction commits addressing the six blocking findings (F1–F6) from the independent review of
aa8e831. The original evidence from that commit is preserved unchanged; these are additions on top, not a re-fold.What this branch adds
c15f0ad— F1, F2, F3, F6cargo/rustcat all — build-time cache mounts are not layers, so nothing survived. The mint-builder stage now copies the toolchain to/opt/rust/toolchainand the crate registry cache to/opt/rust/cargo/registry, withCARGO_HOME=/opt/rust/cargoandCARGO_NET_OFFLINE=true.bin/cashu-toolchain-checkis the proof command: it asserts toolchain identity, ≥50 cached.cratearchives, presence ofcdk-0.17.2/cashu-0.17.2/cdk-sqlite-0.17.2, then compiles the shippedexamples/wallet-roundtripwithcargo build --offline --locked./opt/cashu/knowledge/(cashu-corpus.md,test-mint.md,cdk-wallet-api.md,known-drift.md); no wikilinks that resolve only on the host./var/lib/cashu-test-state, created mode 1777.test-mintrefuses to run with state under/work(assert_state_not_delivered), and a newtest-mint isolationsubcommand is the evidence command: exit 0 only when state is outside/workand no mint artifacts appear inside it.FROMis digest-pinned;CDK_VERSION,CDK_COMMIT(6132607…, tag v0.17.2) andNUTS_COMMIT(49a909c…) are build ARGs;cdk-mintdis installed--locked; the three helper crates ship generatedCargo.lockfiles.0ac777d— F4, F5F4 (recovery semantics). The previous documentation was wrong about
check_all_pending_proofs. Read back from cdk 0.17.2src/wallet/proofs.rs:112-185: it filters out saga-managed proofs, removes spent ones, and returns the total still pending — it does not move survivors back toUnspent. The real recovery path isrecover_incomplete_sagas(wallet/recovery.rs:302) plusrevoke_send(wallet/send/mod.rs:275), which swaps proofs back and is what actually returns value to the spendable set. Corrected in the knowledge topic and asserted in the gate.F5 (exact negative predicates, real residual spend). Two ways the old gate could pass without proving anything, both closed:
matches!(e, Error::TokenAlreadySpent)andmatches!(e, Error::PaymentFailed)— on the variant, not a message substring.total_balance, which reads the wallet's own localstore (wallet/balance.rs:10-20) and says nothing about mint state. The restart leg now sweeps every wallet's entire residual balance into a fresh wallet through the restarted mint and reconciles swept + fees against the pre-restart total, so the mint has to sign for all of it. It also re-presents the pre-restart spent token and requiresTokenAlreadySpent, catching duplicate credit from a rolled-back database.Recovery is exercised from a genuinely non-empty unresolved state across a wallet restart on a real sqlite file (create token, never redeem, drop the wallet, reopen the same file), not with in-memory stores that never reopen.
Containment (unchanged)
Fakewallet backend only —
cdk-mintdis built--no-default-features --features fakewallet,sqlite, so no real payment backend is compiled in and it cannot be pointed at real money. Loopback-only bind, enforced on both the host argument and the rendered config, and checked from/proc/net/tcpin the gate. The test mint is never added toaccepted_mints. Worthless test ecash throughout.Status — read this before reviewing
maxplayer-cashu-sandbox:v0.5.9-fixbuilds clean, and the image now proves the offline CDK build at build time (Finished dev profile ... in 39.34s), so it cannot ship claiming an environment it lacks.reports/cashu-cdk-seller/delta-*-20260909.txt, from a container run with a host directory bind-mounted at/work:.cratearchives,cdk/cashu/cdk-sqlite0.17.2 present, example built--offline --lockedand then run against the mint (issued 32, sent 8, melted 4, fee 1)./var/lib/cashu-test-state,state inside delivered dir: no, no mint artifacts in/work, seed mode600./opt/cashu/knowledge/.aa8e831evidence files are preserved untouched; the old 22/22 gate is not offered as proof of these corrections.reports/cashu-cdk-seller/AUTH-PROVISIONING.mddocuments the exact supported credential path and the concrete human setup step. Live marketplace readiness remains blocked on that human decision; no discovery evidence is claimed.Three defects found by actually running this, not by reading it
prepared.confirm(None)calls — caught by the first build failing.bash -lclost the toolchain: Debian's/etc/profileassignsPATHunconditionally, sorustcwas "not found" in an image that had it. Fixed with/etc/profile.d/10-rust-toolchain.shplus the script resolving its own toolchain, so the proof cannot report a false negative based on how its caller spawned a shell.cc, nogcc, nold). A toolchain plus a warm registry is not a build environment; the offline build died atlinker \cc` not foundafter resolving every dependency correctly. Fixed by installinggcc,libc6-dev,binutilsand recording their exact versions into/opt/rust/TOOLCHAIN.txt`.The first evidence run reported F1 as passing when it had not, because
;separators let a failure scroll past. That is fixed too: the evidence run isset -ethroughout.