From b52a1b3feaf233fd1bc84684ddb97f93bca64444 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 25 Jun 2026 08:41:55 -0400 Subject: [PATCH] =?UTF-8?q?docs(zap):=20close=20#3=20CORS/LNURL=20?= =?UTF-8?q?=E2=80=94=20accept=20graceful=20degradation,=20no=20proxy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decision: keep the visual zappability flag as the honest fallback for CORS-less LNURL hosts. A proxy breaks the static/no-custody rule and adds an invoice-swap security surface; the platform-fee split is inherently incompatible with a CORS-blocked recipient in a static client; and WebLN's only CORS-bypass (webln.lnurl()) pays directly with no NIP-57 receipt, no split, and no deterministic amount. Current behavior is the right answer. Co-Authored-By: Claude Opus 4.8 --- todo/TODO_2026-06-20_pre-launch.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/todo/TODO_2026-06-20_pre-launch.md b/todo/TODO_2026-06-20_pre-launch.md index 997bbe50..7175a424 100644 --- a/todo/TODO_2026-06-20_pre-launch.md +++ b/todo/TODO_2026-06-20_pre-launch.md @@ -184,13 +184,22 @@ Audit started 2026-06-23. See the doc for architecture map + findings. Summary: few times for a late receipt. See docs/zap-audit-plan.md. - [x] **Platform-fee fallback verified no-bypass** — junk override falls back to the configured fee, not 0. -- [ ] **CORS / LNURL proxy decision** (NEEDS A DECISION — the remaining reliability - fix). A static client can't fetch CORS-less LNURL hosts; options: (a) small - Vercel edge proxy that fetches LNURL pay-data + invoice and returns with CORS - [recommended — what web wallets do]; (b) document the limit / CORS-only hosts; - (c) route LN-address resolution via the connected NWC wallet. See - docs/zap-audit-plan.md. NOTE: with NWC now connecting, re-test how many sends - actually fail on CORS vs were just the NWC bug. +- [x] **CORS / LNURL — DECIDED 2026-06-24: accept graceful degradation, no proxy.** + Keep the visual zappability flag (`walletZappabilityCheck` / + `lnurl-unreachable`) as the honest fallback when a recipient's LNURL host + sends no CORS headers. Rationale: + - Browser-enforced CORS can't be bypassed from page JS; the only universal + fix is a proxy, which **breaks the static/no-custody rule** AND adds a + real security surface (the proxy can swap the returned bolt11 → steal the + zap unless it verifies `description_hash`). Not worth it for a static app. + - The fee/receipt model is **fundamentally incompatible** with a CORS-blocked + recipient in a static client: the platform-fee split needs to fetch the + creator's invoice in-page, which is exactly what CORS blocks. + - WebLN was evaluated and rejected: its only CORS-bypassing primitive + (`webln.lnurl()`) **pays directly** — no NIP-57 receipt, no split, no + deterministic amount — so it degrades a zap into an unattributed tip and + bypasses the platform fee. Not acceptable as a silent fallback. + Net: the current behavior is the right answer for a static, no-custody client. - [ ] **Remaining audit items**: platform-fee split correctness (the earlier "fee landed in my own wallet" report + self-zap / creator==platform edge), receipt validation (9735), NWC budget/retry UX, general clunkiness.