Public: anyone can read this; the crew can change it.
The claim page says when its link stops working and how to get another, in plain words #11349
Check · Review · Land · Live done — Landed and live in production.
The claim page now says when its link stops working, and a dead link now answers 410 with a plain line on why and who can send another. The new test file and the existing claim tests pass (37 tests) and `tsc` is clean. I haven't run the rest of the suite (the forge runs the full check on push). `design-lint` printed its OK line; `scripts/gate.ts` printed nothing, so I don't know it ran.
shipped production is serving it deploy eb2664b
The claim page now says when its link stops working, and a dead link now answers 410 with a plain line on why and who can send another. The new test file and the existing claim tests pass (37 tests) and tsc is clean. I haven't run the rest of the suite (the forge runs the full check on push). design-lint printed its OK line; scripts/gate.ts printed nothing, so I don't know it ran.
What changed
- Valid link:
GET /claim(src/web/pages/claim.ts) shows "This link works until<time>Nov 12, 14:30 UTC (in 23 hours). After that, ask alice to send you a new one." The server renders it, and the date and the relative time both come from the stored expiry. - Dead link: an expired or used link now answers 410 on both
GET /claimandPOST /claim. The text says why and names the spawner, for example "It stopped working on Nov 10, 09:00 UTC. Ask alice to send you a new one." The revoked link also names the spawner. src/spawn/claim.ts:linkOfnow also returnsexpiresAt.- Tests:
test/claim-page-words.test.tscovers valid, expired and used links. The expired and used cases assert the plain wording and that the page has no "token" or 4xx number.
Decisions
- The
GETcan't see which code a visitor holds, because the code lives in the#fragment. So it answers from the forge's single current link: open shows the expiry, and expired, used or revoked shows the 410. That says nothing about any particular code. - A made-up code on
POST /claimstill gets the same 404 "not a forge link" as before, so nobody can learn whether a code ever existed. - A forge that already has an admin and no recorded link still shows the form on
GET. I left that alone becauseclaim-timing.test.tsrelies on it.
Try it: spawn a forge and open /claim. To see the 410, set the stored link's e to a past time and reload.
I added an empty Try: commit because the pre-push hook asked for one.
🤖 Generated with Claude Code
The two failing tests didn't come from the claim change, and they pass here after I merged current main into the branch and pushed. I haven't seen the forge's check re-run on this push yet.
job-slices: it failed becausesrc/main.tsruns anentitlementsjob underduringthat the test hadn't listed. That job isn't part of my change, and the test passes now thatmainis merged in.past its deep budget(intest/crawl-budget.test.ts): it passes here; I only ran it after the merge, so I didn't reproduce the failure. I didn't change anything it covers, so I'm treating it as a one-off from the shard run.
After the merge, the claim tests (test/claim-page-words.test.ts and test/claim-link.test.ts) pass, and tsc is clean. The claim page change itself is unchanged: it shows the expiry on a valid link and gives a plain 410 for an expired or used one.
Approved. The valid page shows a date and a relative time in a <time> element, server-rendered and fine without JavaScript. Expired and used links answer 410 on GET and POST in plain words and name who to ask. The made-up-code 404 is kept, so nobody learns whether a code ever existed. The new tests cover valid, expired and used links. The preview forge is not a spawned one, so I could not see the expiry line live and judged it from the source and tests. Two things to do next: (1) add a test for the revoked wording and for the 422 re-render, which now also passes expiresAt and is untested; (2) the tests share one mutable stored link and depend on running in order, so reset it per test.
The claim page now says when its link stops working, and a dead link now answers 410 with a plain line on why and who can send another. The new test file and the existing claim tests pass (37 tests) and
tscis clean. I haven't run the rest of the suite (the forge runs the full check on push).design-lintprinted its OK line;scripts/gate.tsprinted nothing, so I don't know it ran.What changed
GET /claim(src/web/pages/claim.ts) shows "This link works until<time>Nov 12, 14:30 UTC (in 23 hours). After that, ask alice to send you a new one." The server renders it, and the date and the relative time both come from the stored expiry.GET /claimandPOST /claim. The text says why and names the spawner, for example "It stopped working on Nov 10, 09:00 UTC. Ask alice to send you a new one." The revoked link also names the spawner.src/spawn/claim.ts:linkOfnow also returnsexpiresAt.test/claim-page-words.test.tscovers valid, expired and used links. The expired and used cases assert the plain wording and that the page has no "token" or 4xx number.Decisions
GETcan't see which code a visitor holds, because the code lives in the#fragment. So it answers from the forge's single current link: open shows the expiry, and expired, used or revoked shows the 410. That says nothing about any particular code.POST /claimstill gets the same 404 "not a forge link" as before, so nobody can learn whether a code ever existed.GET. I left that alone becauseclaim-timing.test.tsrelies on it.Try it: spawn a forge and open
/claim. To see the 410, set the stored link'seto a past time and reload.I added an empty
Try:commit because the pre-push hook asked for one.🤖 Generated with Claude Code
Closes #11339