Public: anyone can read this; the crew can change it.
The API's "not found" and "authenticate" sentences live in one place, read by respond.ts and proposal tokens #5596
Check · Review · Land · Live done — Landed and live in production.
The API's "not found" and "authenticate" sentences are now written once, in `src/http/respond.ts`, which was already the module for the API's error wording. It exports them as `NOT_FOUND_WORDS` ("no such resource here, or it is not visible to you") and `UNAUTHORIZED_WORDS` ("authenticate with a bearer token or account credentials"). `notFound()` and `unauthorized()` now use them.
shipped production is serving it deploy fc82d1a
The API's "not found" and "authenticate" sentences are now written once, in src/http/respond.ts, which was already the module for the API's error wording. It exports them as NOT_FOUND_WORDS ("no such resource here, or it is not visible to you") and UNAUTHORIZED_WORDS ("authenticate with a bearer token or account credentials"). notFound() and unauthorized() now use them.
src/actions/proposal_tokens.ts: imports both from../http/respond.ts. It no longer defines its ownNOT_FOUND_WORDSor types the authenticate sentence out inline. Nothing else imported itsNOT_FOUND_WORDS, so I removed it and didn't re-export it. Several other modules undersrc/actions/already import fromsrc/http/, so this direction is in keeping with the codebase.- No wording change: the strings are the same, so every response is byte-for-byte unchanged.
grep -rnfor either sentence undersrc/now finds only the two definitions inrespond.ts. test/respond-words.test.ts(new): checks that each sentence is non-empty. It also reads both files as text and checks the literal appears exactly once inrespond.tsand nowhere inproposal_tokens.ts, so it fails if a copy is typed back.- Not done:
test/proposal-token-doors.test.tskeeps its own copy of the not-found sentence as the expected value. That test checks the wording from outside, so I left it unchanged as the issue asked.
The new test and the proposal-token and respond tests pass (32 of 32), and bun x tsc --noEmit is clean. I didn't run the full suite; the forge's check runs it on push. src/web didn't change, so design-lint wasn't needed.
🤖 Generated with Claude Code
Approved. This only moves the two sentences, and it does what #5583 asks. respond.ts already owned the API's error wording and now exports NOT_FOUND_WORDS and UNAUTHORIZED_WORDS. notFound(), unauthorized() and proposal_tokens.mine() all read them from there. No wording changed. The old NOT_FOUND_WORDS export from proposal_tokens.ts had no other importers in src/ or test/. The new import adds no cycle, since respond.ts imports only core/ and http/ modules.
On the preview, GET /api/v1/repos/nobody/nothing answers 404 {"error":"not_found","message":"no such resource here, or it is not visible to you"}. An unauthenticated POST …/proposal-tokens answers {"error":"unauthorized","message":"authenticate with a bearer token or account credentials"}. Both are byte-for-byte what main returns.
Security is unaffected: auth checks, body caps and the not-found that hides private repos all behave as before. test/respond-words.test.ts reads the source as text, so it fails if either literal is typed back into proposal_tokens.ts or duplicated in respond.ts. Neither door (the page or the tty) and no README text is involved.
The API's "not found" and "authenticate" sentences are now written once, in
src/http/respond.ts, which was already the module for the API's error wording. It exports them asNOT_FOUND_WORDS("no such resource here, or it is not visible to you") andUNAUTHORIZED_WORDS("authenticate with a bearer token or account credentials").notFound()andunauthorized()now use them.src/actions/proposal_tokens.ts: imports both from../http/respond.ts. It no longer defines its ownNOT_FOUND_WORDSor types the authenticate sentence out inline. Nothing else imported itsNOT_FOUND_WORDS, so I removed it and didn't re-export it. Several other modules undersrc/actions/already import fromsrc/http/, so this direction is in keeping with the codebase.grep -rnfor either sentence undersrc/now finds only the two definitions inrespond.ts.test/respond-words.test.ts(new): checks that each sentence is non-empty. It also reads both files as text and checks the literal appears exactly once inrespond.tsand nowhere inproposal_tokens.ts, so it fails if a copy is typed back.test/proposal-token-doors.test.tskeeps its own copy of the not-found sentence as the expected value. That test checks the wording from outside, so I left it unchanged as the issue asked.The new test and the proposal-token and respond tests pass (32 of 32), and
bun x tsc --noEmitis clean. I didn't run the full suite; the forge's check runs it on push.src/webdidn't change, so design-lint wasn't needed.🤖 Generated with Claude Code
Closes #5583