Last Updated: February 25, 2026
This document provides detailed sequence diagrams for all authentication and user management flows in Herald. Each diagram shows the exact interactions between components.
User visits a TC app (A, B, or C) without an active session and needs to log in.
sequenceDiagram
actor User
participant App as TC App<br/>(todayscarolinian.com)
participant Herald as Herald<br/>(herald.todayscarolinian.com)
participant MW as Herald Middleware
participant API as Auth Microservice API
participant Firebase as Firebase Auth
participant Firestore as Cloud Firestore
participant Redis as Vercel KV<br/>(Rate Limiting)
User->>App: Visit todayscarolinian.com/articles
App->>App: Check for session cookie
Note over App: No session cookie found
App->>Herald: Redirect to /login?redirect=https://todayscarolinian.com/articles
Herald->>User: Display login page
User->>Herald: Submit email + password + rememberMe
Herald->>API: POST /api/auth/login {email, password, rememberMe}
API->>Redis: Check rate limit for email
alt Rate limit exceeded
Redis-->>API: Rate limit exceeded
API-->>Herald: 429 Too Many Requests
Herald-->>User: Show "Too many attempts" error
else Within rate limit
Redis-->>API: OK (increment counter)
API->>Firebase: signInWithEmailAndPassword()
alt Invalid credentials
Firebase-->>API: Auth error
API->>Redis: Increment failed attempts
API-->>Herald: 401 Unauthorized
Herald-->>User: Show "Invalid credentials" error
else Valid credentials
Firebase-->>API: Return ID token + user object
API->>Firestore: Get user document /users/{uid}
Firestore-->>API: User profile + position
alt Email not verified
API-->>Herald: 403 Email not verified
Herald-->>User: Show "Please verify email" message
else Must change password
API->>API: Set session cookie
API-->>Herald: 200 OK {mustChangePassword: true}
Herald->>Herald: Redirect to /first-login
else Normal login
API->>Redis: Clear failed attempts counter
API->>Firestore: Update lastLoginAt timestamp
API->>Firestore: Create audit log: login_success
API->>API: Set session cookie<br/>domain: .todayscarolinian.com<br/>maxAge: rememberMe ? 30d : 5d
API-->>Herald: 200 OK {user, redirectUrl}
Herald->>App: Redirect to original URL
App->>App: Verify session cookie
App->>Firestore: Fetch user profile (cached)
App-->>User: Display authenticated page
end
end
end
domain: .todayscarolinian.com for SSOmustChangePassword is trueNewly created user logs in with temporary password and must change it immediately.