Skip to content

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • added db fallback for chat otp, redis path unchanged

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

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

@vercel
Copy link

vercel bot commented Dec 25, 2025

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Dec 25, 2025 5:23pm

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Dec 25, 2025

Greptile Summary

Replaces unreliable in-memory OTP storage with database-backed fallback using the existing verification table. The Redis path remains unchanged for deployments with Redis configured.

Key changes:

  • Database storage uses chat-otp:${chatId}:${email} as identifier (different from Redis key format otp:${email}:${chatId})
  • storeOTP() uses a transaction to delete old entries before inserting new OTP
  • getOTP() filters by identifier and checks expiration in the query using gt(verification.expiresAt, now)
  • deleteOTP() removes OTP after successful verification
  • Comprehensive test coverage validates both storage paths behave consistently

Benefits:

  • Eliminates single-instance constraint of in-memory storage
  • Enables multi-instance/serverless deployments without Redis
  • Maintains same 15-minute expiry across both storage methods

Confidence Score: 4/5

  • Safe to merge with one minor race condition concern already flagged in previous review
  • The implementation is solid with proper transaction usage, expiration handling, and comprehensive test coverage. The main concern is the non-atomic delete-then-insert pattern in storeOTP which creates a small race condition window, though this was already noted in the previous thread.
  • apps/sim/app/api/chat/[identifier]/otp/route.ts - review the transaction pattern at lines 44-54

Important Files Changed

Filename Overview
apps/sim/app/api/chat/[identifier]/otp/route.ts replaced in-memory OTP storage with database fallback using verification table; maintains Redis as primary storage
apps/sim/app/api/chat/[identifier]/otp/route.test.ts comprehensive test coverage for both Redis and database storage paths

Sequence Diagram

sequenceDiagram
    participant Client
    participant API as OTP Route
    participant Storage as getStorageMethod()
    participant Redis
    participant DB as Database (verification)
    participant Email as Email Service

    Note over Client,Email: POST - Request OTP
    Client->>API: POST /api/chat/[identifier]/otp<br/>{email}
    API->>DB: Query chat by identifier
    DB-->>API: Return chat config
    API->>API: Validate email against allowedEmails
    API->>API: Generate 6-digit OTP
    API->>Storage: Check storage method
    alt Redis Storage
        Storage-->>API: "redis"
        API->>Redis: SET otp:email:chatId (EX 900)
        Redis-->>API: OK
    else Database Storage
        Storage-->>API: "database"
        API->>DB: BEGIN TRANSACTION
        API->>DB: DELETE verification WHERE identifier=chat-otp:chatId:email
        API->>DB: INSERT verification (id, identifier, value, expiresAt)
        API->>DB: COMMIT TRANSACTION
        DB-->>API: Success
    end
    API->>Email: Send OTP email
    Email-->>API: Success
    API-->>Client: 200 {message: "Verification code sent"}

    Note over Client,Email: PUT - Verify OTP
    Client->>API: PUT /api/chat/[identifier]/otp<br/>{email, otp}
    API->>DB: Query chat by identifier
    DB-->>API: Return chat config
    API->>Storage: Check storage method
    alt Redis Storage
        Storage-->>API: "redis"
        API->>Redis: GET otp:email:chatId
        Redis-->>API: stored OTP
    else Database Storage
        Storage-->>API: "database"
        API->>DB: SELECT * FROM verification<br/>WHERE identifier=chat-otp:chatId:email<br/>AND expiresAt > now
        DB-->>API: Return OTP record
    end
    API->>API: Compare stored OTP with provided OTP
    alt OTP Valid
        API->>Storage: Check storage method
        alt Redis Storage
            API->>Redis: DEL otp:email:chatId
        else Database Storage
            API->>DB: DELETE verification WHERE identifier
        end
        API->>API: Set auth cookie
        API-->>Client: 200 {authenticated: true}
    else OTP Invalid
        API-->>Client: 400 {error: "Invalid verification code"}
    end
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1 waleedlatif1 merged commit f604ca3 into staging Dec 25, 2025
11 checks passed
@waleedlatif1 waleedlatif1 deleted the sim-495 branch December 25, 2025 17:37
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.

2 participants