Skip to content

fix(billing): serialize Gmail inbox allowance decisions so racing alias signups can't both keep it - #9431

Merged
waleedlatif1 merged 2 commits into
stagingfrom
fix/gmail-inbox-allowance-race
Oct 29, 2026
Merged

waleedlatif1 merged 2 commits into
stagingfrom
fix/gmail-inbox-allowance-race

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Better Auth commits each user row before user.create.after runs, so two signups on one Gmail inbox could race: the later account's earlier-account check could run before the earlier row was visible, and both kept the free allowance (follow-up to fix(billing): withhold the free allowance from Gmail aliases of an existing account #9418)
  • handleNewUser now decides inside one transaction under a per-inbox advisory lock (acquireGmailInboxLock, existing acquireAdvisoryXactLock), inserts the stats row, then withdraws the allowance from any later alias on the inbox that got in first (laterGmailAliasesWithAllowance) — the earliest account keeps it whichever hook runs first
  • The stats-row fallback keeps an unlocked check: it only runs when a signup's own decision failed, and locking there would hold the inbox lock through the caller's transaction; it never withdraws from later accounts, so long-standing aliases are never stripped retroactively
  • identityHadFreeAllowance moves to lib/users/free-allowance.ts; the admin balance grant now uses it, so a stats row it creates applies the Gmail rule too (it previously checked deleted identities only)
  • Alias lookups are a single self-join on user_gmail_mailbox_idx; test schema mock gains gmailMailbox

Type of Change

  • Bug fix

Testing

  • lib/users/gmail-alias.integration.ts on real Postgres (INTEGRATION_DB_PROVISION=migrate): 11/11. New guards shown red with the fix disabled: an alias whose signup decided first loses the allowance once the earlier account decides; a held inbox lock blocks a same-inbox signup (pg_blocking_pids); the fallback never withdraws from a later alias. Index test now EXPLAINs the self-join shape
  • lib/billing/core/usage.test.ts, lib/admin/dashboard-credit-grant.test.ts: 30/30
  • bun run lint, check:file-names, check:test-patterns, check:comment-hygiene, check:unused-exports, check:boundaries, check:schema-mock; drizzle-kit generate reports no drift
  • Full type-check / audits / suites left to CI

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 29, 2026 1:22am UTC

Request Review

@greptile-apps

greptile-apps Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The changes since the previous review appear safe to merge.

Summary

The PR puts Gmail allowance decisions inside a transaction with a shared inbox lock. It also removes the allowance from later aliases when the earlier account’s signup finishes last.

  • Gmail signup races leave the free allowance with the earliest account.
  • Admin balance grants check Gmail aliases before creating missing stats rows.

Diagram

sequenceDiagram
  participant Signup
  participant DB as PostgreSQL
  Signup->>DB: Begin transaction
  Signup->>DB: Acquire Gmail inbox lock
  Signup->>DB: Restore previous lock timeout
  Signup->>DB: Check identity and earlier aliases
  Signup->>DB: Insert allowance decision
  Signup->>DB: Withdraw allowance from later aliases
  Signup->>DB: Commit and release inbox lock
Loading

Reviews (2) · Last reviewed commit: "fix(billing): restore lock_timeout after..." · Reviewed by Greptile

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 8 files

This PR changes concurrency-sensitive code such as locks, queues, or retries. Ultrareviews find 2.4x more serious bugs than standard reviews. Comment @cubic-dev-ai ultrareview to run one.

Turn on auto-fix | Re-trigger cubic

Comment thread apps/sim/lib/users/gmail-alias.ts Outdated
Comment thread apps/sim/lib/users/free-allowance.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 8 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit 77dfe17 into staging Oct 29, 2026
68 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/gmail-inbox-allowance-race branch October 29, 2026 02:03

This branch was previously deployed

1 inactive deployment
Preview — 14b5fb2c Deployed Oct 29, 2026 by vercel[bot]
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.

1 participant