Skip to content

feat: token recovery tool + AI audit prompts + speccheck (rebased onto main) - #354

Merged
c03rad0r merged 6 commits into
OpenTollGate:mainfrom
felixfelix-bot:rebase/pr-340
Aug 30, 2026
Merged

c03rad0r merged 6 commits into
OpenTollGate:mainfrom
felixfelix-bot:rebase/pr-340

Conversation

@felixfelix-bot

Copy link
Copy Markdown
Contributor

Rebased version of #340. Conflicts resolved: .gitignore merged both sides, vendor_element_manager.go kept HEAD. 5 commits applied cleanly. Build verified.

@felixfelix-bot

Copy link
Copy Markdown
Contributor Author

Rebased onto main by felixfelix-bot (supersedes #340). Ready for c03rad0r review + merge. Token recovery tool + AI audit prompts + speccheck. All conflicts resolved during rebase.

@Amperstrand Amperstrand left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fidelity-verified against our original #340's final state — all three review-fix rounds present (grep-confirmed in the tree): unspent-only recovery ( with the PENDING retry-later status), 30s per-mint checkstate timeout, no in output, single lazily-loaded wallet. File set is exactly the reviewed 9 (tool + ai-audit + speccheck + gitignore guard), binary absent. CI green.

One note before merge: CHANGELOG entry missing — the tool is user-visible operator tooling. Suggested under Added: 'Token recovery tool + AI audit prompts + speccheck (#354)' with the unspent-only/timeout semantics mentioned. Our original rebuild (orphaned branch 92ad9b9) carried a ready entry if you want to lift the wording.

@Amperstrand Amperstrand left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fidelity-verified against our original #340's final state - all three review-fix rounds present (grep-confirmed in the tree): unspent-only recovery (State != nut07.Unspent with the PENDING retry-later status), 30s per-mint checkstate timeout, no Secret[:16] in output, single lazily-loaded wallet. File set is exactly the reviewed 9 (tool + ai-audit + speccheck + gitignore guard), binary absent. CI green.

One note before merge: CHANGELOG entry missing - the tool is user-visible operator tooling. Suggested under Added: "Token recovery tool + AI audit prompts + speccheck (#354)" with the unspent-only/timeout semantics mentioned. Our original rebuild (orphaned branch 92ad9b9) carried a ready entry if you want to lift the wording.

@Amperstrand Amperstrand left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. Verified locally on this head: go build clean, and a -dry-run smoke against a sample file (comment lines skipped, malformed tokens flagged, per-line + summary report, exit 0) — the documented interface works as described.

Two notes:

  1. Your make/speccheck.sh passes vacuously — --comment-start "//" (no trailing space) matches zero quotes, so the check verifies nothing. #357 documents this exact trap and ships the corrected script. Recommend: merge #357 and let its version of the script land on top of yours, or drop the script from this PR.
  2. Heads-up: the pre-cleanup branches of #360–#363 carried a compiled binary of this tool (scripts/token-recovery/token-recovery). Your source form here is the right one — the binary copies have been dropped from those branches during the incident cleanup.

Approving — merge at your discretion (after the #357 ordering question is settled).

(E2E cloud-lab run for this head is in flight; results will follow.)

@Amperstrand

Copy link
Copy Markdown
Collaborator

E2E results + changelog addition: deployed head ffd34a2 (now includes a CHANGELOG entry for the token recovery tool, added during review) as ci-pr-354.199.ffd34a2 (CI-built ipk) on the OpenWrt x86_64 QEMU lab:

Suite Result
api/test_quote_persistence 4/4 passed
api/test_lightning_backoff 3/3 passed

The token recovery tool itself was smoke-verified locally on this head: builds clean, -dry-run against a sample file skips comments/blank lines, flags malformed tokens, and reports per-line + summary counts with exit 0. Reminder from the earlier review: let #357's corrected make/speccheck.sh land on top of this PR's vacuous-pass copy.

Amperstrand and others added 6 commits August 30, 2026 18:51
Update example from old 'TollGate-ABCD-2.4GHz-1' (band suffix)
to simplified 'TollGate-A1B2' (random chars only).
Token Recovery Tool:
Standalone Go tool that recovers Cashu tokens from
tokens-to-recover.txt (written when autopay fails with NDS gate errors).
Checks proof state at mint via NUT-07 checkstate, recovers unspent
tokens via Wallet.Receive(). Supports --dry-run.

Also includes:
- docs/ai-audit/ — 3 AI audit prompt templates (NUT compliance, security, deps)
- make/speccheck.sh — one-command greatspectations spec checking

Tested against testnut.cashu.exchange with real tokens.
Under set -e, a non-zero exit from 'spectate check' (drift found)
aborted the script before the coverage report and propagated as the
script's exit status. Drift is this script's report, not its failure
mode — report and exit 0; infra errors (install/clone) still abort.
CI gating can invert this deliberately when wired in.

Review findings: cold-code review 2026-08-17 item 3.
…leak

- PENDING proofs were treated as recoverable (state != Spent), so the
  tool could receive in-flight proofs — double-spend attempt or failed
  receive. Recoverable now requires State == Unspent for every proof;
  PENDING gets its own status and a retry-later message.
- Wallet loads once per run (lazy, first recoverable token) instead of
  per line — LoadWallet locks the bolt store, per-token loads contend.
- hash_to_curve error no longer prints p.Secret[:16] — proof secrets
  spend tokens; the slice would also panic on short secrets.
- Dry-run counts recoverable tokens separately instead of as ❌ failed.
- No timeout change needed: gonuts client already uses a 30s
  http.Client timeout (wallet/client/client.go:34).

Review findings: cold review 2026-08-18 (majors 1-2 + minors 1,2,3*4).
c03rad0r pushed a commit to Amperstrand/tollgate-module-basic-go that referenced this pull request Aug 30, 2026
…markers

- contract-lint job now installs greatspectations, clones cashubtc/nuts
  HEAD, and runs the check over all non-test sources — DRIFT FAILS THE
  BUILD (exit-code semantics verified: drifted quote exit 1, clean 0)
- critical invocation fix: --comment-start must be "// " (trailing
  space) — with "//" the marker never matches and the check passes
  vacuously. make/speccheck.sh (new on this branch; supersedes the
  version in open OpenTollGate#354 which carries the vacuous-pass bug) documents
  this in a comment
- fixed the one genuinely drifted quote: NUT-03 swap (spec now writes
  `Proofs` with backticks); 9/9 quotes verified against current spec
- added NUT-05 melt-quote at GonutsWallet.Melt (OpenTollGate#299 site)
- repaired two comment lines that parsed as malformed markers and
  aborted whole-repo runs (merchant.go dedup pointer, port.go doc
  comment)
@c03rad0r
c03rad0r merged commit 328901d into OpenTollGate:main Aug 30, 2026
c03rad0r pushed a commit that referenced this pull request Sep 7, 2026
… fixes) (#376)

* fix(spec): fix drifted NUT-03 quote, malformed markers, NUT-05 comment placement

- NUT-03 swap quote: 'generate new Proofs' -> 'generate new `Proofs`'
  (spec added backticks; the one genuinely drifted quote found by review)
- NUT-05 melt quote added at GonutsWallet.RequestMeltQuote (per reviewer
  feedback: above the request-method, not above Melt())
- merchant.go: reword 'NUT-00' marker prefix to 'Spec (NUT 00)' so it
  doesn't parse as a malformed quote marker
- port.go: reword 'NUT-04 spec' to 'spec (NUT 04)' for the same reason
- CHANGELOG: note spec-quote drift checking entry superseding #357
- .gitignore: add *.cov to exclude greatspectate coverage artifacts

* ci(spec): wire spec-quote drift check with vacuous-pass fix + coverage step

- Contract-lint job: new 'Spec-quote drift check' step that installs
  greatspectations, clones cashubtc/nuts, and verifies all NUT spec
  quotes in source comments against spec — drift fails the build.
- make/speccheck.sh: supports both local drift-report mode and CI
  fail mode. Vacuous-pass fix: tool/config/usage errors (exit 2+)
  propagate non-zero; exit 0 only for clean runs or drift-only
  (exit 1, loud banner). Coverage step folded in from main's #354
  but corrected for the real greatspectate CLI (--coverage=FILE).
- Correct command name: greatspectations installs 'greatspectate'
  as its only console script (no 'spectate'). Both CI and local
  scripts use the correct name.
- Correct --comment-start '// ' (trailing space) — without the
  trailing space the checker passes vacuously (matches nothing).
- Pinned deps: greatspectations at SHA 0f226495 with scheduled-bump
  comment; cashubtc/nuts at SHA 49a909c in CI for reproducibility.
- No silenced pip output (install logs visible).

---------

Co-authored-by: Felix <301398501+felixfelix-bot@users.noreply.github.com>
felixfelix-bot added a commit to felixfelix-bot/tollgate-module-basic-go that referenced this pull request Sep 20, 2026
…o main) (OpenTollGate#354)

* docs: fix stale SSID format comment

Update example from old 'TollGate-ABCD-2.4GHz-1' (band suffix)
to simplified 'TollGate-A1B2' (random chars only).

* feat: add token recovery tool + AI audit prompts + speccheck

Token Recovery Tool:
Standalone Go tool that recovers Cashu tokens from
tokens-to-recover.txt (written when autopay fails with NDS gate errors).
Checks proof state at mint via NUT-07 checkstate, recovers unspent
tokens via Wallet.Receive(). Supports --dry-run.

Also includes:
- docs/ai-audit/ — 3 AI audit prompt templates (NUT compliance, security, deps)
- make/speccheck.sh — one-command greatspectations spec checking

Tested against testnut.cashu.exchange with real tokens.

* fix(speccheck): exit 0 after reporting drift

Under set -e, a non-zero exit from 'spectate check' (drift found)
aborted the script before the coverage report and propagated as the
script's exit status. Drift is this script's report, not its failure
mode — report and exit 0; infra errors (install/clone) still abort.
CI gating can invert this deliberately when wired in.

Review findings: cold-code review 2026-08-17 item 3.

* fix(token-recovery): unspent-only recovery, single wallet, no secret leak

- PENDING proofs were treated as recoverable (state != Spent), so the
  tool could receive in-flight proofs — double-spend attempt or failed
  receive. Recoverable now requires State == Unspent for every proof;
  PENDING gets its own status and a retry-later message.
- Wallet loads once per run (lazy, first recoverable token) instead of
  per line — LoadWallet locks the bolt store, per-token loads contend.
- hash_to_curve error no longer prints p.Secret[:16] — proof secrets
  spend tokens; the slice would also panic on short secrets.
- Dry-run counts recoverable tokens separately instead of as ❌ failed.
- No timeout change needed: gonuts client already uses a 30s
  http.Client timeout (wallet/client/client.go:34).

Review findings: cold review 2026-08-18 (majors 1-2 + minors 1,2,3*4).

* fix: cold review — bound each mint checkstate call with 30s timeout so a hung mint cannot stall recovery

* docs: changelog entry for token recovery tool

---------

Co-authored-by: Amperstrand <amperstrand@localhost>
Co-authored-by: amperstand <atlas@oh-my-opencode.com>
Co-authored-by: Felix <301398501+felixfelix-bot@users.noreply.github.com>
Co-authored-by: Amperstrand <amperstrand@users.noreply.github.com>
felixfelix-bot added a commit to felixfelix-bot/tollgate-module-basic-go that referenced this pull request Sep 20, 2026
…ith reviewer fixes) (OpenTollGate#376)

* fix(spec): fix drifted NUT-03 quote, malformed markers, NUT-05 comment placement

- NUT-03 swap quote: 'generate new Proofs' -> 'generate new `Proofs`'
  (spec added backticks; the one genuinely drifted quote found by review)
- NUT-05 melt quote added at GonutsWallet.RequestMeltQuote (per reviewer
  feedback: above the request-method, not above Melt())
- merchant.go: reword 'NUT-00' marker prefix to 'Spec (NUT 00)' so it
  doesn't parse as a malformed quote marker
- port.go: reword 'NUT-04 spec' to 'spec (NUT 04)' for the same reason
- CHANGELOG: note spec-quote drift checking entry superseding OpenTollGate#357
- .gitignore: add *.cov to exclude greatspectate coverage artifacts

* ci(spec): wire spec-quote drift check with vacuous-pass fix + coverage step

- Contract-lint job: new 'Spec-quote drift check' step that installs
  greatspectations, clones cashubtc/nuts, and verifies all NUT spec
  quotes in source comments against spec — drift fails the build.
- make/speccheck.sh: supports both local drift-report mode and CI
  fail mode. Vacuous-pass fix: tool/config/usage errors (exit 2+)
  propagate non-zero; exit 0 only for clean runs or drift-only
  (exit 1, loud banner). Coverage step folded in from main's OpenTollGate#354
  but corrected for the real greatspectate CLI (--coverage=FILE).
- Correct command name: greatspectations installs 'greatspectate'
  as its only console script (no 'spectate'). Both CI and local
  scripts use the correct name.
- Correct --comment-start '// ' (trailing space) — without the
  trailing space the checker passes vacuously (matches nothing).
- Pinned deps: greatspectations at SHA 0f226495 with scheduled-bump
  comment; cashubtc/nuts at SHA 49a909c in CI for reproducibility.
- No silenced pip output (install logs visible).

---------

Co-authored-by: Felix <301398501+felixfelix-bot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants