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

Sign-up's username and taken-email sentences live in one module, read by every way an account is made #5608

Merged opened this

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

Merged

The two sign-up sentences now come from one new module, `src/actions/signup_words.ts`, which exports `INVALID_USERNAME_MESSAGE` ("Usernames are letters, digits, dots and dashes.") and `EMAIL_TAKEN_MESSAGE` ("That email already has an account."). No existing module owned these words: `actions/signup.ts` holds signup-policy settings, not refusal sentences. So this is a new module.

shipped production is serving it deploy 45be4c2

opened this

The two sign-up sentences now come from one new module, src/actions/signup_words.ts, which exports INVALID_USERNAME_MESSAGE ("Usernames are letters, digits, dots and dashes.") and EMAIL_TAKEN_MESSAGE ("That email already has an account."). No existing module owned these words: actions/signup.ts holds signup-policy settings, not refusal sentences. So this is a new module.

What moved:

  • src/actions/first_admin.ts (FIRST_ADMIN_WORDS) and src/web/pages/signup-passkey.ts (WORDS) import both sentences.
  • src/web/pages/claim.ts, src/web/pages/everyday.ts and src/web/pages/site.ts import the taken-email sentence.
  • Each file changes only the lines the sentences were on, plus one import line. The wording is unchanged, so answers and pages are byte-for-byte the same.
  • grep -rn under src/ now finds each sentence only in signup_words.ts.

What I chose not to do: site.ts has its own username sentence with different wording, "Usernames are letters, digits, dots, dashes." (no "and"). The issue says to change no wording, so I left it as it is. Pointing it at the shared constant would change the sign-up page's text, and it should be a separate issue if wanted.

Test: the new test/signup-words.test.ts checks that each exported sentence is non-empty. It also reads each of the five files as text and checks that none contains either sentence and that each imports signup_words.ts. If a copy is typed back, it fails.

Checks run before pushing:

  • bun x tsc --noEmit is clean.
  • bun scripts/design-lint.ts is clean.
  • bun test passed 94 of 94 across the new test and the first-admin, claim-link, everyday, signup, signup-passkey, signup-password and forge-signin-signup suites, with none failing.

To try it: bun test test/signup-words.test.ts, then grep -rn "That email already has an account" src/.

🤖 Generated with Claude Code

Closes #5592

commented

The two sign-up sentences now come from one new module, src/actions/signup_words.ts, which exports INVALID_USERNAME_MESSAGE ("Usernames are letters, digits, dots and dashes.") and EMAIL_TAKEN_MESSAGE ("That email already has an account."). No existing module owned these words: actions/signup.ts holds signup-policy settings, not refusal sentences. So this is a new module.

What moved:

  • src/actions/first_admin.ts (FIRST_ADMIN_WORDS) and src/web/pages/signup-passkey.ts (WORDS) import both sentences.
  • src/web/pages/claim.ts, src/web/pages/everyday.ts and src/web/pages/site.ts import the taken-email sentence.
  • Each file changes only the lines the sentences were on, plus one import line. The wording is unchanged, so answers and pages are byte-for-byte the same.
  • grep -rn under src/ now finds each sentence only in signup_words.ts.

What I chose not to do: site.ts has its own username sentence with different wording, "Usernames are letters, digits, dots, dashes." (no "and"). The issue says to change no wording, so I left it as it is. Pointing it at the shared constant would change the sign-up page's text, and it should be a separate issue if wanted.

Test: the new test/signup-words.test.ts checks that each exported sentence is non-empty. It also reads each of the five files as text and checks that none contains either sentence and that each imports signup_words.ts. If a copy is typed back, it fails.

Checks run before pushing:

  • bun x tsc --noEmit is clean.
  • bun scripts/design-lint.ts is clean.
  • bun test passed 94 of 94 across the new test and the first-admin, claim-link, everyday, signup, signup-passkey, signup-password and forge-signin-signup suites, with none failing.

To try it: bun test test/signup-words.test.ts, then grep -rn "That email already has an account" src/.

🤖 Generated with Claude Code

Approved — before the latest push

Approved. The two sentences now live in src/actions/signup_words.ts and are read by the five places that said them. The wording is unchanged, so no page or JSON answer changes, and the preview / answers 200. I read the diff and hit the preview root only; I did not run the tests. The security floor, both doors and the design system are untouched, since only message constants moved. Two things I would do next: (1) site.ts keeps its own username sentence ("dots, dashes", no "and"). Pick one wording in a separate pull so the sign-up page matches the passkey and first-admin doors. Claim/everyday/site also keep their other refusal sentences (username taken, reserved) inline. (2) The test greps source text for the sentences, which is brittle. A test that drives each door to email_taken and compares the answer to EMAIL_TAKEN_MESSAGE would pin the behaviour instead.

commented

Sign-up's invalid-username and taken-email sentences now live in one place, src/actions/signup_words.ts. Every way an account is made reads them from there (#5592).

This push merges main into the branch. The only conflict was in the imports of src/web/pages/signup-passkey.ts: this branch imports EMAIL_TAKEN_MESSAGE and INVALID_USERNAME_MESSAGE from signup_words.ts, and main added PASSKEY_EXPIRED, PASSKEY_REJECTED and PASSKEY_TAKEN from src/web/passkey-words.ts. The file uses all five, so it keeps both imports. src/web/pages/site.ts merged without a conflict.

The type check is clean, and the 91 sign-up, passkey and TUI sign-up tests pass, across 19 files. The full check was not run here; the forge runs it on this push.

🤖 Generated with Claude Code

Approved

Pure refactor: the two sentences move to src/actions/signup_words.ts, the five readers import them, wording is unchanged, and the preview answers 200. No input, auth or markup changes, so the security and design lists are not touched. Two next steps: (1) the username sentence still has a second wording, "letters, digits, dots, dashes.", in site.ts, claim.ts, everyday.ts and crew.ts. Open an issue to pick one wording and point all of them at the constant. (2) The source-text test only checks the two exact strings, so it will not catch a drifted variant like that one. A behaviour test per door that asserts the refusal text would hold up better.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs