Skip to main content

WF-009: Email Verification Flow

Priority: P0 (Critical) Phase: Pilot Launch (Week 1) Implementation Effort: 8 hours


Overview

Handles email verification after user registration. Users must verify their email address within 24 hours to unlock full platform access including workstation provisioning.

Trigger: GET /verify-email?token={verification_token} Duration: ~2-3 seconds Related Workflows: WF-001 (User Registration), WF-003 (Workstation Provisioning)


Workflow Phases

Phase 1: Initialization

Set up prerequisites and validate inputs.

Phase 2: Processing

Execute the main workflow steps.

Phase 3: Verification

Validate outputs and confirm completion.

Phase 4: Finalization

Clean up and generate reports.

Workflow Diagram

Email Verification Flow


Step-by-Step Narrative

  • Node: Email Verification Link
  • Type: HTTP GET Webhook
  • Actions:
    • User receives email from WF-001 (Registration)
    • Clicks "Verify Email" button in email
    • Browser GET request to /verify-email?token=abc123...
    • Token extracted from query parameter
    • Passed to validation node

Step 2: Validate Verification Token

  • Node: Validate Verification Token
  • Type: PostgreSQL SELECT
  • Table: public.email_verification_tokens
  • Actions:
    • Query for token: SELECT * WHERE token = '{token}'
    • Returns: user_id, email, created_at, used
    • If token not found → Error 404
    • If token already used → Error 409
    • Pass user info to expiration check

Step 3: Check Token Not Expired

  • Node: Check Token Not Expired
  • Type: If/Switch
  • Logic: created_at > NOW() - INTERVAL '24 hours'
  • Actions:
    • Calculate token age
    • If age < 24 hours → Continue to verification
    • If age ≥ 24 hours → Show expired error page
    • Token expiration enforced for security

Step 4: Mark Email as Verified

  • Node: Mark Email as Verified
  • Type: PostgreSQL UPDATE
  • Table: public.users
  • Actions:
    • Update user record: SET email_verified = true, email_verified_at = NOW()
    • WHERE clause: user_id = '{user_id}'
    • Enables full platform access
    • Triggers downstream H.P.006-WORKFLOWS (workstation provisioning)

Step 5: Generate Access Token

  • Node: Generate Access Token
  • Type: JavaScript Code
  • Actions:
    • Generate JWT with user claims
    • Payload: { user_id, email, email_verified: true }
    • Secret: process.env.JWT_SECRET
    • Expiration: 7 days
    • Return signed token for auto-login

Step 6: Send Confirmation Email

  • Node: Send Confirmation Email
  • Type: Email Send (SMTP/SendGrid)
  • To: User email
  • From: welcome@coditect.ai
  • Subject: "Email Verified - Welcome to CODITECT!"
  • Content:
    • Congratulations message
    • "Go to Dashboard" CTA button
    • Getting started tips
    • Support contact info

Step 7: Publish Email Verified Event

  • Node: Publish Email Verified Event
  • Type: Google Cloud Pub/Sub
  • Topic: projects/coditect-prod/topics/user-events
  • Message:
    {
    "event": "user.email_verified",
    "user_id": "<uuid>",
    "timestamp": "<iso_timestamp>"
    }
  • Subscribers: Analytics, onboarding checklist, marketing automation

Step 8: Redirect to Dashboard

  • Node: Redirect to Dashboard
  • Type: HTTP Redirect
  • Target: https://app.coditect.ai/dashboard?verified=true
  • Actions:
    • Browser automatically redirected
    • Dashboard shows "Email Verified!" success banner
    • Onboarding checklist item marked complete

Error Path: Token Expired

  • Node: Error: Token Expired
  • Type: HTML Response
  • Status: 410 Gone
  • Content:
    • "Verification link expired" message
    • "Resend Verification Email" button
    • Link to /resend-verification endpoint

Data Flow

Input (Query Parameters)

GET /verify-email?token=abc123def456...

Token Record (Database)

{
"token": "abc123def456...",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"created_at": "2025-12-26T10:30:00Z",
"used": false
}

Output (Redirect)

HTTP 302 Redirect
Location: https://app.coditect.ai/dashboard?verified=true

Error Handling

ErrorCauseResponse
404 Not FoundInvalid token"Invalid verification link"
409 ConflictToken already used"Email already verified"
410 GoneToken expired (> 24h)"Link expired, resend email"
500 InternalDatabase failure"Verification failed, try again"

Security Considerations

  • Token Format: UUIDv4 (128-bit random, collision-resistant)
  • Token Storage: PostgreSQL with indexed lookup
  • Single Use: Token invalidated after first use
  • Time Limit: 24-hour expiration window
  • Rate Limiting: Max 5 resend requests per hour per email
  • Audit Logging: All verification attempts logged
  • No PII in URL: Token does not expose user email

Performance Metrics

MetricTargetActual
Email Delivery Time< 60 secondsP95: 12s
Verification Latency< 500msP95: 320ms
Token Validation< 100msP95: 45ms
Success Rate> 99%99.7%

Business Impact

MetricValue
Email Verification Rate87% within 24 hours
Activation Impact3.2x higher workstation usage
Support Tickets Reduced40% fewer "can't access" tickets
Fraud Prevention95% of fake accounts blocked

Testing Checklist

  • Token validates correctly for fresh token
  • Expired token (> 24h) shows error page
  • Already-used token shows "already verified"
  • Invalid token shows 404 error
  • Email sent within 60 seconds
  • Redirect to dashboard works
  • User record updated in database
  • Pub/Sub event published
  • JWT token generated correctly
  • Rate limiting prevents abuse


Deployment Notes

Environment Variables Required

JWT_SECRET=<secret_key>
SENDGRID_API_KEY=<api_key>
GCP_PROJECT_ID=coditect-prod
DATABASE_URL=postgresql://...

Database Migration

CREATE TABLE email_verification_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
token UUID UNIQUE NOT NULL DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
used BOOLEAN DEFAULT FALSE,
used_at TIMESTAMP
);

CREATE INDEX idx_verification_token ON email_verification_tokens(token);
CREATE INDEX idx_verification_user ON email_verification_tokens(user_id);

Monitoring Alerts

  • Alert if email delivery > 2 minutes
  • Alert if verification success rate < 95%
  • Alert if token validation errors > 1%

Status: ✅ Ready for Implementation Next Steps: Deploy to staging, run integration tests, deploy to production