Audit hardening: payout correctness, self-custody payouts, bech32, AI batching#26
Merged
Conversation
A payout item was marked "paid" for any non-empty preimage the wallet returned, with no proof the sats actually moved. A buggy or hostile wallet could fake settlement. Add app/services/bolt11.py to extract an invoice's payment hash and check sha256(preimage) == payment_hash. Items whose preimage does not verify get a new terminal "unverified" status (not "failed", so retry won't re-send money that may already have left the wallet). The decoder is validated against the canonical BOLT#11 spec test vector.
create_payout built a fresh Payout on every call, so a double-click or a client retry after a timeout paid every winner again. Add a unique (allocation_id, team_label) constraint plus an explicit 409 pre-check, with an IntegrityError catch on flush as the race backstop (fires before any sats move). Re-attempts route through the existing retry endpoint.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
comwanga
added a commit
that referenced
this pull request
Jun 20, 2026
Self-custody payouts + audit hardening (re-land of #26 remainder)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
End-to-end audit hardening. Each fix is its own commit, developed under TDD. Backend 156 passed; frontend 58 passed + typecheck + lint + production build green.
Bitcoin / Lightning — correctness
paidfor any preimage the wallet returned. Newbolt11.py(validated against the canonical BOLT#11 spec vector) checkssha256(preimage) == payment_hash; an unverifiable preimage is terminalunverified.create_payoutmade a fresh payout every call, so a double-click / timeout-retry paid winners twice. Unique(allocation_id, team_label)constraint (migration0008) + 409 + IntegrityError race backstop.total_satswas bounded only bygt=0; configurablePAYOUT_MAX_SATSenforced pre-flight.Bitcoin / Lightning — self-custody (architectural)
Design:
docs/superpowers/specs/2026-06-20-self-custody-payouts-design.md.lib/lightning.ts) resolves invoices (LUD-16) and performs the NIP-47pay_invoiceover a WebSocket; the server createspendingitems and verifies each reported preimage before recordingpaid.nwcrequest field) is removed, so the backend has no way to spend — self-custody is enforced, not opt-in. This also eliminates the old blocking/timeout-prone server-side payment loop.Nostr
AI
max_tokens=1024call truncated past ~14 "Other" registrants and silently dropped the whole event to the deterministic fallback. Now batched with per-batch failure isolation, a cacheable system block, and an abstention path. Prompt-build/parse are pure, unit-tested helpers.Hygiene
requestsdependency.Still open (larger, additive — recommend separate PRs)
More native rails (BOLT12 offers / NIP-57 zaps), client-side
get_balancepreflight, registration rate-limiting, and deeper AI features (the unusedtech_stack/interestssignals, team rationale, NL results query).