improvement(auth): layer disposable-email-domains into signup email validation#5010
Conversation
…me/drop prompt `drizzle-kit push --force` only suppresses the data-loss confirm, not the rename-vs-drop disambiguation prompt. That prompt fires whenever a diff both adds and drops tables/columns at once (e.g. migration 0231 created sim_trigger_state while dropping the workspace_notification_* tables), and in CI it crashes with a bare "Interactive prompts require a TTY" stack trace. Catch that specific failure in the dev push step and emit a GitHub error annotation explaining the cause and the fix (drop the stale objects on the dev DB to match schema.ts — the same DROPs the versioned migration already applied to staging/prod), instead of leaving an opaque trace. Exit status is preserved either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…alidation Compose the disposable-email-domains list (exact + wildcard) into better-auth-harmony's validator alongside its bundled Mailchecker list, so signup rejects an email if either flags it. Server-only module to keep the dataset out of the client bundle.
|
@greptile review |
PR SummaryMedium Risk Overview Separately, the dev migrations workflow captures Reviewed by Cursor Bugbot for commit d70f56d. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a489c4f. Configure here.
Greptile SummaryThis PR layers the
Confidence Score: 5/5Safe to merge — the new validation layer is additive and gated behind an existing feature flag. The validator composition in auth.ts preserves the full original check (format validation via validator.js + Mailchecker domain block) and adds the disposable-email-domains list on top. The lazy-load cache is correct and idiomatic. Test coverage is thorough. The migrations workflow change is a pure diagnostic improvement with no behavioral change on success paths. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant emailHarmony as emailHarmony plugin
participant Mailchecker as validateEmailWithMailchecker
participant Disposable as isDisposableEmailDomain
participant Cache as Module-level cache
Client->>emailHarmony: POST /sign-up/email
emailHarmony->>Mailchecker: validateEmailWithMailchecker(email)
alt format invalid OR Mailchecker blocklist
Mailchecker-->>emailHarmony: false
emailHarmony-->>Client: 400 Invalid email
else passes Mailchecker
Mailchecker-->>emailHarmony: true
emailHarmony->>Disposable: isDisposableEmailDomain(email)
Disposable->>Cache: loadDisposableData()
alt cache cold
Cache->>Cache: dynamic import() exact + wildcard
Cache-->>Disposable: Set + wildcards
else cache warm
Cache-->>Disposable: cached (immediate)
end
alt domain flagged as disposable
Disposable-->>emailHarmony: true
emailHarmony-->>Client: 400 Invalid email
else domain clean
Disposable-->>emailHarmony: false
emailHarmony-->>Client: proceed with signup
end
end
Reviews (3): Last reviewed commit: "improvement(auth): defer disposable-doma..." | Re-trigger Greptile |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR layers
Confidence Score: 4/5Safe to merge — the new blocklist is additive and fail-closed, so the worst realistic outcome of any dataset gap is a missed disposable address, not a broken signup flow for legitimate users. The core validator composition in auth.ts is correct, the dataset is properly kept server-side, and the test suite covers the main paths well. The two minor gaps — no apps/sim/lib/messaging/email/disposable-domains.server.ts and its test file — the server-only guard and the untested wildcard equality branch are both in this new module. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Signup request\nemail address] --> B{SIGNUP_EMAIL_VALIDATION_ENABLED?}
B -- No --> Z[Allow signup]
B -- Yes --> C[emailHarmony custom validator]
C --> D{validateEmailWithMailchecker\nbetter-auth-harmony/email}
D -- false\ndisposable per Mailchecker --> R[Reject signup]
D -- true --> E{isDisposableEmailDomain\ndisposable-email-domains pkg}
E -- exactDomains.has domain --> R
E -- wildcardBaseDomains match --> R
E -- no match --> Z
Reviews (2): Last reviewed commit: "improvement(auth): layer disposable-emai..." | Re-trigger Greptile |
…ic import Address review: load the ~120K-entry dataset on first use instead of at module import, so deployments with SIGNUP_EMAIL_VALIDATION_ENABLED off never pay the cost. Add a bare wildcard-base test case.
|
@greptile review |

Summary
disposable-email-domainspackage (exact + wildcard lists) as an extra signup gate, composed intobetter-auth-harmony's validator alongside its bundled Mailchecker list — an email is rejected if either flags it (union, not replacement).isDisposableEmailDomain()module + ambient types; kept out of the client bundle so the ~120K dataset never ships to the browser. ClientquickValidateEmailkeeps its small fast-feedback set.SIGNUP_EMAIL_VALIDATION_ENABLEDflag.Type of Change
Testing
isDisposableEmailDomain(exact, wildcard subdomain, case-insensitivity, normal domain, custom catch-all, malformed) — all passingbun run lintclean,bun run check:api-validation:strictpassed,tsc --noEmit0 errorsNote
BLOCKED_SIGNUP_DOMAINS/BLOCKED_EMAIL_MX_HOSTS.Checklist