Trust: same-origin checks on every mutation. src/http/origin_gate.ts holds the rule, and today only per-surface tests prove it. #11818 does this for admin-only routes; this is the same walk for the origin.
Done looks like:
[ ] test/origin-walk.test.ts reads the router's table (the way scripts/openapi-routes.ts or the admin walk in #11818 does), sends every POST/PUT/PATCH/DELETE route a cookie-carrying request with a foreign Origin and expects a refusal before any handler work; a bearer-token API route and the named webhook/OAuth callbacks are on one short exclusion list, each with its reason on its line.
[ ] The test fails naming the route when one is added without the gate, and a second assertion fails when an exclusion no longer matches a route (the list only shrinks).
[ ] Any route the walk finds open is fixed in the same pull, or named in the pull with its issue.
Files: test/origin-walk.test.ts, src/http/origin_gate.ts (only to fix a finding)
Risks: the walk must not call a handler with side effects; assert on the refusal only.
Brief: a Sonnet builder (Mason or Scout). Never touch the release workflow or the chart; bun test on the touched tests and bun x tsc --noEmit pass before the push; if scripts/gate.ts still lists tests by hand, add the new test there in the same commit.
Trust: same-origin checks on every mutation.
src/http/origin_gate.tsholds the rule, and today only per-surface tests prove it. #11818 does this for admin-only routes; this is the same walk for the origin.Done looks like:
test/origin-walk.test.tsreads the router's table (the wayscripts/openapi-routes.tsor the admin walk in #11818 does), sends every POST/PUT/PATCH/DELETE route a cookie-carrying request with a foreignOriginand expects a refusal before any handler work; a bearer-token API route and the named webhook/OAuth callbacks are on one short exclusion list, each with its reason on its line.Files: test/origin-walk.test.ts, src/http/origin_gate.ts (only to fix a finding) Risks: the walk must not call a handler with side effects; assert on the refusal only. Brief: a Sonnet builder (Mason or Scout). Never touch the release workflow or the chart;
bun teston the touched tests andbun x tsc --noEmitpass before the push; if scripts/gate.ts still lists tests by hand, add the new test there in the same commit.