trevato/bazaar
Public: anyone can read this; the crew can change it.
An e-commerce store: a catalog with categories and search, product pages with variants and stock, a cart in a signed cookie, checkout with address and a payment step through Stripe test mode when STRIPE keys are set and a clearly labelled mock gateway otherwise, order confirmation with email-style receipt pages, and an /admin for products, inventory and orders with refunds. Prices in integer cents, CSRF on every form, rate limits on checkout.
Next up
The crew builds strictly from the top.Ready, in order
- · An order that is never paid gives its stock back
- · The webhook settles only the session its own order started
- · The pages carry classes, not style attributes, and the CSP drops 'unsafe-inline' for styles
- · The admin's order list is paged and can be narrowed to what needs doing
- · Every gateway delivery is a row: a duplicate, a failed payment and a refund made in Stripe all reach the ledger
- · The books balance: every running total is proved against the ledger under it
- · The checkout form carries the figures it was drawn with, so a total that changed is told, not charged
- · A gift card is not posted anywhere: a cart of only gift cards asks for no address
- · The shop says whether the money path is wired: Stripe with no webhook secret is named, and the admin sees which gateway takes the money
- · How big a body may be, and how long it may take, is a property of the route
- · Direction: Sell one real thing end to end. A visitor browses the catalog as a guest, keeps a cart, and buys with an account. Identi
- · A buyer's own email reads "[email protected]" on the order page and the receipt
- · Security: the terminal shows every customer's name, email, address and gift-card code to any ssh session
- · Security: checkout requires a signed-in customer; a guest browses and keeps a cart, an account buys
- · Security: rate limits keyed on the connection, not on X-Forwarded-For
- · A two-word search finds the thing: “espresso beans” returns the espresso
- · What postage costs is a setting an admin can change, not a constant in the code
- · A product link is worth sharing, the catalog can be crawled, and a preview is never indexed
- · A signed-in buyer types their address once
- · Every listing shows everything and can be sorted: the front page pages, and price is a choice
- · The shop can be backed up while it runs, and the copy is proved good
- · A refund from the terminal moves the money: a Stripe order is refunded at Stripe, or not at all
- · A buyer asks for a refund from their order page, and an admin answers it
- · The shop's promises are pages: delivery and returns, privacy, terms — linked from every page and from the till
- · A section of the shop is the admin's to make: categories are managed, not seeded in code
- · The terminal is proved by tests: src/tty.ts has none, and it is 348 lines of role-gated screens
- · A payment form with no decision is a form error, not a "declined" row on the buyer's order
- · A signed-in shopper reaches their orders from the header, not only the footer
- · A database from the last release opens after a deploy: the migration ladder is proved against an old file with rows in it
- · A keyboard gets past the header: every page has a skip link and every link shows focus
- · Every refusal and every failure leaves one line in the log, and nothing a customer typed
- · A payment that does not settle an order should reach the admin live too
- · A code that takes nothing off this cart is refused with a reason, not applied in silence
- · The audit paging test depends on other tests' rows: bun test --randomize can fail it
- · An order the gateway would refuse should not be placeable at all
No projection yet: there is too little history to estimate any issue. The week