Skip to content

fix: resolve signup watchlist review issues and auto-unlock on SIGNUP entry removal#27923

Merged
emrysal merged 4 commits intomainfrom
devin/1770974465-fix-signup-watchlist-issues
Feb 13, 2026
Merged

fix: resolve signup watchlist review issues and auto-unlock on SIGNUP entry removal#27923
emrysal merged 4 commits intomainfrom
devin/1770974465-fix-signup-watchlist-issues

Conversation

@alishaz-polymath
Copy link
Copy Markdown
Member

@alishaz-polymath alishaz-polymath commented Feb 13, 2026

What does this PR do?

Fixes three bugs in the signup watchlist review feature introduced in #27912, and adds auto-unlock behavior when SIGNUP-source watchlist entries are removed.

Bug Fixes

  1. GlobalWatchlistRepository.deleteEntry missing await — Prisma queries are lazy; without await, the delete was silently never executed. This caused watchlist entries to persist even after an admin unlocked a user.

  2. Email verification race conditionsendEmailVerification was called (fire-and-forget) BEFORE the watchlist check added the email to the blocklist. By the time sendEmailVerification ran its internal watchlist check, the email was already blocked, so no verification token was ever created. Fixed by moving sendEmailVerification to AFTER the watchlist early-return path, so it only runs for non-watchlisted signups.

  3. No verification email on unlock — After an admin unlocks a user and removes them from the watchlist, the user had no way to verify their email. Now sendEmailVerification is called after unlock in lockUserAccount.handler.ts.

Additionally, sendEmailVerification is now scoped to non-invite signups (!checkoutSessionId && !token) to prevent redundant verification emails for team invite users who already have emailVerified set.

New: Auto-unlock on SIGNUP watchlist entry removal

When a watchlist entry with source: SIGNUP and type: EMAIL is deleted (single or bulk) via AdminWatchlistOperationsService, the associated user is automatically:

  • Unlocked (via new UserRepository.unlockByEmail)
  • Sent a fresh verification email

This works for both deleteWatchlistEntry (single) and bulkDeleteWatchlistEntries (bulk). Errors in the unlock/email flow are caught and logged — they do not block the deletion itself.

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A

How should this be tested?

  1. Enable the signup-watchlist-review feature flag in the database
  2. Sign up a new user (non-invite flow, non-premium username)
  3. Verify the watchlist entry has source: 'SIGNUP' (not 'MANUAL')
  4. Verify no verification email is sent at signup (email is blocked by watchlist)
  5. As admin, unlock the user via the admin panel
  6. Verify the watchlist entry is deleted from the database
  7. Verify the user receives a fresh verification email after unlock
  8. Verify the verification link works
  9. New: As admin, remove a SIGNUP-source watchlist entry directly from the watchlist management UI
  10. Verify the associated user is automatically unlocked and receives a verification email
  11. Verify removing a MANUAL-source entry does not trigger auto-unlock

Human Review Checklist

⚠️ Important items for reviewer attention:

  • sendEmailVerification in unlock handler is awaited (lockUserAccount.handler.ts:45): Unlike the fire-and-forget pattern in the signup handler, the unlock handler awaits the call. If the email service fails, the unlock response will also fail. Confirm this is acceptable or if it should be fire-and-forget.

  • deleteEntry await fix (GlobalWatchlistRepository.ts:166): Confirm the missing await was indeed the root cause of watchlist entries not being deleted on unlock.

  • Order of operations in signup handler (calcomSignupHandler.ts:320-326): The watchlist check + early return now happens BEFORE sendEmailVerification. For the watchlist review path, the handler returns at line 317, so sendEmailVerification at line 320 is never reached — which is the correct behavior.

  • !token guard on sendEmailVerification (calcomSignupHandler.ts:320): Team invite signups (token flow) already set emailVerified directly, so they skip verification. Confirm this guard is correct.

  • Auto-unlock error handling (AdminWatchlistOperationsService.ts:215-227): The unlockSignupUser method catches errors and logs them but does not throw. This means if unlock fails, the watchlist deletion still succeeds. Confirm this is the desired behavior (deletion should not be blocked by unlock failures).

  • Non-atomic unlock (UserRepository.ts:1440-1459): unlockByEmail uses findFirst + update (two queries). There's a theoretical race condition if the user gets locked between find and update. Low risk but worth noting.

  • findEntriesByIds interface expansion (WatchlistRepository.ts:237-244): Now returns source, type, value fields. Verify no other callers depend on the previous narrower return type.


Link to Devin run: https://app.devin.ai/sessions/89436f0e54694e308731b95c32036f1d
Requested by: @alishaz-polymath

…erification ordering, and unlock flow

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

1 issue found across 5 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts">

<violation number="1" location="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts:320">
P2: The new unconditional verification call also runs for token-based invite signups, even though those users are already marked `emailVerified`. This can create unnecessary verification tokens/emails and confuse invited users. Consider skipping the call when `foundToken` is present.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 13, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ Pushed commit fb0490c

@alishaz-polymath alishaz-polymath added ready-for-e2e run-ci Approve CI to run for external contributors labels Feb 13, 2026
@alishaz-polymath alishaz-polymath marked this pull request as ready for review February 13, 2026 09:39
@graphite-app graphite-app bot added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Feb 13, 2026
@graphite-app graphite-app bot requested a review from a team February 13, 2026 09:39
Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
@devin-ai-integration devin-ai-integration bot changed the title fix: resolve signup watchlist review issues with deleteEntry, email verification ordering, and unlock flow fix: resolve signup watchlist review issues and auto-unlock on SIGNUP entry removal Feb 13, 2026
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/features/watchlist/lib/service/AdminWatchlistOperationsService.ts">

<violation number="1" location="packages/features/watchlist/lib/service/AdminWatchlistOperationsService.ts:224">
P1: Rule violated: **Avoid Logging Sensitive Information**

Remove the email address from error logging to avoid exposing PII in logs (Rule: Avoid Logging Sensitive Information).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 13, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ Pushed commit 0d94a79

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
Copy link
Copy Markdown
Contributor

@emrysal emrysal left a comment

Choose a reason for hiding this comment

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

LGTM!

@emrysal emrysal merged commit 50c7210 into main Feb 13, 2026
54 checks passed
@emrysal emrysal deleted the devin/1770974465-fix-signup-watchlist-issues branch February 13, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e run-ci Approve CI to run for external contributors size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants