shop.orderPage calls settleStripe, which does a fetch to Stripe inside a GET, with a fifteen-second timeout. A shopper coming back from Checkout on a phone can wait on someone else's network before the first byte of their receipt, and every refresh of a pending order asks again. The bar is milliseconds on the common request, and the webhook is the path that is meant to carry this news.
Done looks like
[ ] GET /orders/:number makes no network call. It renders from the database, and a pending_payment order holding a cs_ reference says in plain words that the payment is being confirmed and that the page can be reloaded.
[ ] The confirmation is still asked for on the return, but off the render path: either the response is sent and the settle runs after it — the shape AGENTS.md asks for, "work that can wait is done after the response" — or Stripe returns to a POST that settles and redirects. Pick one, and say in the pull why.
[ ] A settle attempt is bounded at about three seconds, and at most one is in flight per order: a shopper hammering reload does not open ten sockets to Stripe.
[ ] A failed or refused attempt is an order_event, never a 500 and never a blank page.
[ ] An order whose webhook never arrives still settles — by the sweep #15 adds or by one attempt on the next visit, whichever the pull chooses, and the choice has a test.
[ ] The single settlement function #31 and #33 land stays the only thing that writes a charge; nothing about their rules is loosened to make this easier.
[ ] Tests, with the fake Stripe #14 already put in the suite: the order page answers in milliseconds while the fake holds its reply for a second; two returns at once write one charge; a Stripe that never answers leaves the order pending, with an event and a page that says so.
Files I expect to change:src/shop.ts, src/orders.ts, src/gateway.ts, src/pages/checkout.ts, src/stripe.test.ts.
Risks: this must not grow into a job framework — one process, work after the response, no queue and no dependency. It waits on #31 and #33 because all three rewrite the same settlement path, and taking this one first would put the other two in conflict.
shop.orderPagecallssettleStripe, which does afetchto Stripe inside a GET, with a fifteen-second timeout. A shopper coming back from Checkout on a phone can wait on someone else's network before the first byte of their receipt, and every refresh of a pending order asks again. The bar is milliseconds on the common request, and the webhook is the path that is meant to carry this news.Done looks like
GET /orders/:numbermakes no network call. It renders from the database, and apending_paymentorder holding acs_reference says in plain words that the payment is being confirmed and that the page can be reloaded.AGENTS.mdasks for, "work that can wait is done after the response" — or Stripe returns to a POST that settles and redirects. Pick one, and say in the pull why.order_event, never a 500 and never a blank page.Files I expect to change:
src/shop.ts,src/orders.ts,src/gateway.ts,src/pages/checkout.ts,src/stripe.test.ts.Risks: this must not grow into a job framework — one process, work after the response, no queue and no dependency. It waits on #31 and #33 because all three rewrite the same settlement path, and taking this one first would put the other two in conflict.
Suggested: ledger.