Skip to content

fix(frontend): make profile URLs case-insensitive#485

Open
IvGolovach wants to merge 3 commits intojunhoyeo:mainfrom
IvGolovach:codex/fix-profile-username-case-477
Open

fix(frontend): make profile URLs case-insensitive#485
IvGolovach wants to merge 3 commits intojunhoyeo:mainfrom
IvGolovach:codex/fix-profile-username-case-477

Conversation

@IvGolovach
Copy link
Copy Markdown
Contributor

@IvGolovach IvGolovach commented Apr 28, 2026

Summary

Make profile username lookups case-insensitive across the frontend public profile surfaces.

Fixes #477.

Why

Shared profile URLs should resolve regardless of username casing. Before this change, /u/imlunahey could return not found while /u/ImLunaHey worked, which made profile links unreliable and inconsistent with GitHub username expectations.

Diff scope

  • Added packages/frontend/src/lib/db/usernameLookup.ts with shared case-insensitive username matching and cache-key normalization helpers.
  • Updated packages/frontend/src/app/api/users/[username]/route.ts to resolve profile usernames case-insensitively while returning the stored canonical username.
  • Updated packages/frontend/src/lib/embed/getUserEmbedStats.ts so embed stats and contribution lookups resolve usernames case-insensitively.
  • Updated packages/frontend/src/lib/leaderboard/getLeaderboard.ts so all-time and period user-rank lookups match usernames case-insensitively.
  • Updated packages/frontend/src/app/api/submit/route.ts and packages/frontend/src/app/api/settings/submitted-data/route.ts so revalidation tags match the normalized cache keys.
  • Added and updated regression coverage in:
    • packages/frontend/__tests__/api/usersProfile.test.ts
    • packages/frontend/__tests__/api/settingsSubmittedDataDelete.test.ts
    • packages/frontend/__tests__/api/submitAuth.test.ts
    • packages/frontend/__tests__/lib/getLeaderboard.test.ts
    • packages/frontend/__tests__/lib/getLeaderboardAllTime.test.ts
    • packages/frontend/__tests__/lib/getUserEmbedStats.test.ts
    • packages/frontend/__tests__/lib/usernameLookup.test.ts

Branch integrity

  • Base branch: main
  • git rev-parse origin/main: edc8ed1fca49ec4a6936e4d4e15ca45dfd442b8e
  • git rev-list --left-right --count origin/main...HEAD: 0 1
  • Behind count: 0
  • Ahead count: 1
  • git merge-base origin/main HEAD: edc8ed1fca49ec4a6936e4d4e15ca45dfd442b8e
  • git merge-base --is-ancestor origin/main HEAD: PASS, exit 0
  • Fast-forward safety: confirmed. This branch is one commit ahead of origin/main with no divergence.

Commit integrity

  • a6962fce4bff10798490d16c79a1aba2686382b2 fix(frontend): make profile username lookups case-insensitive
  • One logical change per commit: confirmed.
  • Ledger-Id trailer validation: Not applicable — scripts/ledger/ does not exist in this repository.
  • Unique Ledger-Id confirmation for squash-merge repositories: Not applicable — scripts/ledger/ does not exist in this repository.

Ledger proof

Not applicable — scripts/ledger/ does not exist in this repository.

Diff hygiene

git diff --name-status origin/main...HEAD:

