feat(auth): implement user self-deactivation with email verification
Summary of Changes
Implemented a secure, two-step User Account Self-Deactivation flow with email verification in compliance with the strict 5-layer architecture and audit safety standards.
Business & Security Invariants
-
Two-Step Verification Flow:
-
POST /api/v1/auth/deactivate/request: Requires authenticated user session, validates current password via bcrypt, derives a time-limited (15-minute) signed JWT token bound topasswordHash(purpose: "deactivate-account"), and dispatches a verification email. -
POST /api/v1/auth/deactivate/confirm: Cryptographically verifies the token, marks user as inactive (isActive = false,deletedAt = NOW(),deletedBy = userId), revokes sessions, and clears client authentication cookies.
-
-
Zero Token Leakage:
- The deactivation token is handled strictly inside the service layer and sent via the email service. It is never returned in API responses or leaked across architectural layers.
-
Sole Admin Lockout Protection:
- Deactivation requests and confirmations are rejected with a validation error if the requesting user is the last remaining active Admin in the system, preventing accidental orphan administrative lockout.
-
Comprehensive Revocation via Atomic Transaction:
- Executes inside a database transaction:
- Soft-deletes user record (
isActive = false,deletedAt = NOW(),deletedBy = userId). - Deletes all active refresh tokens for the user.
- Deactivates all associated API keys (
isActive = false). - Deactivates all associated crawl schedules (
isActive = false).
- Soft-deletes user record (
- Executes inside a database transaction:
-
Strict Layering & Zero Hardcode Compliance:
- Only repository interacts with the database.
- Utilizes shared domain constants for roles and audit actions without hardcoded string literals.