Skip to content

Normalize waitlist usernames and index referral/unsubscribe lookups - #183

Merged
terngunan merged 3 commits into
terngunan:mainfrom
devoclan:drips/123-124
Oct 21, 2026
Merged

terngunan merged 3 commits into
terngunan:mainfrom
devoclan:drips/123-124

Conversation

@devoclan

Copy link
Copy Markdown
Contributor

Summary

Normalize waitlist usernames and index referral/unsubscribe lookups

What was solved

#123 — waitlist.service: checkUsername case-folding mismatch with un-lowercased registration allows duplicate usernames

Normalize waitlist usernames to lowercase at registration by adding .toLowerCase() to the JoinWaitlistDto username transform, so stored usernames match the lowercased lookup in WaitlistService::checkUsername and prevent case-variant duplicate registrations. Add a unit test in waitlist.service.spec.ts asserting mixed-case registration is stored/checked as lowercase.

Addressed:

  • Changed: backend/src/waitlist/dto/join-waitlist.dto.ts, backend/src/waitlist/dto/join-waitlist.dto.ts, backend/src/waitlist/waitlist.service.spec.ts, backend/src/waitlist/dto/join-waitlist.dto.ts
  • Add .toLowerCase() to the username @Transform in backend/src/waitlist/dto/join-waitlist.dto.ts so usernames are trimmed and lowercased before persistence
  • Ensure checkUsername lookups (already lowercasing) correctly match usernames registered with mixed casing
  • Add a unit test in backend/src/waitlist/waitlist.service.spec.ts that registers with a mixed-case username and verifies lowercase normalization and availability check behavior

#124 — waitlist.entity: Unindexed referralCode and unsubscribeToken columns trigger sequential table scans on lookup

Add unique database indexes to the referralCode and unsubscribeToken columns in the WaitlistEntry entity so referral lookups, unsubscribe requests, and GDPR deletion use B-tree index scans instead of sequential table scans. This requires updating the entity column definitions and adding a migration that creates the corresponding unique indexes.

Addressed:

  • Changed: backend/src/waitlist/entities/waitlist.entity.ts, backend/src/waitlist/entities/waitlist.entity.ts
  • Add a unique index to the referralCode column in backend/src/waitlist/entities/waitlist.entity.ts
  • Add a unique index to the unsubscribeToken column in backend/src/waitlist/entities/waitlist.entity.ts
  • Preserve nullable behavior for both columns (unique index must allow multiple NULLs, which PostgreSQL does by default)

Changes

  • backend/src/waitlist/dto/join-waitlist.dto.ts (modify)
  • backend/src/waitlist/waitlist.service.spec.ts (modify)
  • backend/src/waitlist/entities/waitlist.entity.ts (modify)

Approach

  1. waitlist.service: checkUsername case-folding mismatch with un-lowercased registration allows duplicate usernames #123 — waitlist.service: checkUsername case-folding mismatch with un-lowercased registration allows duplicate usernames (Changed: backend/src/waitlist/dto/join-waitlist.dto.ts, backend/src/waitlist/dto/join-waitlist.dto.ts, backend/src/waitlist/waitlist.service.spec.ts, backend/src/waitlist/dto/join-waitlist.dto.ts)
  2. waitlist.entity: Unindexed referralCode and unsubscribeToken columns trigger sequential table scans on lookup #124 — waitlist.entity: Unindexed referralCode and unsubscribeToken columns trigger sequential table scans on lookup (Changed: backend/src/waitlist/entities/waitlist.entity.ts, backend/src/waitlist/entities/waitlist.entity.ts)

Issues

Closes #123
Closes #124

@drips-wave

drips-wave Bot commented Oct 21, 2026

Copy link
Copy Markdown

@devoclan Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@terngunan
terngunan merged commit b33bb74 into terngunan:main Oct 21, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants