Public: anyone can read this; the crew can change it.
Every refusal at the front door is a page of the shop, with a way back #88
Check · Review · Land · Live done — Landed and live in production.
`src/pages/oops.ts` is new: a status and a sentence in, a page of this shop out — header, stylesheet, what happened in a person's words, and a way out of it. Every refusal `src/server.ts` makes now goes through it (cross-site `403`, stale-form `403`, `415`, `400`, `413`, `408`, `500`), and `shop.tooMany`'s `429`, which had a page of its own, shares it. The refusal sentences live in one table at th…
shipped production is serving it deploy ab962da
Sign in to join this conversation.
src/pages/oops.tsis new: a status and a sentence in, a page of this shop out — header, stylesheet, what happened in a person's words, and a way out of it. Every refusalsrc/server.tsmakes now goes through it (cross-site403, stale-form403,415,400,413,408,500), andshop.tooMany's429, which had a page of its own, shares it. The refusal sentences live in one table at the top ofsrc/server.tsso all seven can be read at once.Machine callers are untouched:
src/http.tsgainswantsHtml(), and a caller whoseacceptdoes not mentiontext/htmlgets exactly the line it got before (forbidden,expected a form,that body was too large, …), whilePOST /webhooks/stripe— the one raw route — answers plain text however it asks. The stale-form page links to/cartand/and still sets the session cookie, so going back and sending the form again succeeds rather than failing the same way twice; there is a test that does exactly that. The500page says the shop failed and nothing else — no message, no path, no stack — andconsole.errorkeeps the exception whole. Everything still leaves throughfinish(), so the security floor andcache-control: no-storeare on a refusal like any other response.Worth a look in the preview:
POSTa form with a stale token (or open a tab, wait for the session to roll, and submit) — the page should carry your cart count in the header and both links. Six new tests insrc/server.test.tscover each refusal; all six fail onmainand the suite is 142 green, including--randomize. The one test seam worth reviewing: the500test lends/searcha handler that throws and gives it back in afinally, because a 500 has no other door. What I did not do:/admin/events's own403and the webhook's400s are handler answers to machine callers and stay plain text, and no dependency was added.🤖 Generated with Claude Code
Closes #45