specs/014-email-verification/tasks.md
Rama main · réplica de lectura del repositorio original.
# Email Verification Requirements
## Introduction
Email verification ensures users own the email address they register with. Users receive a verification link after registration and must click it before their account becomes fully active.
## Requirements
### REQ-1: Verification Token Generation
**User Story**: As a system, I want to generate secure verification tokens, so that email verification links cannot be guessed or forged.
**Acceptance Criteria**:
- Generate cryptographically secure random token on registration
- Token stored in database with expiration timestamp
- Token is single-use (invalidated after verification)
- Default expiration: 24 hours (configurable)
### REQ-2: Verification Email
**User Story**: As a new user, I want to receive a verification email after registration, so that I can activate my account.
**Acceptance Criteria**:
- Email sent immediately after registration
- Email contains clickable verification link
- Link format: `{APP_URL}/verify-email?token={token}`
- Email includes expiration information
- Uses existing EmailService infrastructure
### REQ-3: Unverified User State
**User Story**: As a system, I want to restrict unverified users, so that only verified email addresses can access the application.
**Acceptance Criteria**:
- New users created with `emailVerified = false`
- Unverified users cannot login (authentication fails with specific error)
- Unverified users can request new verification email
- JWT token NOT returned on registration (only after verification)
### REQ-4: Email Verification Endpoint
**User Story**: As a user, I want to verify my email by clicking the link, so that my account becomes active.
**Acceptance Criteria**:
- Public GET endpoint `/auth/verify-email?token={token}`
- Valid token: set `emailVerified = true`, delete token, return success
- Expired token: return error with option to resend
- Invalid/used token: return appropriate error
- On success, user can now login and the welcome email is sent to the user
### REQ-6: Registration Flow Change
**User Story**: As a user, I want clear feedback after registration, so that I know to check my email.
**Acceptance Criteria**:
- Registration returns success message (not JWT token)
- Response indicates verification email was sent
- Response includes email address (masked: `j***@example.com`)
### REQ-7: Admin Bypass
**User Story**: As an admin, I want to manually verify users, so that I can help users with email issues.
**Acceptance Criteria**:
- Admin endpoint to set `emailVerified = true`
- Add to existing AdminController
- Analytics event logged for audit
### REQ-8: Configuration
**User Story**: As a developer, I want to configure email verification behavior, so that I can adjust for different environments.
**Acceptance Criteria**:
- `application.email.verification.enabled` - Enable/disable feature (default: true)
- `application.email.verification.expiration-hours` - Token expiration (default: 24)
- When disabled, registration works as before (returns JWT immediately)
## Non-Functional Requirements
### Architecture
- New `EmailVerificationToken` entity with: id, token, userId, expiresAt, createdAt
- New `EmailVerificationTokenRepository`
- Extend `User` entity with `emailVerified` boolean field
- New Flyway migration for schema changes
- Verification logic in `AuthenticationService` or new `EmailVerificationService`
### Security
- Tokens must be cryptographically random (use `SecureRandom`)
- Tokens should be URL-safe (Base64 URL encoding)
- Token length: minimum 32 bytes
- Tokens stored hashed in database (like passwords)
- Rate limiting on resend endpoint to prevent abuse
- Verification endpoint should not leak user existence
### Database Changes
- Add `email_verified` column to users table (BOOLEAN, NOT NULL, DEFAULT FALSE)
- New `email_verification_tokens` table:
- id (UUID, PK)
- user_id (UUID, FK to users)
- token_hash (VARCHAR, indexed)
- expires_at (TIMESTAMP)
- created_at (TIMESTAMP)
### API Design
- `POST /auth/register` - Returns message, not token
- `GET /auth/verify-email?token={token}` - Verify email
- `POST /auth/resend-verification` - Request new verification email
- `PUT /admin/users/{id}/verify-email` - Admin manual verification
### Email Template
- Template name: `email_verification`
- Variables: fullName, verificationLink, expirationHours, domain
- Clear call-to-action button
- Expiration warning