Skip to content

feat: username policy — length cap, substring blocklist, reserved words - #144

Merged
windoze95 merged 1 commit into
mainfrom
feat/username-policy
Jul 13, 2026
Merged

feat: username policy — length cap, substring blocklist, reserved words#144
windoze95 merged 1 commit into
mainfrom
feat/username-policy

Conversation

@windoze95

Copy link
Copy Markdown
Owner

What

Usernames had no maximum length on the server (the client caps at 30, the API accepted a 5,000-character name), and the forbidden list was exact-match only — so saltybytesadmin, admin1 and adm1n all sailed straight through.

Changes

  • 30-character cap, chosen to match the existing client rule in register_screen.dart — no app change needed, and builds already in App Review stay in step.
  • Two-tier blocklist. forbiddenSubstrings holds distinctive terms that may not appear anywhere (brand, owner handles, admin, moderator); forbiddenExact holds reserved words that are only a problem when they are the whole name. A blanket "contains" check is the obvious move here and it's wrong: matching test anywhere rejects sweetestchef and thegreatest, and user rejects validuser123 — which is an existing passing test.
  • Leetspeak folding before matching, so 4dm1nadmin and s4l7ybyte5saltybytes.
  • Broader reserved list: roles, auth surface, infra/mail, support, billing + tier names (incl. the hidden unlimited tier), product routes, placeholders. Dropped entries that can never match (test_user, saltybytes-admin) — non-alphanumeric names are rejected before the list is consulted.
  • Local rules run before the uniqueness check, so junk input no longer costs a DB round trip; profanity detector is built once instead of on every signup.

julian and yana remain deliberately available.

Verification

go test ./... -count=1 green. New table tests cover the length bounds, leetspeak evasion, and the near-miss names that a naive substring match would eat. Spot-checked verdicts on ~50 realistic names:

Allowed Blocked
testkitchen, sweetestchef, grassroots, unofficialchef, arsenalsupporter, validuser123, homecook, julian, yana admin, sysadmin, administrator, 4dm1n, saltybytes, thesaltybytesguy, saltybytesadmin, s4l7ybyte5, r00t, windoze95, russianminx, moderator

Note

Signup is the only place a username is set (PUT /users/me only updates first name and email), so this one gate covers it. Existing accounts are unaffected — the rules run at creation only.

🤖 Generated with Claude Code

https://claude.ai/code/session_0194PdH4wDTnz5SWfzyoKagc

The username rules had no maximum length (the client capped at 30, the
server accepted anything), and the forbidden list was exact-match only, so
"saltybytesadmin" and "adm1n" both sailed through.

- Cap usernames at 30 characters, matching the existing client rule in
  register_screen.dart so old app builds stay in step.
- Split the blocklist in two: forbiddenSubstrings for distinctive terms that
  may not appear anywhere (brand, owner handles, admin, moderator), and
  forbiddenExact for reserved words too common to match as substrings.
  Matching "test" or "user" anywhere would reject "sweetestchef" and
  "validuser123", so those stay exact-only.
- Fold leetspeak digits before matching, so "4dm1n" and "s4l7ybyte5" are
  caught as "admin" and "saltybytes".
- Broaden the reserved words: roles, auth surface, infra/mail, support,
  billing and tier names, product routes, placeholders. Dropped the entries
  that can never match ("test_user", "saltybytes-admin") — non-alphanumeric
  names are rejected before the list is consulted.
- Run the local rules before the uniqueness check, so a junk username no
  longer costs a database round trip, and build the profanity detector once
  instead of per signup.

"julian" and "yana" remain deliberately available.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0194PdH4wDTnz5SWfzyoKagc
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@windoze95
windoze95 merged commit ac4e9c2 into main Jul 13, 2026
1 check passed
@windoze95
windoze95 deleted the feat/username-policy branch July 13, 2026 02:54
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.

1 participant