Skip to content

hard: registration wallet-existence checks are TOCTOU — concurrent registers create duplicate identities - #127

Open
Godfrey-Delight wants to merge 1 commit into
StepFi-app:mainfrom
Godfrey-Delight:fix/registration-race-condition-db-uniqueness
Open

hard: registration wallet-existence checks are TOCTOU — concurrent registers create duplicate identities#127
Godfrey-Delight wants to merge 1 commit into
StepFi-app:mainfrom
Godfrey-Delight:fix/registration-race-condition-db-uniqueness

Conversation

@Godfrey-Delight

Copy link
Copy Markdown
Contributor

🔗 Related Issue

Closes #120


🔖 Title

fix(auth): enforce database-level uniqueness in register and eliminate race conditions


📝 Description

Eliminated application-side pre-check queries in AuthService.register() (findByWallet and checkUsernameExists) which allowed race conditions during concurrent user registrations (e.g., double-click or retry storms). Uniqueness is now enforced directly by DB-level UNIQUE constraints on users.wallet_address and users.username. Unique constraint violations (Postgres 23505) are caught and mapped to existing structured 409 ConflictException error responses (AUTH_WALLET_EXISTS, AUTH_USERNAME_TAKEN). In addition, failed registration attempts clean up uploaded avatar objects and partial user records to prevent orphaned state.


🔄 Changes Made

  • Database Migration: Added migration 20260826130000_ensure_users_unique_constraints.sql ensuring UNIQUE indexes exist on users.wallet_address and users.username.
  • Repository Layer: Updated UsersRepository.createProfile() to catch Postgres error 23505 and map wallet/username collisions to structured ConflictException responses. Added deleteAvatar and deleteUserById methods.
  • Auth Service Rewrite: Rewrote AuthService.register() to attempt direct insertion via createProfile(), eliminating racy pre-checks. Wrapped profile creation, avatar upload, and token issuance in a try...catch block with rollback cleanup.
  • Unit & Race Tests: Added unit tests covering PostgreSQL 23505 error mapping, parallel duplicate-wallet and duplicate-username race tests (Promise.allSettled), sequential re-registration compatibility, and avatar/user cleanup on failure.
  • Documentation: Updated context/progress-tracker.md.

📸 Screenshots (if applicable)

N/A (Backend API logic change)


🗒️ Additional Notes

  • npm run build passed cleanly with 0 TypeScript errors.
  • npm test passed with 30/30 test suites green (355/355 total tests passing).
  • API error format and status codes remain 100% backward compatible for legitimate callers.

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.

hard: registration wallet-existence checks are TOCTOU — concurrent registers create duplicate identities

1 participant