Let the signup route's trial row win over the trigger's - #236
Merged
Merged
Conversation
The on_auth_user_created_subscription trigger inserts a plain 3-day user_subscriptions row the instant auth.users gets a row, so by the time signUp() returns the row already exists. The route then upserted its own row with ignoreDuplicates: true, which turned the upsert into a no-op: signup_ip stayed NULL on every user and the repeat-IP 1-day trial never applied. Upsert with merge instead (ON CONFLICT (user_id) DO UPDATE), so the route's signup_ip and trial window land on the trigger's row. Columns the route does not send (id, created_at, renewal flags, subscription_*) are untouched. The trigger stays, since it covers OAuth and magic-link signups that never hit this route. Tests cover both branches: a fresh IP gets 3 days with signup_ip set, a repeat IP gets 1 day, and both assert the upsert merges rather than ignores duplicates. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ThreatCrush Security Scan95 finding(s) HIGH/CRITICAL: 11 | MEDIUM: 29 | LOW: 55
…and 45 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
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.
Problem
on_auth_user_created_subscription(create_trial_subscription()) inserts a plain 3-dayuser_subscriptionsrow the moment a user is created. The signup route then upserted its own row withignoreDuplicates: true, so its row never landed:signup_ipstayed NULL on every user since the anti-abuse feature shipped (2026-02-15), and the repeat-IP 1-day trial never applied. Prod today: 2,163 rows, 0 with a trial shorter than 3 days.Change
src/app/api/auth/signup/route.ts: upsert with merge (ignoreDuplicates: false, i.e.ON CONFLICT (user_id) DO UPDATE) so the route'ssignup_ip,trial_started_atandtrial_expires_atland on the trigger's row. Columns the route does not send (id,created_at, renewal flags,subscription_*) are left as the trigger/defaults set them.Tests
src/app/api/auth/signup/route.test.tsgains aTrial anti-abuse (signup_ip)block:X-Forwarded-Forhop excluding the user's own row, upsert payload hassignup_ipset and a 3-day window, options{ onConflict: 'user_id', ignoreDuplicates: false }Both fail against the old route and pass with this one. Full CI gates run locally: eslint 0 errors,
tsc --noEmitclean, vitest 2,921 passed / 219 files.Deploy
Merging to master runs "CI Pipeline", and
deploy-droplet.ymlchains off its success (workflow_run), so no dispatch is needed. Verification on the droplet after deploy:/api/healthhealthy, a throwaway signup from a test IP writessignup_ipand a 3-daytrial_expires_at.🤖 Generated with Claude Code