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:
+14
@@ -2074,3 +2074,17 @@ DATABASE_URL=/data/parking.sqlite); the script ships in the deploy bundle next t
|
||||
(@parking/db has no `files` allowlist → whole pkg copied). Verified on throwaway dev-DB copies (both
|
||||
gates refuse correctly; each flag wipes/keeps the right tables; real dev DB never touched). Recorded
|
||||
in local-dev-workflow.md + appliance-provisioning.md §7d.
|
||||
|
||||
## [2026-07-01] feat | Card tender DISABLED until a P2PE POS is on-site (cash-only)
|
||||
|
||||
No card processor / POS terminal on any site yet, so offering "Card" would let an operator record a
|
||||
card payment that never cleared → corrupts till reconciliation ([[threat-model]] surface). Disabled
|
||||
the card option in the UI: new apps/web/src/lib/features.ts → CARD_PAYMENTS_ENABLED=false gates both
|
||||
tender pickers (BoothPayModal.tsx, SubscriptionManager.tsx); with card off there's nothing to choose,
|
||||
so the tender row is suppressed entirely and payment silently defaults to cash. UI-only gate — the
|
||||
Tender="cash"|"card" type, payment events, shift accounting, and reports still understand card (so
|
||||
historical card events + a future re-enable stay coherent). Verified via Playwright: an unpaid-ticket
|
||||
modal shows Total + "Pay + open barrier" with NO tender/cash/card row. Re-enable = flip the flag once
|
||||
a bank-certified P2PE terminal is provisioned (PCI scope stays out of the app — the terminal captures
|
||||
card data, not the app). New page concepts/card-payments.md documents current state + future-POS
|
||||
device requirements + re-enable path; linked from index, parking-session, open-questions #3.
|
||||
|
||||
Reference in New Issue
Block a user