crash-window lane: no value recovery after restart (SIGKILL between mint-signed and wallet-save) — #502/#700 acceptance FAILS on main
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
Start with tests/cloud-lab/run-crash-injection.sh and identify the post-restart recovery wait and assertion. Then follow the receive-intent journal and resume in src/merchant/ and the swap-intent machinery in src/tollwallet/; compare the lane behavior with the passing unit test named in the issue. Determine whether reconciliation completes within the lane window and whether it recovers value; done means the lane exits 0 and a fresh payment succeeds.
Written by the indexing model from the issue text.
Description
Summary
The crash-window acceptance lane for the payment-convergence work (#502/#700, the business-transaction record) fails on current main: after the tollgate is SIGKILLed between "mint signed the swap" and "wallet has persisted", the boot-time intent resume does not recover the value within the lane's window. This is the exact invariant the lane exists to hold.
Severity: S1/S2 candidate (funds-adjacent). The log shows the #502 machinery engaging (intent restored, NUT-07 reconciliation started) — so the failure is either reconciliation-not-completing in the lane's wait window (timing) or reconciliation completing without recovering the value (lost value). Distinguishing those two is the first triage step.
Verified on
- Commit:
68ad5144ab09cb4723d8f3f655cbba1ac7ea9de5(main, 2026-10-07) + release-prep metadata commit (code-identical) - Host: docker 29.1.3, linux/amd64; lane run via
tests/cloud-lab/run-crash-injection.sh - Campaign evidence: release-labgrid-testing, 2026-10-07
Evidence (verbatim, from the lane transcript)
== paying in the background (the swap response will be swallowed)
== waiting for the swap response marker (mint has signed)
marker: /v1/swap
== SIGKILL the tollgate (mid-wait: mint signed, wallet has NOT processed)
killed at 18:53:33
== restarting the tollgate; boot resume must replay the intent
FAIL: no recovery after restart — the crash window destroyed value:
2026/10/07 16:53:33 PurchaseSession: Receive completed, amount=0, err=mint did not answer; the outcome is unknown: could not swap proofs: mint http://killer:8085/v1/swap did not answer; the request may have been processed — reconcile before retrying: Post "http://killer:8085/v1/swap": EOF
2026/10/07 16:53:34 Restored 1 pending receive intent(s) — reconciling against their mints (NUT-07)
Note the two log lines: the pending intent IS restored and NUT-07 reconciliation IS started one second after restart — then the lane's recovery assertion fails.
Reproduce
Prerequisites: a linux docker host (docker 29.x needs the Dockerfile.client ARG fix from the companion issue "cloud-lab client image unbuildable on docker/buildkit 29" — or build the client image manually first). If your docker build bridge has no working DNS for proxy.golang.org (symptom: dial tcp: lookup proxy.golang.org ... network is unreachable inside RUN go build), pre-build images with build.network: host.
git clone https://github.com/OpenTollGate/tollgate-module-basic-go && cd tollgate-module-basic-go
git checkout 68ad5144ab09cb4723d8f3f655cbba1ac7ea9de5
cd tests/cloud-lab
export TG_GO_VERSION="$(jq -r '.go.version' ../../packaging/build-inputs.json)" # 1.26.8
./run-crash-injection.sh ; echo EXIT=$?
Expected (per #497/#502/#676 acceptance): exit 0 — intent resume recovers the value AND a fresh payment afterwards still succeeds.
Actual: FAIL: no recovery after restart — the crash window destroyed value and exit 1.
Troubleshooting guide (for the fixing agent)
- Read the lane first:
tests/cloud-lab/run-crash-injection.sh— the killer proxy (killerproxy.pyfrom PRTA, mounted read-only) swallows every/v1/swapresponse once the mint has signed; the tollgate is SIGKILLed when the/marker/kill.markerfile appears; the assertion block is after the restart. Find the exact wait window it gives the reconcile loop. - Distinguish timing vs lost value: instrument or watch the upstream container logs after restart — does the NUT-07 reconcile (
Restored 1 pending receive intent(s)) ever complete? If it completes but the proofs are gone, that's lost value; if it needs longer than the lane waits, the lane's window is too tight for the reconcile path (still a release problem, different fix). - Code pointers: the receive-intent journal and resume live in the #502/#700 business-transaction work —
src/merchant/(purchase-session guard + journal; seepurchasesession_duplicate_guard_test.gofor the intended semantics) andsrc/tollwallet/(swap-intent machinery; gonuts-tollgate v0.13.0 persrc/tollwallet/go.mod). The "outcome is unknown … reconcile before retrying" string in the log above is the unknown-outcome path — that is the state the resume must resolve. - Reference material:
docs/architecture/bearer-instrument-port.mdandresearch/bearer-port-demo/describe the intended derivation-replay recovery (NUT-07 answer is about consumption, never existence;SPENT/UNSPNTonly from what the authority said). - Unit-level repro that passes today:
cd src/merchant && go test -tags testenv -run 'TestPurchaseSessionGuardHoldsThroughTheOutcomeUnknownWindow' -v(needs anndsctlshim on PATH on a bare host — see companion issue). The docker lane is where it fails; the unit test seeds a scripted wallet, the lane uses a real mint behind the killer.
Fix hints
- If timing: widen/loop the lane's post-restart wait on a functional signal (e.g. poll the owed-grant/session event rather than a fixed sleep), and check the reconcile backoff constants the boot resume uses.
- If lost value: the boot-time replay must re-derive the blinded proofs from the journal and re-drive the swap (or recover via NUT-09 token state) — start where
Restored N pending receive intent(s)is logged and follow what that reconcile actually does for a swap whose response was swallowed. - Regression guard: this lane IS the regression guard — once fixed, keep it in the release gate (
make release-checkwithTOLLGATE_RELEASE_CHECK_CONFORMANCE=1on the machine that owns the lane).
References
- #497 (crash-window acceptance), #502/#700 (business-transaction record), #676 (harness), #631 (bearer-instrument port research)
- Dominant language
- Go
- Stars
- 12
- Forks
- 14
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 211
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenTollGate/tollgate-module-basic-go
-
go-battery needs an ndsctl on PATH: TestPurchaseSessionGuardHoldsThroughTheOutcomeUnknownWindow fails on bare hosts (passes with stub)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OpenTollGate/tollgate-module-basic-go#726 ·
Maintainers usually reply within 1 day
-
rebrand-literal-gutter: uhttpd section-vocabulary check trips on a COMMENT (uhttpd.luci in 92-tollgate-admin-setup:178)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OpenTollGate/tollgate-module-basic-go#723 ·
Maintainers usually reply within 1 day
-
Discovery endpoint serves text/plain content-type on / — r2r clients warnPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
OpenTollGate/tollgate-module-basic-go#628 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
OpenTollGate/tollgate-module-basic-go#725 ·
Maintainers usually reply within 1 day
-
cloud-lab Dockerfile.client: mid-file ARG invisible to FROM — client and killer images unbuildable on docker/buildkit 29 (golang:-bookworm)Possibly taken @Amperstrand claimed this today. Open
Difficulty 1/5 Under an hour Newbie friendliness 25/100
OpenTollGate/tollgate-module-basic-go#724 ·
Maintainers usually reply within 1 day
All issues in OpenTollGate/tollgate-module-basic-go
Similar issues
-
agent-research-recommend agent-review-finding chore
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
jordansmall/spindrift#4821 · 1 comment ·
Maintainers usually reply within 1 day
-
area:web
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
praetorianer777/GoTome#178 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
oracle/go-oracledb#105 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day