Skip to content

fix(organizations): restrict organization names to letters A–Z, digits and name punctuation - #2041

Merged
Devin-Holland merged 8 commits into
stagefrom
org-name-charset-allowlist
Oct 29, 2026
Merged

Devin-Holland merged 8 commits into
stagefrom
org-name-charset-allowlist

Conversation

@Devin-Holland

@Devin-Holland Devin-Holland commented Oct 28, 2026 •

Copy link
Copy Markdown
Member
A barefoot dungeon hero files little hats and dots off stone name tiles while his tiara cat pushes a plain golden tile toward a glowing gate

⊙ Problem

Central Manager now rejects organization names outside an allowlist (central-manager#1063). The new-organization form had no character rule, so a bad name failed only after submit. Its blank-name default, ${firstname} ${lastname} Org, would also fail for users with accented names like José García.

🤔 Does the form need its own copy of the rule?

Central Manager is authoritative, but without a copy here a bad name fails only after submit, and the blank-name default would get a 400. The copy can drift from Central Manager's; that is tracked in studio#2040.

💡 Solution

  • The name field uses central-manager's rule: a letter A–Z or digit first, then letters A–Z, digits, spaces and ' ’ - . , & ( ). The form shows the error inline and the hint lists the allowed characters.
  • A blank name still submits a default. It now drops accents (José García Org → Jose Garcia Org).
  • If the name still fails (Łukasz, Øystein, Weiß have no unaccented form), the default is My Organization. The suggested subdomain still comes from the user's own name (ukasz-nowak-org), so they don't all collide on my-organization.
  • A typed name is only accepted or rejected, never changed.
  • Deploy this before central-manager#1063, so the default never hits the new 400.

✅ Verification

  • pnpm exec vitest run: 614 files pass. Two unrelated editor tests failed once under full-suite load and pass alone, twice.
  • The new tests fail on base. The form tests check the actual submitted payload: a typed name unchanged, @mallory@evil.com refused, José García → Jose Garcia Org, Łukasz Nowak → My Organization at ukasz-nowak-org. Also new: default-name tests and regex tests.
  • tsc -b, oxlint and dprint check are clean.
  • End-to-end route: not run in a browser against CM. The form tests stop at the submitted payload, and CM's tests start from that payload.

🤖 Generated by Anthropic Claude (Opus); posted via @Devin-Holland.

Related PRs: none found
Complexity: easy

Deferred findings

  • 686bcc1086557b14 nit maintainability — src/lib/string/regex/organizationNameRegex.ts — CM regex parity is by copy only; drift undetected by CI — NOT FILED

Late Grok findings

2 surviving (highest nit) — Grok reviewed f6c24b4, ruled against 8d9b883
  • nit — src/features/organizations/mutations/newOrganizationSchema.ts:38 — a profile first name with a leading space (for example ' José') passes filter(Boolean). That produces ' Jose Garcia Org', which fails the allowlist, so a blank-name submit falls back to My Organization. Trimming each part first would keep the name.
  • nit — src/features/organizations/components/NewOrgForm.tsx:113 — the form description doesn't list the curly apostrophe ’, although the regex accepts it. The copy understates what's allowed and doesn't reject any valid name.

Not standing: 1 dropped-factually-wrong, 1 accepted-known. Grok ran 17m (17m from launch to report); the fold adjudication (cursor-grok@f6c24b41e4ad-d1902f50, claude) took 1m.

Late Grok findings

2 surviving (highest minor) — Grok reviewed 7bc6c3d, ruled against da2e2f2
  • minor — src/features/organizations/mutations/newOrganizationSchema.ts:50 — If a user's name has no ASCII letter or digit (李明 王芳, Иван Петров), the suggested subdomain is still the shared my-organization, the same one nameless users get. All of these users collide (409) on a blank-subdomain submit, and resubmitting sends the same value. A name with exactly one ASCII chara
  • nit — src/features/organizations/mutations/newOrganizationSchema.ts:36 — The comment's "so accents are dropped (José → Jose)" clause repeats what unaccentedUserName and line 39 already say. Only "names are English-only" is a real why [8: read at HEAD]

Not standing: 1 dropped-factually-wrong, 1 merged. Grok ran 11m (11m from launch to report); the fold adjudication (cursor-grok@7bc6c3d61851-69f40e33, claude) took 1m.

Review-Coverage: authored=claude; ran=cursor-composer,gemini,codex,cursor-grok; late=cursor-grok:adjudicated; adjudicated=domain; declined=muse; rounds=4; full=1 @ da2e2f2

Review-Attention: study ~15m (critical: newOrganizationSchema.ts; decisions: ascii-gate-threshold, subdomain-source-diverges-from-display-name, fallback-for-untransliterable, transliterate-default-but-reject-typed, ascii-only-allowlist, deploy-order, do-less-alternative) @ da2e2f2

Devin-Holland and others added 4 commits October 28, 2026 16:45
…igits and name punctuation

The new-organization form now validates the name against the same allowlist central-manager
enforces: an English letter or digit first, then letters, digits, spaces and ' ’ - . , & ( ).
When the name is left blank, the default built from the user's name drops accents
(José → Jose) and falls back to "My Organization" when it still is not a valid name, so the
default never fails central-manager's validation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ers A–Z

The blank-name default no longer contains a double space when a user has only one name, or
"undefined" when the name is missing; with no name at all it falls back to "My Organization".
The error and hint now say letters A–Z, since accented letters are refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ization name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Devin-Holland
Devin-Holland marked this pull request as ready for review October 28, 2026 21:13
@Devin-Holland
Devin-Holland requested a review from a team as a code owner October 28, 2026 21:13

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces stricter validation for organization names using a new regex and Zod schema, while also implementing a helper to generate normalized, accent-free default organization names from user profiles. Comprehensive unit tests have been added to verify these validation rules and fallback behaviors. The review feedback suggests improving the user experience and data cleanliness by trimming leading and trailing whitespace from the organization name input in both the schema validation and the form's live preview logic.

Comment thread src/features/organizations/mutations/newOrganizationSchema.ts
Comment thread src/features/organizations/components/NewOrgForm.tsx Outdated
@dawsontoth
dawsontoth added this pull request to the merge queue Oct 28, 2026
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 82.19% 16729 / 20354
🔵 Statements 82.07% 17752 / 21628
🔵 Functions 77.58% 4542 / 5854
🔵 Branches 77.17% 13353 / 17302
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/features/organizations/components/NewOrgForm.tsx 86.36% 90% 85.71% 86.36% 72-74
src/features/organizations/mutations/newOrganizationSchema.ts 100% 100% 100% 100%
src/lib/string/regex/organizationNameRegex.ts 100% 100% 100% 100%
Generated in workflow #2485 for commit da2e2f2 by the Vitest Coverage Report Action

@dawsontoth
dawsontoth removed this pull request from the merge queue due to a manual request Oct 28, 2026
Devin-Holland and others added 2 commits October 29, 2026 10:51
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…racter class

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@DavidCockerill DavidCockerill left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving the hyphen is fine; the class accepts exactly the same characters as CM's. My my-organization note is non-blocking, so I'm fine with this going in as long as it deploys before central-manager#1063.

Findings drafted by claude-opus-5-5 via daivid-review, reviewed and posted by @DavidCockerill.

Comment thread src/features/organizations/mutations/newOrganizationSchema.ts
Devin-Holland and others added 2 commits October 29, 2026 11:38
…he default name falls back

Users whose names have no unaccented form (Łukasz, Øystein) all got the
`My Organization` default and so all suggested `my-organization`, which
CM refuses with 409 once one org holds it.

Dispatch-Task: fix-Devin-Holland_studio_2041-9db89d90
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… no letter A–Z or digit

A name like 太郎 kebab-cases to just `org`, which every such user would share.

Dispatch-Task: fix-Devin-Holland_studio_2041-9db89d90
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Devin-Holland
Devin-Holland added this pull request to the merge queue Oct 29, 2026
Merged via the queue into stage with commit 8446552 Oct 29, 2026
4 checks passed
@Devin-Holland
Devin-Holland deleted the org-name-charset-allowlist branch October 29, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants