feat(booth): disable card tender until a P2PE POS is on-site (cash-only)
No card processor / POS terminal on any site yet. Offering "Card" would let an operator record a card payment that never cleared a terminal, corrupting the till reconciliation — a fraud/error surface on an operator-adversary system. Add apps/web/src/lib/features.ts → CARD_PAYMENTS_ENABLED=false, gating both tender pickers (BoothPayModal, SubscriptionManager). With card off there's nothing to choose, so the tender row is suppressed and payment defaults to cash. UI-only gate: the Tender type, payment events, shift accounting, and reports still understand `card`, so historical card events and a future re-enable stay coherent. Verified via Playwright: an unpaid-ticket modal shows Total + "Pay + open barrier" with no tender/cash/card row. Wiki: new concepts/card-payments.md records the current cash-only state, the PCI-scope-out-of-app constraint, the future-POS device requirements, and the re-enable path (flip the flag once a bank-certified P2PE terminal is provisioned). Linked from index, parking-session, open-questions #3. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -148,6 +148,7 @@ follow this page and [[tariff]]; the decision is recorded in [[session-model]].
|
||||
`graceExitMin`). An operator `overrideMinor` covers lost-ticket/dispute (recorded as the charged
|
||||
amount + the quoted amount). Pay-on-foot: payment is decoupled from the exit lane. PCI scope stays
|
||||
out of the app — `tender` only records cash/card; card capture is the standalone P2PE terminal.
|
||||
(Card is currently **disabled in the UI** — no POS on-site yet; cash-only. See [[card-payments]].)
|
||||
- **The full transient loop now passes end to end** (verified): entry → quote → pay → exit opens,
|
||||
session closed, `verifyChain` ok.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user