M	packages/frontend/__tests__/api/settingsSubmittedDataDelete.test.ts
M	packages/frontend/__tests__/api/submitAuth.test.ts
M	packages/frontend/__tests__/api/usersProfile.test.ts
M	packages/frontend/__tests__/lib/getLeaderboard.test.ts
M	packages/frontend/__tests__/lib/getLeaderboardAllTime.test.ts
A	packages/frontend/__tests__/lib/getUserEmbedStats.test.ts
A	packages/frontend/__tests__/lib/usernameLookup.test.ts
M	packages/frontend/src/app/api/settings/submitted-data/route.ts
M	packages/frontend/src/app/api/submit/route.ts
M	packages/frontend/src/app/api/users/[username]/route.ts
A	packages/frontend/src/lib/db/usernameLookup.ts
M	packages/frontend/src/lib/embed/getUserEmbedStats.ts
M	packages/frontend/src/lib/leaderboard/getLeaderboard.ts
  • git diff --check origin/main...HEAD: PASS, no output
  • Forbidden-file confirmation: no .env files, local environment files, secrets, tokens, credentials, ops/reports/** artifacts, __pycache__/, *.pyc, .DS_Store, .coverage, htmlcov/, coverage.xml, build artifacts, cache files, unrelated generated files, or unrelated source changes.

Test proof

  • packages/frontend/node_modules/.bin/vitest run: PASS, 154 tests passed across 19 test files
  • bun run lint: PASS, 0 errors, 7 warnings in pre-existing unrelated files
  • bun run build: PASS
  • Backend pytest: Not applicable — no backend/runtime/migration/backend dependency files changed.
  • Coverage percentage: Not applicable — backend coverage gate is not required for this frontend-only change.

Verification-pack proof

Not applicable — no infra/governance/replay/invariant/verification files changed.

Migration notes

Not applicable — no DB migration changed.

CI context confirmation

  • Required contexts: backend, frontend, simulated-correctness-core
  • CI context names unchanged.
  • Not applicable — no CI/workflow context changes.

Runtime safety

Reviewed runtime files/modules:

  • packages/frontend/src/app/api/users/[username]/route.ts
  • packages/frontend/src/lib/embed/getUserEmbedStats.ts
  • packages/frontend/src/lib/leaderboard/getLeaderboard.ts
  • packages/frontend/src/app/api/submit/route.ts
  • packages/frontend/src/app/api/settings/submitted-data/route.ts
  • packages/frontend/src/lib/db/usernameLookup.ts

Runtime reasoning:

  • No new blocking locks: the change only replaces exact username predicates with an exact case-insensitive SQL predicate and normalizes cache tag strings.
  • No new unbounded queues: no queueing, background workers, polling loops, or async accumulation paths were added.
  • No invariant removal: canonical stored usernames are still returned in API responses; cache revalidation remains scoped to the same public profile and leaderboard surfaces.
  • No invariant regression introduced.

Documentation integrity

Not applicable — no docs, runbooks, public commands, or operational behavior changed.

Rollback plan

  • Intended post-merge rollback command for squash merge: git revert <post_merge_commit_sha>
  • Replace <post_merge_commit_sha> with the final squash/merge commit SHA after merge.
  • DB downgrade required: no.
  • Data repair required: no.
  • Operational caveats: none expected.

Known residual risks

  • Low: LOWER(users.username) may not use the existing username unique index on every Postgres plan. No migration was added because this is a narrow single-user lookup; a functional index can be added later if profile lookup volume requires it.

Validation

- scripts/ledger/check: Not applicable - scripts/ledger/ does not exist in this repository.
- git fetch --no-tags origin main: PASS
- packages/frontend/node_modules/.bin/vitest run: PASS, 154 tests
- bun run lint: PASS, 0 errors, 7 warnings in pre-existing unrelated files
- bun run build: PASS
- git diff --check: PASS
- git diff --cached --check: PASS

Rollback

- git revert HEAD
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tokscale Ready Ready Preview, Comment Apr 28, 2026 7:37pm

Request Review

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 13 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/frontend/src/app/api/users/[username]/route.ts">

<violation number="1" location="packages/frontend/src/app/api/users/[username]/route.ts:32">
P1: Case-insensitive username lookup combined with `limit(1)` is ambiguous without a case-insensitive uniqueness guarantee, and may return the wrong user if case-variant duplicates exist.</violation>
</file>

<file name="packages/frontend/src/lib/leaderboard/getLeaderboard.ts">

<violation number="1" location="packages/frontend/src/lib/leaderboard/getLeaderboard.ts:507">
P2: Case-insensitive user lookup is not backed by case-insensitive uniqueness, so `.limit(1)` can return arbitrary users for case-colliding usernames and cache under a shared normalized key.</violation>
</file>

<file name="packages/frontend/src/lib/db/usernameLookup.ts">

<violation number="1" location="packages/frontend/src/lib/db/usernameLookup.ts:5">
P2: Case-insensitive username lookup uses LOWER(column) without a matching functional index, which can bypass the existing username index and degrade query performance.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/frontend/src/app/api/users/[username]/route.ts
Comment thread packages/frontend/src/lib/leaderboard/getLeaderboard.ts
Comment thread packages/frontend/src/lib/db/usernameLookup.ts Outdated
Validation

- scripts/ledger/check: Not applicable - scripts/ledger/ does not exist in this repository.
- git fetch --no-tags origin main: PASS
- packages/frontend/node_modules/.bin/vitest run __tests__/api/usersProfile.test.ts __tests__/lib/getLeaderboard.test.ts __tests__/lib/getLeaderboardAllTime.test.ts __tests__/lib/getUserEmbedStats.test.ts __tests__/lib/usernameLookup.test.ts: PASS, 23 tests
- packages/frontend/node_modules/.bin/vitest run: PASS, 162 tests
- bun run lint: PASS, 0 errors, 7 warnings in pre-existing unrelated files
- bun run build: PASS
- git diff --check: PASS
- git diff --cached --check: PASS

Rollback

- git revert HEAD
Validation

- scripts/ledger/check: Not applicable - scripts/ledger/ does not exist in this repository.
- git fetch --no-tags origin main: PASS
- packages/frontend/node_modules/.bin/vitest run __tests__/api/usersProfile.test.ts __tests__/lib/getLeaderboard.test.ts __tests__/lib/getLeaderboardAllTime.test.ts __tests__/lib/getUserEmbedStats.test.ts __tests__/lib/usernameLookup.test.ts: PASS, 24 tests
- packages/frontend/node_modules/.bin/vitest run: PASS, 163 tests
- bun run lint: PASS, 0 errors, 7 warnings in pre-existing unrelated files
- bun run build: PASS
- git diff --check: PASS
- git diff --cached --check: PASS

Rollback

- git revert HEAD
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.

Profile URLs should be case-insensitive

1 participant