Auth
User Registration
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-001 | Register with email, password, and phone | Not logged in, at /register | 1. Enter email "newuser@example.com" 2. Enter full name "John Doe" 3. Enter phone "+1234567890" 4. Enter password "SecurePass123!" 5. Confirm password "SecurePass123!" 6. Enter organization name "Acme Corp" 7. Click "Sign Up" button | Success toast appears. User redirected to /verify. Email and phone verification gates shown. | High |
| AUTH-002 | Register with Google OAuth | Not logged in, at /register | 1. Click "Continue with Google" button 2. Complete Google OAuth flow in popup | User redirected to /chat after OAuth success. Account created with Google email and name. | High |
| AUTH-003 | Validation: passwords do not match | Not logged in, at /register | 1. Fill all fields with valid data 2. Enter password "SecurePass123!" 3. Enter confirm password "DifferentPass456!" 4. Click "Sign Up" | Error message "Passwords do not match." displayed below confirm password field. Form not submitted. | High |
| AUTH-004 | Validation: invalid phone number | Not logged in, at /register | 1. Fill all fields with valid data 2. Enter phone number "123" (invalid format) 3. Click "Sign Up" | Error message "Please enter a valid mobile number." displayed. Form not submitted. | High |
| AUTH-005 | Validation: email already exists | Not logged in, at /register. Email "existing@example.com" already registered | 1. Enter email "existing@example.com" 2. Fill all other fields 3. Click "Sign Up" | Error message displayed: "Email already registered." User remains on /register form. | High |
| AUTH-006 | Validation: required fields empty | Not logged in, at /register | 1. Leave email field empty 2. Click "Sign Up" | HTML5 validation: "Please fill in this field." shown on email input. Form not submitted. | Medium |
| AUTH-007 | Validation: weak password | Not logged in, at /register | 1. Fill all fields 2. Enter password "123" (too weak) 3. Click "Sign Up" | Error displayed (if backend enforces password policy): "Password does not meet security requirements." | Medium |
| AUTH-008 | Rate limit: multiple registration attempts | Not logged in, at /register | 1. Attempt to register 6 times in quick succession (within 1 hour) | After 5 successful attempts, 6th attempt shows error: "Too many registration attempts. Please try again later." | Medium |
User Login
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-009 | Login with email and password | Not logged in, user registered, at /login | 1. Enter email "user@example.com" in identifier field 2. Enter password "SecurePass123!" 3. Click "Sign In" | Success toast "Logged in successfully." User redirected to /chat. Access and refresh tokens stored as httponly cookies. | High |
| AUTH-010 | Login with phone and password | Not logged in, user registered with phone, at /login | 1. Enter phone number "+1234567890" in identifier field 2. Enter password "SecurePass123!" 3. Click "Sign In" | User logged in and redirected to /chat. | High |
| AUTH-011 | Login with Google OAuth | Not logged in, user has Google account linked, at /login | 1. Click "Sign In with Google" button 2. Complete Google OAuth flow | User redirected to /chat. Session authenticated. | High |
| AUTH-012 | Login: invalid credentials | Not logged in, at /login | 1. Enter email "user@example.com" 2. Enter password "WrongPassword123" 3. Click "Sign In" | Error message displayed: "Invalid email or password." User remains on /login. No tokens set. | High |
| AUTH-013 | Login: account suspended | Not logged in, user account suspended, at /login | 1. Enter email "suspended@example.com" 2. Enter correct password 3. Click "Sign In" | User account_status is 'suspended'. User redirected to /account-locked page instead of /chat. | High |
| AUTH-014 | Login: account deactivated | Not logged in, user account deactivated, at /login | 1. Enter email "deactivated@example.com" 2. Enter correct password 3. Click "Sign In" | User account_status is 'deactivated'. User redirected to /account-locked page. | High |
| AUTH-015 | Login: non-existent email | Not logged in, at /login | 1. Enter email "nonexistent@example.com" 2. Enter any password 3. Click "Sign In" | Error message displayed: "Invalid email or password." (does not reveal whether account exists). | High |
| AUTH-016 | Validation: empty email field | Not logged in, at /login | 1. Leave email field empty 2. Click "Sign In" | HTML5 validation error: "Please fill in this field." Form not submitted. | Medium |
| AUTH-017 | Validation: empty password field | Not logged in, at /login | 1. Enter email "user@example.com" 2. Leave password empty 3. Click "Sign In" | HTML5 validation error: "Please fill in this field." Form not submitted. | Medium |
| AUTH-018 | Password visibility toggle | Not logged in, at /login | 1. Click in password field 2. Type "SecurePass123" 3. Click eye icon to show password | Password text becomes visible (input type changes to "text"). Eye icon changes to crossed-eye icon. | Low |
| AUTH-019 | Rate limit: multiple login attempts | Not logged in, at /login | 1. Attempt login with wrong password 11 times within 15 minutes | After 10 failed attempts, 11th attempt shows error: "Too many login attempts. Please try again in a few minutes." Further login attempts blocked for 15 min. | Medium |
| AUTH-020 | Error message display: Google sign-in failed | Not logged in, redirected from Google with error, at /login?error=google_failed | 1. Page loads | Error message displayed: "Google sign-in failed. Please try again." | Low |
Password Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-021 | Forgot password: email sent | Not logged in, at /forgot-password | 1. Enter email "user@example.com" 2. Click "Send Reset Link" | Success page shown: "Check your inbox" message. Email sent to "user@example.com" with password reset link. | High |
| AUTH-022 | Forgot password: non-existent email | Not logged in, at /forgot-password | 1. Enter email "nonexistent@example.com" 2. Click "Send Reset Link" | Same success page shown as AUTH-021 (does not reveal whether email exists). No email sent. | High |
| AUTH-023 | Forgot password: rate limit | Not logged in, at /forgot-password | 1. Attempt to send reset link 6 times in 1 hour | After 5 attempts, 6th attempt shows error: "Too many password reset requests. Please try again later." | Medium |
| AUTH-024 | Reset password: valid token | Not logged in, email verification token valid, at /reset-password?token=VALID_TOKEN | 1. Click password reset link from email | Page loads with password reset form. Token auto-verified in background. | High |
| AUTH-025 | Reset password: new password set | Valid password reset token in URL, at /reset-password?token=VALID_TOKEN | 1. Enter new password "NewSecure123!" 2. Confirm password "NewSecure123!" 3. Click "Reset Password" | Success message shown. User redirected to /login. Old password no longer works; new password allows login. | High |
| AUTH-026 | Reset password: token expired | Password reset token expired, at /reset-password?token=EXPIRED_TOKEN | 1. Page loads | Error message shown: "Verification link is invalid or has expired." Link to /forgot-password provided. | High |
| AUTH-027 | Reset password: invalid token | Password reset token malformed, at /reset-password?token=INVALID | 1. Page loads | Error message shown: "Verification link is invalid or has expired." | High |
| AUTH-028 | Reset password: passwords do not match | Valid password reset token, at /reset-password?token=VALID_TOKEN | 1. Enter password "NewSecure123!" 2. Enter confirm password "Different456!" 3. Click "Reset Password" | Error message: "Passwords do not match." Form not submitted. | Medium |
| AUTH-029 | Change password: logged in user | Logged in user, at /settings or account page (requires navigation) | 1. Go to account settings 2. Click "Change Password" 3. Enter current password "OldPass123!" 4. Enter new password "NewPass456!" 5. Confirm new password "NewPass456!" 6. Click "Change Password" | Success toast shown: "Password changed successfully." | High |
| AUTH-030 | Change password: wrong current password | Logged in user, at password change form | 1. Enter current password "WrongPassword" 2. Enter new password "NewPass456!" 3. Confirm "NewPass456!" 4. Click "Change Password" | Error message: "Current password is incorrect." Password not changed. | High |
Email Verification
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-031 | Email verification: auto-submit on verify link click | Registered user, email unverified, at /verify-email?token=VALID_TOKEN | 1. Click email verification link from inbox | Page shows "Verifying your email..." spinner briefly. Success icon and "Email verified!" message shown. After 1.5 seconds, redirected to /verify (phone gate) or /chat (if phone also verified). | High |
| AUTH-032 | Email verification: invalid token | At /verify-email?token=INVALID_TOKEN | 1. Page loads | Error page shown: "Verification failed. Verification link is invalid or has expired." Link to /verify provided. | High |
| AUTH-033 | Email verification: expired token | At /verify-email?token=EXPIRED_TOKEN | 1. Page loads | Error page shown: "Verification failed. Verification link is invalid or has expired." | High |
| AUTH-034 | Email verification: missing token in URL | At /verify-email without token parameter | 1. Page loads | Error page shown: "Verification failed. Invalid verification link." | High |
| AUTH-035 | Email verification: resend verification email | Logged in user at /verify, email unverified | 1. Click "Resend verification email" link | Success toast shown: "Verification email sent." Email resent to user email. Resend button disabled for 60 seconds with countdown. | High |
| AUTH-036 | Email verification gate: user stays on /verify until email verified | Logged in user with email unverified, at /verify | 1. Attempt to navigate to /chat directly (via URL bar) | User redirected back to /verify. Cannot access app until email verified. | High |
Phone Verification
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-037 | Phone OTP: request OTP sent | Logged in user at /verify, email verified, phone unverified | 1. Page shows phone verification form 2. OTP auto-requested on page load | OTP sent to user's phone via WhatsApp. Message shows "Enter the 6-digit code sent to your phone." | High |
| AUTH-038 | Phone OTP: valid 6-digit code | Logged in user at /verify with OTP sent | 1. Receive OTP "123456" on WhatsApp 2. Enter digits "123456" in 6 OTP input fields 3. OTP auto-submits after 6th digit entered | Success toast shown. User redirected to /chat. phone_verified flag set to true. | High |
| AUTH-039 | Phone OTP: auto-focus on next field | Logged in user at /verify, OTP form displayed | 1. Click 1st OTP input 2. Type "1" 3. Focus auto-moves to 2nd input | 2nd input field focused. Cursor visible in 2nd field. | Low |
| AUTH-040 | Phone OTP: backspace to previous field | Logged in user at /verify, OTP form with partial input | 1. Focus is on 3rd OTP input 2. Press Backspace on empty 3rd input | Focus moves to 2nd input field. | Low |
| AUTH-041 | Phone OTP: paste all 6 digits at once | Logged in user at /verify, OTP form focused on 1st input | 1. Copy "123456" from clipboard 2. Paste into OTP field (Ctrl+V) | All 6 digits populated across all fields automatically. Paste event prevented from default. | Low |
| AUTH-042 | Phone OTP: non-numeric input rejected | Logged in user at /verify, OTP form | 1. Click OTP input 2. Type "abc123!" | Only numeric characters "123" accepted. Non-numeric chars filtered out. | Low |
| AUTH-043 | Phone OTP: invalid code | Logged in user at /verify, wrong OTP code entered | 1. Enter OTP "999999" 2. Form auto-submits after 6 digits | Error message shown: "Invalid OTP. Please try again." Fields cleared. Resend option available. | High |
| AUTH-044 | Phone OTP: resend OTP | Logged in user at /verify, OTP expired or not received | 1. Wait 10 seconds 2. Click "Resend OTP" button | OTP resent to WhatsApp. Button disabled for 60 seconds with countdown timer. Success message shown: "OTP sent." | High |
| AUTH-045 | Phone OTP: rate limit on resend | Logged in user at /verify, attempted resend 11 times | 1. Click "Resend OTP" 11 times rapidly | After 10 successful resends within 15 minutes, 11th attempt shows error: "Too many OTP requests. Please try again later." Resend blocked. | Medium |
| AUTH-046 | Phone OTP: skip phone verification (optional) | Logged in user at /verify with email verified, phone optional | 1. Click "Skip for now" button (if available) | User redirected to /chat. Phone verification can be completed later from settings. | Medium |
| AUTH-047 | Phone verification gate: user must verify phone | Logged in user with email verified, phone unverified | 1. Try to navigate to /chat | User redirected to /verify. Phone verification required before app access. | High |
Session & Token Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-048 | Cookies set after login | User logs in | 1. Complete login flow | Browser dev tools > Application > Cookies shows: - access_token cookie (httponly, secure, samesite=lax, max_age = ACCESS_TOKEN_EXPIRE_MINUTES * 60) - refresh_token cookie (httponly, secure, samesite=lax, max_age = REFRESH_TOKEN_EXPIRE_DAYS * 86400) | High |
| AUTH-049 | Access token expiry | Logged in user, access token near expiry | 1. Wait for access token to expire 2. Make API request to protected endpoint | Request fails with 401. Refresh token automatically used to obtain new access token. Request retried. User session continues without logout. | High |
| AUTH-050 | Refresh token expiry | Logged in user, refresh token expired | 1. Wait for refresh token to expire 2. Make API request | Request fails with 401. User redirected to /login. Must re-authenticate. | High |
| AUTH-051 | Logout clears cookies | Logged in user at /chat | 1. Click account menu > "Logout" 2. Confirm logout | Access and refresh token cookies deleted. User redirected to /login. No longer authenticated. | High |
| AUTH-052 | Silent refresh on route navigation | Logged in user with near-expiry access token, navigating pages | 1. Access token expires in 30 seconds 2. User clicks link to different page 3. Refresh happens automatically | Page loads successfully without user seeing 401 error. Refresh is silent (no loading indicator). | Medium |
Organization & Member Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-053 | Organization created on registration | User completes registration | 1. Register new account with org name "Acme Corp" 2. Complete verification | Organization "Acme Corp" created. User is default owner/admin of org. user_role = "admin" in UserOrganization. | High |
| AUTH-054 | List organizations for user | Logged in user member of 2 orgs | 1. (Backend call simulated) Fetch /auth/me | Response includes organizations array with both org details. | High |
| AUTH-055 | Invite member to organization | Logged in as Admin, at /settings > Members | 1. Click "Invite Member" button 2. Enter email "newmember@example.com" 3. Select role "Agent" from dropdown 4. Click "Send Invite" | Success toast: "Invite sent to newmember@example.com." Invitation email sent with acceptance link. Member listed as "Pending" until they accept. | High |
| AUTH-056 | Invite validation: invalid email | Logged in as Admin, at invite form | 1. Enter email "notanemail" 2. Click "Send Invite" | Error: "Please enter a valid email address." Form not submitted. | High |
| AUTH-057 | Invite validation: already member | Logged in as Admin, inviting existing member | 1. Enter email of current member 2. Click "Send Invite" | Error: "User is already a member of this organization." | Medium |
| AUTH-058 | Accept invitation | Invited user receives email with acceptance link, at /invites/accept?token=VALID_TOKEN | 1. Click acceptance link in email | Page auto-processes acceptance. Success message shown: "Invitation accepted!" User now appears as active member in org. Can access org in app. | High |
| AUTH-059 | Accept invitation: invalid token | At /invites/accept?token=INVALID_TOKEN | 1. Page loads | Error message: "Invalid or expired invitation link." | High |
| AUTH-060 | Accept invitation: already accepted | At /invites/accept?token=ALREADY_USED_TOKEN | 1. Page loads | Error message: "This invitation has already been used." | Medium |
| AUTH-061 | Remove member from organization | Logged in as Admin, at /settings > Members list, member "John" visible | 1. Click row for "John" 2. Click "Remove Member" button 3. Confirm in modal | Success toast: "Member removed." John no longer appears in members list. John can no longer access org; sees "Access denied" if attempting. | High |
| AUTH-062 | Update member role | Logged in as Admin, at /settings > Members, member "John" has role "Agent" | 1. Click row for "John" 2. Click role dropdown (showing "Agent") 3. Select "Manager" 4. Click "Save" | Success toast: "Role updated." John's role now displays as "Manager". John's permissions change accordingly. | High |
| AUTH-063 | Permission boundary: Agent cannot manage members | Logged in as Agent, at /settings | 1. Navigate to Members section 2. Look for "Invite Member" button | "Invite Member" button not visible or disabled. Members list visible but not editable. | High |
| AUTH-064 | Permission boundary: Agent cannot update org settings | Logged in as Agent, at /settings > Organization | 1. Attempt to click "Edit" on org name or settings fields | Edit controls not available. Settings displayed as read-only. Error if attempting direct API call: "Permission denied: manage_organization required." | High |
Profile & Settings
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-065 | Get current user profile (/auth/me) | Logged in user | 1. (Backend call simulated) Fetch /auth/me | Response includes: user object (id, email, full_name, phone, avatar_url, is_active, email_verified, phone_verified, is_superadmin), organizations array, permissions array, current_org_id | High |
| AUTH-066 | Update user profile | Logged in user, at /settings > Profile | 1. Click "Edit Profile" 2. Change full_name to "Jane Smith" 3. Upload avatar image 4. Click "Save" | Success toast: "Profile updated." full_name and avatar_url updated. Changes reflected in UI (account menu, profile page). | High |
| AUTH-067 | Update profile: email change | Logged in user, at profile settings | 1. Change email to "newemail@example.com" 2. Click "Save" | Email change requested. Verification email sent to newemail@example.com. Current email remains active until new email verified. "Email verification required" banner shown. | High |
| AUTH-068 | Update org settings | Logged in as Admin, at /settings > Organization | 1. Change org name to "Acme Corp Global" 2. Update description 3. Click "Save" | Success toast: "Organization updated." Org name and description changed. Change visible to all members. | High |
| AUTH-069 | Update org settings: permission check | Logged in as Agent, at /settings > Organization | 1. Attempt to edit org name field | Field disabled or not editable. API call attempt returns: "Permission denied: manage_organization required." (or HTTP 403). | High |
Role & Permission Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-070 | List all roles in organization | Logged in as Admin with manage_organization permission, at /settings > Roles | 1. Navigate to Roles section 2. Page loads | List of roles displayed: system roles (Admin, Agent, Manager) and custom roles if any. Each role shows name, description, is_system_role badge, member count. | High |
| AUTH-071 | Get single role with permissions | Logged in as Admin, at /settings > Roles > "Agent" role | 1. Click on "Agent" role | Role detail panel opens showing: id, name, description, is_system_role, permissions list (e.g., "contacts:read", "messages:write"). | High |
| AUTH-072 | Create custom role | Logged in as Admin with roles:write permission, at /settings > Roles | 1. Click "Create Role" button 2. Enter name "Team Lead" 3. Enter description "Team lead permissions" 4. Click "Create" | Success toast: "Role created." New role "Team Lead" appears in list. is_system_role = false. No permissions assigned yet. | High |
| AUTH-073 | Update role metadata | Logged in as Admin, editing custom role | 1. Click on custom role "Team Lead" 2. Edit description to "Updated description" 3. Click "Save" | Success toast: "Role updated." Description changed. Cannot update system role metadata (e.g., "Admin" role not editable). | High |
| AUTH-074 | Cannot modify system roles | Logged in as Admin, viewing "Admin" system role | 1. Click on "Admin" role 2. Attempt to edit description or name 3. Try to submit changes | Edit controls disabled or "Read-only system role" message shown. Update attempt returns error: "Cannot modify system roles." | High |
| AUTH-075 | Update role permissions | Logged in as Admin, editing custom role "Team Lead" | 1. Click on "Team Lead" role 2. Scroll to Permissions section 3. Check "messages:read", "messages:write", "contacts:read" 4. Uncheck "reports:admin" 5. Click "Save Permissions" | Success toast: "Permissions updated." Selected permissions now assigned to role. Members with this role gain/lose access accordingly. | High |
| AUTH-076 | List all available permissions | Logged in user with roles:read permission | 1. (Backend call simulated) Fetch /roles/permissions/all | Response includes all permission objects: id, name, description (e.g., "contacts:read", "messages:write", "reports:admin"). | Medium |
| AUTH-077 | Permission propagation to user | User assigned to role with specific permissions | 1. User logs in 2. Make API request to protected endpoint requiring "messages:write" 3. User has role "Agent" which includes "messages:write" permission | API request succeeds (user has permission). | High |
| AUTH-078 | Permission denial for missing permission | User assigned to role without permission | 1. User logs in 2. Make API request to protected endpoint requiring "reports:admin" 3. User has role "Agent" (no "reports:admin") | API request fails with 403 Forbidden. Frontend shows: "Permission denied. Contact your admin." | High |
Google OAuth Integration
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-079 | Google OAuth: new user registration flow | Not logged in, at /register | 1. Click "Continue with Google" button 2. Google OAuth popup appears 3. Sign in with Google account (e.g., john@gmail.com) 4. Authorize app permissions | Popup closes. User logged in and redirected to /chat (or /verify if first-time setup required). New user account created with google_id linked. Email pre-filled from Google. | High |
| AUTH-080 | Google OAuth: existing user login | Not logged in, user already has Google linked, at /login | 1. Click "Sign In with Google" 2. Google OAuth flow completes 3. User approves (re-auth) | User logged in and redirected to /chat. Same access/refresh tokens set. | High |
| AUTH-081 | Google OAuth: link to existing account | Logged in user without Google linked | 1. At /settings > Connected Accounts 2. Click "Link Google Account" 3. Complete Google OAuth | Success message: "Google account linked." google_id stored on user. Can now login via Google. | Medium |
| AUTH-082 | Google OAuth: error handling | At /login or /register, Google OAuth fails | 1. Click "Continue with Google" 2. Google auth server returns error (user denies, network error) | User redirected back to /login?error=google_failed. Error message shown: "Google sign-in failed. Please try again." | High |
Account Status & Restrictions
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-083 | Suspended account cannot login | User account suspended by admin | 1. Attempt login with suspended user credentials 2. Click "Sign In" | Login succeeds technically, but user.account_status = 'suspended'. User redirected to /account-locked (not /chat). Message: "Your account has been suspended. Contact support." | High |
| AUTH-084 | Deactivated account cannot login | User account deactivated | 1. Attempt login with deactivated user credentials 2. Click "Sign In" | Login attempt succeeds, but account_status = 'deactivated'. User redirected to /account-locked. Message: "Your account has been deactivated." | High |
| AUTH-085 | Active account can login normally | User account with status 'active' | 1. Attempt login with correct credentials | Login succeeds. User redirected to /chat. account_status = 'active'. | High |
Trial & Subscription
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-086 | Start trial on first login | New user completes registration | 1. Complete registration and email/phone verification 2. User redirected to /chat | Trial started. Organization has trial_started_at set. trial_ends_at = current_time + trial_duration_days. User can access all features during trial. | High |
| AUTH-087 | Trial expiration warning | User with trial expiring in 3 days | 1. User logs in 2. Navigates to /chat | Banner shown at top: "Your trial expires in 3 days. Upgrade to continue." Upgrade link provided. | Medium |
| AUTH-088 | Trial expired: access denied | User with trial expired, no active subscription | 1. User logs in 2. Attempts to use paid features (e.g., send message) | Feature blocked. Modal shown: "Trial has expired. Upgrade to continue using this feature." Upgrade button provided. | High |
Audit & Security Logging
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-089 | Login audit logged | User logs in | 1. User logs in successfully 2. (Backend: audit log created) | Audit log entry created: action="user.login", resource_type="user", resource_id=user_id, outcome="success", ip_address captured. | Medium |
| AUTH-090 | Failed login audit logged | User fails login | 1. User attempts login with wrong password | Audit log entry created: action="user.login", outcome="failure", failure_reason="Invalid credentials", ip_address captured. | Medium |
| AUTH-091 | Role change audit logged | Admin updates member role | 1. Admin changes user role from "Agent" to "Manager" 2. Click "Save" | Audit log entry created: action="role.updated", resource_type="role", metadata includes role_id, new_role, ip_address. | Medium |
| AUTH-092 | Invite sent audit logged | Admin invites member | 1. Admin sends invite to newmember@example.com | Audit log entry created: action="invite.sent", resource_type="invite", invitee_email, inviter_id, ip_address. | Medium |
Edge Cases & Recovery
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| AUTH-093 | Duplicate registration attempt | Email already registered, at /register | 1. Enter registered email 2. Enter password and confirm 3. Click "Sign Up" | Error: "Email already registered." User directed to /login instead. | Medium |
| AUTH-094 | Session timeout | Logged in user, session idle > REFRESH_TOKEN_EXPIRE_DAYS | 1. User inactive for entire refresh token lifespan 2. User attempts API call | 401 Unauthorized. Refresh token invalid. User redirected to /login. Must re-authenticate. | High |
| AUTH-095 | Concurrent login from different device | User logs in from Device A, then Device B | 1. User logs in on Device A 2. User logs in on Device B | Both sessions valid and active. User can operate simultaneously on both devices (unless explicit "single session" policy enforced). | Low |
| AUTH-096 | Email verification resend cooldown | User clicks "Resend Email" multiple times rapidly | 1. Click "Resend Email" 2. Immediately click again 3. Click again | After 1st email sent, resend button disabled for 60 seconds. Subsequent clicks show countdown timer. Only 1 email sent per 60-second window. | Low |
| AUTH-097 | User deleted: attempt login with deleted email | User account deleted | 1. Attempt login with formerly registered email | Login fails: "Invalid email or password." (does not reveal account was deleted). | Medium |