feat(lnurl): /session — one verified tap for a terminal visit #1

Merged
padreug merged 2 commits from feat/card-session-endpoint into main 2026-09-20 15:16:37 +00:00

2 commits

Author SHA1 Message Date
4e9cd78b59 feat(lnurl): /session — one verified tap for a terminal visit
Some checks failed
lint.yml / feat(lnurl): /session — one verified tap for a terminal visit (pull_request) Failing after 0s
GET /api/v1/session/{external_id}?p=&c= for bitSpire tap-to-enter. A tap
yields a single-use SUN, so a terminal that verified it at entry could not
reuse the p/c to move sats later. This verifies once (advancing the
counter like /scan), records one hit, and returns what the rest of the
visit needs: the card wallet's balance + fiat equivalent (wallet currency,
then the instance default; display only), the LUD-03 withdraw step
(callback, k1 = hit) and the LUD-06 top-up step (callback), both keyed by
the hit — the same single-use bearer /scan and /pay already hand out.
Withdraw is withheld with a reason once the daily limit is spent, as
/scan would refuse; top-up stays available.

Tests drive the real decrypt/CMAC path with a SUN encrypted under the
card's keys, and pin /verify + /pay behaviour across the helper refactor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-20 17:01:14 +02:00
3e614428c0 refactor(lnurl): share tap authentication across the fork endpoints
/pay and /verify each carried a copy of /scan's card lookup + SUN
decrypt/CMAC/replay checks + counter advance. Extract _authenticate_tap()
(same checks, same order, same reasons) and _client_info() so the fork
endpoints can't drift from upstream's acceptance rules. /scan itself is
untouched (upstream code). No behaviour change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-20 17:01:14 +02:00