Fix referral quota for existing recipients#442
Conversation
Greptile SummaryThis PR fixes an over-eager 429 response when submitting referral invites that include emails already in the
Confidence Score: 5/5Safe to merge; the reordering is logically correct and the newly added error guard on the duplicate-check query is an improvement. The change is a focused reorder of three existing operations in POST /api/referrals. The duplicate-invite lookup now runs before quota math, newValidEmails replaces validEmails in both quota comparisons, and the previously-swallowed Supabase error on that lookup is now handled explicitly. No new execution paths are introduced that could cause data loss, double-sends, or auth bypass beyond what already existed. Only src/app/api/referrals/route.ts changed; the quota-count queries in that file still discard their error field, worth a follow-up but not a blocker. Important Files Changed
Sequence DiagramsequenceDiagram
participant C as Client
participant R as POST /api/referrals
participant DB as Supabase (svc)
participant M as Email Service
C->>R: "POST { emails }"
R->>R: Auth check
R->>R: "Validate & dedupe email syntax → validEmails"
R->>DB: "SELECT referred_email WHERE referrer_id=? AND referred_email IN validEmails"
DB-->>R: existingInvites (or error → 500)
R->>R: Build alreadyInvited set → newValidEmails
alt newValidEmails is empty
R-->>C: 400 All already invited
end
R->>DB: "COUNT referrals WHERE referrer_id=? AND created_at > -1h"
DB-->>R: hourlyCount
alt "hourlyCount + newValidEmails.length > 10"
R-->>C: 429 hourly limit
end
R->>DB: "COUNT referrals WHERE referrer_id=? AND created_at > -24h"
DB-->>R: dailyCount
alt "dailyCount + newValidEmails.length > 50"
R-->>C: 429 daily limit
end
R->>DB: SELECT profile (user client)
DB-->>R: profile
R->>M: sendEmail for each newValidEmail
M-->>R: emailResults
R->>DB: INSERT successful referral rows (user client)
DB-->>R: inserted referrals
R-->>C: "200 { message, data }"
Reviews (2): Last reviewed commit: "Handle referral duplicate lookup errors" | Re-trigger Greptile |
Fixes #439.
Referral quota checks were counting all valid email addresses before filtering addresses that had already been invited. That could return 429 even when only one new recipient would consume quota.
This moves duplicate-invite filtering before the hourly and daily quota checks, then counts only new valid emails against the limits.
Tests:
git diff --checknpm test -- src/app/api/referrals/route.test.ts --runInBandblocked:vitestnot installed locally