Repository navigation
Refuse a participant name of only spaces on sign-up and edit - #545
Conversation
NameSchema checked min(1) before trimming, so " " passed and was stored blank on sign-up, and the edit page skipped it and said "Saved." It now trims first, the way EmailSchema does, so both refuse it with invalid_input on name, as a move already did. The move's own re-check is now redundant and goes. The sign-up dialog and the edit page show "Enter your name, up to 100 characters." for that error instead of the validator's text. Fixes #515. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W25bvopySXe58SR1eCv6Qh
Tophat: passedI ran 86ab04f locally with
UX: participants see one new message. When the sign-up dialog or the edit page refuses a name (only spaces, or longer than 100 characters), they see "Enter your name, up to 100 characters." This replaces the validator text in the dialog, and the false "Saved." on the edit page. API callers and MCP clients now get a 400 for a spaces-only name, where before it was stored blank. The base-and-head screenshot pairs show the change: Screenshots are in https://claude.ai/code/session_01PHChS19UH8onuBt22xk69S. Generated by Claude Code |
richshaw
left a comment
There was a problem hiding this comment.
Review: passed (round 1)
The PR fixes #515 the way the issue outlines. NameSchema (src/schemas/common.ts:23) now trims and then checks min(1) through a .pipe, as EmailSchema does, so " " is refused on sign-up and on edit. The issue path stays ['name'], so fromZodError sets field: 'name', api-response.ts passes it to the client, and both commit-dialog.tsx and edit-form.tsx already send the error through participantErrorCopy, which now maps it to NAME_INVALID. Removing MoveNameSchema is safe: CommitmentUpdateInputSchema uses the same NameSchema.optional(), so a move that sends a blank name is refused by the edit schema before anything is written, and a move that sends no name still skips the check (the DB test for a stored blank name now creates that row directly). The length limit is still on the raw string, as before, so no name that passed before is refused for length now. organizerDisplayName follows the new rule, and no column stores it (the MCP tool omits it for that reason), so no existing row can start failing a settings save. Every "Done when" item is covered.
Blocking (0)
Optional (1):
- 🟡 The comment above
errorTextinsrc/app/s/[slug]/commit-dialog.tsx:339-342lists which errors get their own copy and doesn't mention a refused name yet. If another push comes, add it there.
Earlier threads: none. Copilot couldn't review (quota).
Checks: CI is green on 86ab04f (lint-type-test, e2e, CodeQL). I read the diff, the callers of NameSchema and participantErrorCopy, and the error path through api-response.ts. The tophat passed on this exact SHA (ux=yes), so no runtime code has changed since.
Why the owner: this is UX. Participants now see "Enter your name, up to 100 characters." when the sign-up dialog or the edit page refuses a name, in place of the validator's text in the dialog and the false "Saved." on the edit page. API callers get a 400 for a spaces-only name where it used to be stored blank. Worth a look: the tophat's before-and-after pairs 545-base-blank-signup-phone / 545-head-blank-signup-phone and 545-base-edit-blank-phone / 545-head-edit-blank-phone.
https://claude.ai/code/session_01Ge3RPBKd3XN7tyWzLhpSP7
Generated by Claude Code
|
Approved by the owner at https://claude.ai/code/session_01DXydxGNyVt8sXcDp4XzG84 Generated by Claude Code |
Fixes #515.
The problem
NameSchemacheckedmin(1)before trimming, so a name of only spaces passed and came out as"". Signing up stored the participant with a blank name (blank on the Responses tab and in the CSV, "Thanks , you signed up…" in the email), and the edit page skipped the blank name and said "Saved." Only a move refused it. When the server did refuse a name, the sign-up dialog showed the validator's text ("String must contain at least 1 character(s)", 'Check the value of "name".').The fix
src/schemas/common.ts:NameSchemanow trims first and checks after, the wayEmailSchemadoes (max(100)on the raw string, then.pipe(z.string().min(1))). Sign-up and edit both refuse a blank name withinvalid_inputonname.src/services/commitments.ts:MoveNameSchemaand the move's extra check are removed. The edit schema now applies the same rule, so the check was redundant. The existing "refuses a blank name on a move" DB test still covers it.src/app/s/[slug]/name-message.ts(new), used byparticipantErrorCopy: aninvalid_inputonnamereads "Enter your name, up to 100 characters." in the sign-up dialog and on the edit page. One message covers both reasons a name can be refused (blank, or over 100), so it never says the wrong one. I chose to word the server's refusal rather than add a client-side check, because both forms already go throughparticipantErrorCopy.organizerDisplayNameusesNameSchematoo, so a display name of only spaces is now refused as well.Tests
common.test.ts:NameSchematrims, refuses empty, spaces-only and whitespace-only names, and refuses names over 100 characters.commitments.test.ts: the create and update schemas both refuse" "onname. These failed before the schema change.participant-error.test.ts: a refused name gets the new copy on both pages, and anotherinvalid_inputdoesn't.commitments.db.test.ts: the test that pinned the blank name ("a name of spaces is stored blank") is replaced. A new test checks that sign-up and edit refuse" "and keep the old name. The move test for a stored blank name now creates that row directly, as an old row would be.pnpm lint && pnpm typecheck && pnpm knip && pnpm test(1302),pnpm test:db(493),pnpm build && pnpm budgets.Generated by Claude Code