Normalize usernames for safe indexed lookup - #194
Merged
Conversation
Request only public WCA identity, allowlist login fields, and stop MongoDB and PostgreSQL writes. Add a value-free two-phase purge with an enforced privacy rollback floor so the compatibility column can remain safely empty until a later drop.
Exit unsuccessfully when MongoDB cannot be reached and clear the PostgreSQL compatibility column independently of guarded user upserts. This prevents connection failures or equal timestamps from leaving legacy email values behind.
Centralize username validation and add a collision-aware MongoDB backfill. Mirror normalized keys through an additive PostgreSQL migration for safe friend discovery.
Reconcile MongoDB username targets into PostgreSQL and fail index creation while collisions remain. Canonicalize privacy markers and keep test authentication on the shared normalization path.
coder13
force-pushed
the
agent/issue-185-normalized-usernames
branch
from
July 13, 2026 04:13
de3b389 to
35e3198
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
400validation and409case-insensitive conflict responses without interpolated regular expressionsPrivacy behavior
Email is never a discovery input or fallback. Email-like username input receives the same generic
INVALID_USERNAMEresponse as other invalid input and never issues a lookup. Privacy-marker detection happens after NFKC canonicalization, so compatibility characters such as fullwidth and small@cannot bypass it.The legacy backfill never prints private raw values. It removes email-like usernames from MongoDB and reconciles both PostgreSQL username fields to
NULLby WCA user ID. This branch preserves #192's no-email ingestion and dual-write behavior.Dependency and merge order
This branch is rebased onto the current head of #192 (
72e1494), so the integration with the email purge has been resolved and tested. Because #192 is not yet onmaster, this PR temporarily includes its two commits.Merge and deploy #192 first. After it lands, refresh this branch against
masterso the PR contains only #185's commits. Intended rollout order remains #192 → #185 → friendship/discovery work.Migration behavior
The MongoDB script defaults to a read-only, value-free report. Applying it writes the planned MongoDB targets, rereads and verifies them, then reconciles exact PostgreSQL targets by WCA user ID when PostgreSQL is enabled. PostgreSQL-disabled deployments are reported explicitly and can rerun the same idempotent reconciliation before bringing the mirror back.
Invalid non-email legacy usernames remain undiscoverable. Collision members retain display values but have no normalized key; index creation fails closed until every collision is explicitly resolved. Username writes and discovery must remain disabled during that state, preventing a third account from claiming a collided key.
--create-indexrequires--apply, zero pending changes, zero privacy removals, zero collisions, and zero PostgreSQL verification mismatches. It then creates or verifies the named sparse unique index. A repeated apply reports no modified rows.Validation
CI=true yarn test— 3 workspaces passed, 224 tests totalyarn lint— 3 workspaces passedyarn workspace letscube-server postgres:schema:validate— passedyarn build— passed (existing Vite chunk-size warnings only)git diff --check origin/master...HEAD— passedCloses #185