Skip to content

LUD-24 – pinLimit for withdrawRequest (PIN protection for NFC/Boltcard) - #290

Open
AxelHamburch wants to merge 11 commits into
lnurl:ludsfrom
AxelHamburch:draft/pinlimit-withdrawrequest
Open

LUD-24 – pinLimit for withdrawRequest (PIN protection for NFC/Boltcard)#290
AxelHamburch wants to merge 11 commits into
lnurl:ludsfrom
AxelHamburch:draft/pinlimit-withdrawrequest

Conversation

@AxelHamburch

@AxelHamburch AxelHamburch commented May 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Clean resubmission of PR #200 (pinLimit for withdrawRequest), open since
February 2023 without being merged.

Supersedes #200. Related to governance discussion: #289.

Spec file: 24.md

What this adds

An optional pinLimit field to the withdrawRequest response (LUD-03 extension).
When present and the withdrawal amount meets or exceeds the threshold, the wallet
must collect a 4-digit numeric PIN before sending the callback. If the PIN is
absent or wrong, the SERVICE MUST reject the request — there is no fallback.

Assigned as LUD-24.

Why now

Changes vs PR #200

PR #200 This PR
LUD number LUD-21 (conflict) LUD-24
HTTPS implicit explicit MUST
Brute-force protection SHOULD MUST
Service rejection if PIN missing unclear explicit MUST
Mermaid diagram none added (aligned with LUD-03)
Prior art reference none PR #200 cited

Known implementations (verified)

Project Evidence
SwissBitcoinPay/boltcard-tools-terminal PR #33 merged 2024-05-26
boltcard/boltcard-lndhub Release v0.2.0 (2023-08-06): "PIN feature added"

@andrerfneves andrerfneves added contested Competing proposals for the same LUD number — needs arbitration draft Spec exists but still being shaped lud-extension Adds a field or behavior to an existing LUD labels May 25, 2026
@AxelHamburch

Copy link
Copy Markdown
Contributor Author

Known Implementations of LUD-XX pinLimit

The following open-source projects implement the draft
LUD-XX pinLimit for withdrawRequest
spec. They were developed independently against the same draft and interoperate
end-to-end, demonstrating production readiness prior to formal number assignment.


Service-side implementations

These projects serve the withdrawRequest JSON and validate the pin parameter
on the callback.

lnbits/boltcards — LNbits extension

  • PR: lnbits/boltcards#67
  • Key commit: dc46cd1
  • Adds pinLimit field to withdrawRequest response
  • PIN stored as pbkdf2_hmac hash; validated on callback
  • Card disabled after 3 consecutive failures
  • PIN failure count persisted across taps (pin_total_attempts)
  • Frontend form fields for setting PIN and threshold (sats/msats)

bitPOS-app/bitpos — self-hosted Lightning PoS

  • File: artifacts/api-server/src/routes/lnurlw.ts
  • pinLimit included in withdrawRequest when card has a PIN set
  • pinLimitMsats = null maps to 0 on the wire (PIN always required)
  • PIN verified via bcrypt against stored hash
  • Atomic k1 consumption includes pinLockedAt guard (defence-in-depth)
  • Card locked in DB after 3 failures; fail counter reset on success

Terminal / wallet-side implementations

These projects read the withdrawRequest, detect pinLimit, and collect the
PIN from the user before sending the callback.

AxelHamburch/zapbox_extension — ZapBox NFC touch terminal (LNbits extension)

  • Commit: c111234
  • Detects pinLimit in withdrawRequest; compares price_msat >= pin_limit_msat
  • Sends pin_required WebSocket event to the ZapBox touch display with amount_sat, session_id, max_attempts
  • Device renders PIN pad and POSTs 4-digit PIN to /nfc/pin_submit?session_id=&pin=
  • Server-side coroutine awaits PIN via asyncio.Event (max 180 s timeout)
  • On wrong PIN: sends pin_error WS event with remaining attempts
  • On 3rd failure: raises HTTP 403; device shows blocked screen
  • Appends &pin=XXXX to the boltcards callback URL

Buho-Ecosystem/Buho_go — BuhoGO mobile wallet (Android/iOS)

  • Commit: 38ada0a
  • Branch: feature/bolt-card-pin-limit
  • pinLimit forwarded from fetchLNURLInfo into pendingPayment
  • After invoice creation, checks amount_sats × 1000 >= pinLimit
  • Shows fullscreen PinEntryDialog (4-digit numeric, spec-compliant)
  • User cancels → withdrawal resets silently; no callback sent
  • PIN appended as &pin=XXXX to callback URL via submitWithdrawCallback
  • Wrong PIN → service error surfaced to user; retry by sliding again
  • No PIN prompt when pinLimit absent or amount below threshold (existing flow unchanged)

End-to-end interoperability

NFC Card tap
     │
     ▼
LNURL-withdraw Service ──────────────────────── boltcards (LNbits)   PR #67
  returns withdrawRequest                        bitpos (self-hosted)  merged
  with optional pinLimit field
     │
     ▼
Terminal / Wallet ────────────────────────────── zapbox_extension      merged
  detects pinLimit                               Buho_go (mobile)      open PR
  prompts user for 4-digit PIN
  sends ?pin= in callback
     │
     ▼
Service validates PIN
  wrong PIN  → ERROR + attempts remaining
  3 failures → card blocked
  correct    → OK, payment settles

A card provisioned against boltcards or bitpos can be tapped at a
zapbox_extension terminal or paid via Buho_go — the PIN flow works
end-to-end across all combinations.

@andrerfneves andrerfneves changed the title Draft: LUD-XX – pinLimit for withdrawRequest (PIN protection for NFC/Boltcard) Draft: LUD-24 – pinLimit for withdrawRequest (PIN protection for NFC/Boltcard) Jul 11, 2026
@andrerfneves andrerfneves changed the title Draft: LUD-24 – pinLimit for withdrawRequest (PIN protection for NFC/Boltcard) LUD-24 – pinLimit for withdrawRequest (PIN protection for NFC/Boltcard) Jul 11, 2026
@andrerfneves
andrerfneves force-pushed the draft/pinlimit-withdrawrequest branch 2 times, most recently from 7f20c84 to f2b4dc3 Compare July 11, 2026 02:59
@andrerfneves

Copy link
Copy Markdown
Collaborator

Assigning LUD 24

@andrerfneves
andrerfneves force-pushed the draft/pinlimit-withdrawrequest branch from f2b4dc3 to bba3a72 Compare July 11, 2026 03:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contested Competing proposals for the same LUD number — needs arbitration draft Spec exists but still being shaped lud-extension Adds a field or behavior to an existing LUD

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants