fix(cart): production's demo checkout button is not labelled as a demo #195

Closed
opened 2026-08-27 11:07:29 -05:00 by bermudalamb · 0 comments
Owner

Production is in demo mode as the interim from #190/#191, and in that exact configuration the storefront shows a full-width primary button reading plainly Checkout. Not Checkout (Demo). A real customer has no way to tell the order is pretend.

The label is gated the wrong way round. frontend/src/cart/Cart.tsx:248 reads:

{config.paypalClientId ? 'Checkout (Demo)' : 'Checkout'}

So the (Demo) suffix appears only when a PayPal client id is present — the case where the demo button sits beside real PayPal buttons and is obviously the secondary option. Production has no PayPal credentials, which is the entire reason DEMO_MODE was turned on, so app.ts:48 returns paypalClientId: null and the one case that actually needs the label is the one case that does not get it. The type prop is gated identically, so it is also promoted to primary.

What clicking it does, against live data, via POST /demo/purchasecompleteCheckout (backend/src/routes/cartCheckout.ts:179-202):

  • UPDATE items SET status = 'sold', sold_at = now() — the item is genuinely withdrawn from the shop.
  • INSERT INTO orders (..., amount_cents, status) VALUES (..., 'completed') — a completed order at the real price, distinguishable from a real one only by processor = 'demo'.
  • notifyFavoritersOfSale — real "it sold" emails to real customers, through production's configured Brevo SMTP.

The compose banner added in #191 says "NOBODY IS EVER CHARGED ... every order placed is a pretend one". Both halves are true, and neither is the risk. #190, #191 and #192 all reason carefully about not charging by accident and none of them consider accepting orders by accident, which is what this configuration actually does. The failure is not financial, it is that a customer places an order they believe is real, the inventory says sold, other customers are emailed about the sale, and nobody is expecting to ship anything.

Fix

Make the label and the button type unconditional whenever demoMode is on — the demo button should say so whether or not PayPal is configured. Whatever the storefront tells the customer after the click should be checked against the same standard while we are in here.

Found by

Code review of the #190/#191/#192 cutover range (5f21d97..fdb5b7a), raised as Critical 1. Verified against source: Cart.tsx:240-249, app.ts:45-50, cartCheckout.ts:179-260.

Urgent while production stays in demo mode.

Production is in demo mode as the interim from #190/#191, and in that exact configuration the storefront shows a full-width primary button reading plainly **`Checkout`**. Not `Checkout (Demo)`. A real customer has no way to tell the order is pretend. The label is gated the wrong way round. `frontend/src/cart/Cart.tsx:248` reads: ```tsx {config.paypalClientId ? 'Checkout (Demo)' : 'Checkout'} ``` So the `(Demo)` suffix appears only when a PayPal client id is present — the case where the demo button sits beside real PayPal buttons and is obviously the secondary option. Production has no PayPal credentials, which is the entire reason `DEMO_MODE` was turned on, so `app.ts:48` returns `paypalClientId: null` and the one case that actually needs the label is the one case that does not get it. The `type` prop is gated identically, so it is also promoted to `primary`. What clicking it does, against live data, via `POST /demo/purchase` → `completeCheckout` (`backend/src/routes/cartCheckout.ts:179-202`): - `UPDATE items SET status = 'sold', sold_at = now()` — the item is genuinely withdrawn from the shop. - `INSERT INTO orders (..., amount_cents, status) VALUES (..., 'completed')` — a completed order at the real price, distinguishable from a real one only by `processor = 'demo'`. - `notifyFavoritersOfSale` — real "it sold" emails to real customers, through production's configured Brevo SMTP. The compose banner added in #191 says "NOBODY IS EVER CHARGED ... every order placed is a pretend one". Both halves are true, and neither is the risk. #190, #191 and #192 all reason carefully about not *charging* by accident and none of them consider *accepting orders* by accident, which is what this configuration actually does. The failure is not financial, it is that a customer places an order they believe is real, the inventory says sold, other customers are emailed about the sale, and nobody is expecting to ship anything. ## Fix Make the label and the button type unconditional whenever `demoMode` is on — the demo button should say so whether or not PayPal is configured. Whatever the storefront tells the customer after the click should be checked against the same standard while we are in here. ## Found by Code review of the #190/#191/#192 cutover range (`5f21d97..fdb5b7a`), raised as Critical 1. Verified against source: `Cart.tsx:240-249`, `app.ts:45-50`, `cartCheckout.ts:179-260`. Urgent while production stays in demo mode.
bermudalamb self-assigned this 2026-08-27 11:29:11 -05:00
bermudalamb added this to the Code Quality and Hardening 2 project 2026-08-27 11:29:21 -05:00
bermudalamb added reference feature/195-demo-checkout-label 2026-08-27 17:03:23 -05:00
bermudalamb moved this to Review in Code Quality and Hardening 2 on 2026-08-27 17:03:31 -05:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bermudalamb/redefined-designs#195