mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-04 11:52:25 +00:00
- docs/zap-audit-plan.md: architecture map, findings (LNURL CORS send-error, comment box confirmed working, popover mis-position), and prioritized next steps (CORS/LNURL proxy decision first, then popover, fee-split correctness, receipt validation, NWC UX). Notes the injectable-fetcher/deps test seams. - TODO #3 points to the doc; #9 adds two unverified learnings: confirm the community-blacklist batching actually dropped the kind-30000 storm (still saw =32 in a later load), and trace the `from_hex` malformed-hex source via the new sanitizer dev-log. Planning/docs only. Co-Authored-By: Claude Opus 4.8 <[email protected]>
4.1 KiB
4.1 KiB
Zap System Audit — Plan & Findings
Status: in progress (audit started 2026-06-23). Branch: unstable.
Pre-launch priority #3. The zap flow feels clunky and errors on send.
Architecture (map for the next session)
- Two controllers:
js/ui/components/video-modal/zapController.js(the in-modal UI — button, popover, comment/amount inputs; dispatchesvideo:zap/zap:open) andjs/ui/zapController.js(the logic —open(),sendZap(), retry, receipts).ModalManagerwiresvideo:zap → zapController.sendZap. - Payment flow:
sendZap→splitAndZap(js/payments/zapSplit.js) → per share (creator,platform)processShare→lnurl.fetchPayServiceData→buildZapRequest(kind 9734, comment incontent) →lnurl.requestInvoice(nostr=zapRequest + optionalcomment=param) →wallet.sendPayment(NWC,nwcClient.js) →zapReceiptValidator(kind 9735). - Fee split:
PLATFORM_FEE_PERCENT(instance-config, currently 30) →platformShare = floor(amount*fee/100),creatorShare = amount - platformShare; platform address viaplatformAddress.js/PLATFORM_LUD16_OVERRIDE.
Findings so far
- Send error = recipient LNURL unreachable (CORS/offline). [PARTLY FIXED]
Sending to a creator whose LNURL host is down or lacks CORS headers (observed:
unitypay.cash/.well-known/lnurlp/goblinbox) makes the browserfetchreject with "Failed to fetch". Shipped (dd1ce113):fetchPayServiceDatanow throws a clear, coded (lnurl-unreachable) message. Root issue remains: a static client CANNOT fetch CORS-less LNURL hosts — see "CORS proxy" below. - Comment box works. Confirmed via screenshot — the textarea renders and binds;
the comment is carried in the zap-request
content+ the LNURLcommentparam. The earlier "message doesn't work" was the popover being mis-positioned/hard to use (see 3a), not a comment bug. - Popover mis-positioning (zap + embed) — see TODO 3a; shared
popoverEngine.
To do (next session, in priority order)
- CORS / LNURL proxy decision (the real reliability fix). A static client
can't fetch LNURL endpoints that omit CORS headers, so zaps to many creators
fail. Options: (a) a small server-side/edge proxy (Vercel function) that fetches
the LNURL pay-service data + invoice and returns it with CORS — what most web
wallets do; (b) document the limitation and only support CORS-enabled hosts;
(c) route via the connected NWC wallet if it can resolve LN addresses. Decide,
then implement. Confirm whether
unitypay.cashis also just offline. - Popover positioning (3a). Fix the shared engine safely (portal in-modal
panels out to
#uiOverlay, or remove the modal-subtree containing block). Needs the live computedposition/left/top+ DOM parent of#modalZapDialog. VERIFY non-modal popovers still position right after. - Platform-fee split correctness. Verify recipients/percentages/rounding; ensure the fee can't swallow the whole zap, be bypassed, or (earlier report) land the platform fee in the sender's own wallet when zapping certain targets. Check the self-zap / creator==platform edge case. Add cheat-resistant tests.
- Receipt validation (kind 9735). Confirm accuracy before crediting; the
unvalidatedReceipts/failureReceiptspaths and the "Awaiting validated zap receipt" state. (Earlier fix:zapReceiptValidatorSimplePool.listshim.) - NWC error UX. "Budget exceeded" and partial-share retry flow — make the messaging + retry obviously usable (it's currently terse).
- General clunkiness. Step back on the whole flow: amount presets, the split summary, success/partial/failure states, focus, and mobile.
Cheat-resistant testing notes
fetchPayServiceData/requestInvoiceaccept an injectablefetcher— test failure modes by injecting rejecting/erroring fetchers (seetests/lnurl-fetch-error.test.mjs).splitAndZaptakes injectabledependencies(seetests/zap-split.test.mjs) — use it to assert fee math, rounding, and recipient routing without real LN.