Public: anyone can read this; the crew can change it.

A test pins resending the email-verification link: throttled, capped, and honest when already verified #7040

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`POST /settings/email/verify` now has a test, `test/settings-email-verify.test.ts`, and the test found one bug, which this pull also fixes. The new test and `bun x tsc --noEmit` pass here. I did not run the rest of the suite; the forge's check does that on push.

shipped production is serving it deploy 2fa0c24

opened this

POST /settings/email/verify now has a test, test/settings-email-verify.test.ts, and the test found one bug, which this pull also fixes. The new test and bun x tsc --noEmit pass here. I did not run the rest of the suite; the forge's check does that on push.

The fix. A signed-out press used to redirect to /settings with the flash "The link could not be sent. Try again." resendVerifyLink in src/web/pages/account.ts was the only handler in that file that skipped the signInFirst(ctx) guard its siblings use. It now has the guard, so a signed-out press redirects to /signin?next=….

What the test covers. Each case posts an empty urlencoded form the way the page does, with the forge_session cookie and a same-origin Origin header.

  • Unverified: an unverified person gets "A new link is on its way." and one mail goes out. A second press at once gets the too_soon message, and no second mail is sent.
  • Verified: a verified person gets "Your email is already verified." and no mail is sent.
  • No mail set up: a second app with no mailer answers "This forge sends no mail yet. Ask its owner to verify you."
  • Refused: a signed-out press goes to sign-in and no mail is sent. A cross-origin post gets 403 and no mail is sent.

Left out. The capped and failed messages have no case, because the issue didn't ask for them.

I did not run scripts/design-lint.ts, because nothing under src/web/ that renders changed.

Closes #7025

commented

POST /settings/email/verify now has a test, test/settings-email-verify.test.ts, and the test found one bug, which this pull also fixes. The new test and bun x tsc --noEmit pass here. I did not run the rest of the suite; the forge's check does that on push.

The fix. A signed-out press used to redirect to /settings with the flash "The link could not be sent. Try again." resendVerifyLink in src/web/pages/account.ts was the only handler in that file that skipped the signInFirst(ctx) guard its siblings use. It now has the guard, so a signed-out press redirects to /signin?next=….

What the test covers. Each case posts an empty urlencoded form the way the page does, with the forge_session cookie and a same-origin Origin header.

  • Unverified: an unverified person gets "A new link is on its way." and one mail goes out. A second press at once gets the too_soon message, and no second mail is sent.
  • Verified: a verified person gets "Your email is already verified." and no mail is sent.
  • No mail set up: a second app with no mailer answers "This forge sends no mail yet. Ask its owner to verify you."
  • Refused: a signed-out press goes to sign-in and no mail is sent. A cross-origin post gets 403 and no mail is sent.

Left out. The capped and failed messages have no case, because the issue didn't ask for them.

I did not run scripts/design-lint.ts, because nothing under src/web/ that renders changed.

Approved

Approved. The guard matches its sibling handlers, and the preview shows it: a signed-out POST to /settings/email/verify with a same-origin Origin answers 303 to /signin?next=%2Fsettings%2Femail%2Fverify. The test would fail without the fix, because the old flash would be set, and it also covers unverified, throttled, already-verified, no-mailer and cross-origin. No src/web markup changed, so the design system is untouched.

Two things I would do next:

  1. Make the sign-in next for a POST-only path land somewhere that renders (/settings). After sign-in, next=/settings/email/verify becomes a GET on a POST-only route.
  2. Add capped and failed cases so every message in resendVerifyLink is pinned.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs