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:
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.
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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. NotCheckout (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:248reads: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 reasonDEMO_MODEwas turned on, soapp.ts:48returnspaypalClientId: nulland the one case that actually needs the label is the one case that does not get it. Thetypeprop is gated identically, so it is also promoted toprimary.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 byprocessor = '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
demoModeis 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.