Repository navigation
test(cloud-lab): #497 crash-window harness — SIGKILL between mint-signed and wallet-save - #569
Amperstrand wants to merge 1 commit into
Conversation
da902a1 to
5f2201e
Compare
|
Technical review (evidence pass) Ran the harness for real, twice, on a shared docker host (unique compose project, dedicated subnet, full teardown verified): it does what the body claims, the kill point is deterministic, and a full run costs ~5 minutes. Two small blockers below (both one-liners); the design itself is sound and is the right shape for #497's TollGate-layer acceptance criterion. What I ranBoth runs: mints+killer up → tollgate last (accepted mints correctly rewritten to The killer's request log (docker timestamps, run 2) is the determinism proof: The 17.02 retry is precisely the case a one-shot swallow would have let complete behind the kill — the persistent-swallow design at killerproxy.py:72-93 is not just theory, it carried the window. Marker semantics are sound: the marker is written exactly when the mint's 200 reaches the proxy, and the wallet provably cannot complete between marker and kill. One worry I checked and ruled out: could the client's funding swap arm the marker early? Empirically no — the killer logs every request before forwarding, and the client's Runtime/leak-safety of the script itself: every wait is bounded (mint 40×1 s, marker 60×1 s, recovery 40×3 s, HTTP timeouts on all client calls) — no hang path I can find. Isolation claims verified live: no host ports ( Blocker 1 — cleanup leaks the killer container and the network
"${COMPOSE[@]}" -f "$RUN_DIR/override.yml" down -v --remove-orphans >/dev/null 2>&1 || trueI verified this exact invocation removes everything (used it to tear down my KEEP=1 run; containers, network, and volumes all gone). Blocker 2 — changelog entry links the wrong PRCHANGELOG.md:212 links Boundary coverage vs the AGENTS.md listAGENTS.md enumerates five kill boundaries. This harness covers exactly one of them — and the one #497's acceptance criterion names:
None of that blocks this PR — its stated scope is the last TollGate-layer deliverable, and it delivers that. Smaller notes
Hygiene: single well-structured commit, no attribution footers, base is 8 commits behind DispositionRequest-changes — both items are one-liners: (1) make |
|
Technical review (evidence pass) — PR head The branch head does not contain this PR. The body describes the #497 crash-injection harness — What the head does contain is a single commit, This is not an isolated accident, and I want to flag the pattern because it has now eaten four PR heads. PR #549 ( Since the diff carries no code, the usual criteria are vacuous for what's actually here — no new dependencies, no security surface, nothing to test. But against the described change, one thing deserves to be said before a re-push, because it's the part a maintainer will press on: the killer-proxy design is the correct shape for the #497 acceptance criterion. Killing after the mint's first signed swap response (not after the request) is the only placement that hits the true point-of-no-return; funding and paying through the killer so the token's mint URL matches the tollgate's accepted spelling pre-empts exactly the alias-canonicalization trap that made #375/#480 confusing; and gating the recovery assertion on the intent machinery (rather than weakening it to pass on Blocking items, in order:
Disposition: request-changes — nothing to review yet; the described change is real, wanted (#497 is the open P0), and the design is sound, but the head must actually carry it. Given the cluster, it may be worth a maintainer-side audit of what else the overwriting push clobbered across #530/#549/#557/#569. |
5f2201e to
95fe457
Compare
…ned and wallet-save run-crash-injection.sh places the tollgate's mint traffic behind killerproxy.py, which swallows every /v1/swap response once the mint has signed — including the wallet library's connection-retry ladder (a one-shot swallow lets the retry complete the operation and defeats the injection; a release file gates the pass-through back on after the kill, which is exactly what the boot-time replay needs). The driver SIGKILLs the tollgate at that exact boundary, restarts it, and requires the intent resume to recover the value; a fresh payment must then still succeed. This is #497's acceptance criterion at the TollGate layer: 'Test kills the process (SIGKILL) between POST-swap and SaveProofs with a mint that recorded the swap; on restart the wallet completes the swap and the proofs appear (balance preserved).' Verified live against the intent train (gonuts #31/#33 + the boot-resume wiring): marker -> kill mid-wait -> restart -> 'pending op … recovered 50 sats' -> post-recovery payment 200. Against pre-intent binaries the recovery assertion fails by design — that is the point.
95fe457 to
252ca33
Compare
|
Branch restored and rebased (post-review maintenance). This branch had been force-pushed over with unrelated content (the #577-era changelog commit); the crash-window harness survived only as a dangling commit. Restored from |
|
First live run of the crash-injection harness — mechanics PASS, and its verdict on the current tree is (correctly) RED. Ran
Which is the finding worth having on record: the #497 exposure is real and unmitigated on today's main — a power loss between the mint's swap acceptance and the wallet's proof save destroys the customer's value today, and this lane is the acceptance harness that any future swap-intent PR (gonuts-tollgate #31/#33-era machinery + the TMBG boot-resume wiring) must turn green. Until then the harness is doing its job by staying red. Mechanics note for whoever runs it next: it publishes host |
|
Conflicts resolved on a rebase of the single commit ( Replacement PR: #676 — #676 — base
Not run here: the harness needs a tollgate built with the gonuts swap-intent machinery plus the compose lab — and against a pre-intent binary the recovery assertion fails by design, so a run without that binary proves nothing. The commit's live record (marker → kill mid-wait → restart → Two shellcheck findings in the new script — flagging, not silently editing an approved file: Merge #676 and this PR closes as superseded, or force-push |
Implements the last #497 deliverable at the TollGate layer: the SIGKILL-at-boundary harness — literally the issue's acceptance criterion ("kill between POST-swap and SaveProofs…; on restart the wallet completes the swap and the proofs appear").
How the deterministic kill works
killerproxy.pysits in the compose network between the tollgate and the mint (the tollgate's config points its accepted mint at the killer service). All traffic passes through except/v1/swapresponses after the mint has signed the first one:releasefile — from then on the killer passes through, which is precisely what the boot-time intent replay needs.The scenario
run-crash-injection.sh(same isolation conventions aslab.sh): isolated project/subnet/container names, no host ports, all mints + killer up before the tollgate boots (a boot-order mistake starts it degraded — lesson #6 in the RUNBOOK), fund and pay through the killer so the token's mint URL matches the tollgate's accepted spelling, kill, restart, then two assertions: the recovery log line, and a fresh payment returning 200.Verified live (against the intent train: gonuts #31/#33 + boot-resume wiring)
Against pre-intent binaries the recovery assertion fails by design — the harness exists to prove the window costs value without the machinery. The lane needs the gonuts intent PRs merged + the TMBG boot-resume wiring to pass on
main; until then it is runnable manually against the stacked branch (how it was verified).Also in this PR
make go-battery: 16 modules green (shell/python only, no Go changes).