trading-platform/docs/02-definicion-modulos/OQI-001-fundamentos-auth/requerimientos/RF-AUTH-002-email.md
rckrdmrd c1b5081208 feat(ml): Complete FASE 11 - BTCUSD update and comprehensive documentation alignment
ML Engine Updates:
- Updated BTCUSD with Polygon API data (2024-2025): 215,699 new records
- Re-trained all ML models: Attention (R²: 0.223), Base, Metamodel (87.3% confidence)
- Backtest results: +176.71R profit with aggressive_filter strategy

Documentation Consolidation:
- Created docs/99-analisis/_MAP.md index with 13 new analysis documents
- Consolidated inventories: removed duplicates from orchestration/inventarios/
- Updated ML_INVENTORY.yml with BTCUSD metrics and training results
- Added execution reports: FASE11-BTCUSD, correction issues, alignment validation

Architecture & Integration:
- Updated all module documentation with NEXUS v3.4 frontmatter
- Fixed _MAP.md indexes across all folders
- Updated orchestration plans and traces

Files: 229 changed, 5064 insertions(+), 1872 deletions(-)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 09:31:29 -06:00

365 lines
17 KiB
Markdown

---
id: "RF-AUTH-002"
title: "Autenticacion por Email"
type: "Requirement"
status: "Done"
priority: "Alta"
module: "auth"
epic: "OQI-001"
version: "1.0"
created_date: "2025-12-05"
updated_date: "2026-01-04"
---
# RF-AUTH-002: Autenticación por Email
**Version:** 1.0.0
**Fecha:** 2025-12-05
**Estado:** ✅ Implementado
**Prioridad:** P0 (Crítica)
**Épica:** [OQI-001](../_MAP.md)
---
## Descripción
El sistema debe permitir a los usuarios registrarse e iniciar sesión mediante email y contraseña, con verificación de email obligatoria y recuperación de contraseña segura.
---
## Objetivo de Negocio
- Proporcionar método de auth tradicional para usuarios que prefieren no usar OAuth
- Mantener control total sobre las credenciales
- Cumplir con requisitos regulatorios de identificación
---
## Requisitos Funcionales
### RF-AUTH-002.1: Registro
**DEBE:**
1. Aceptar email, contraseña, nombre y apellido
2. Validar formato de email (RFC 5322)
3. Validar política de contraseña
4. Verificar que email no exista en el sistema
5. Hashear contraseña con bcrypt (cost 12)
6. Enviar email de verificación
7. Crear usuario con status `pending_verification`
**NO DEBE:**
1. Almacenar contraseña en texto plano
2. Permitir emails duplicados
3. Revelar si email ya existe (seguridad)
### RF-AUTH-002.2: Verificación de Email
**DEBE:**
1. Generar token único de verificación (64 chars)
2. Almacenar token con TTL de 24 horas
3. Enviar link de verificación por email
4. Validar token al hacer click
5. Marcar email como verificado
6. Invalidar token después de uso
### RF-AUTH-002.3: Login
**DEBE:**
1. Aceptar email y contraseña
2. Verificar que el usuario existe
3. Comparar hash de contraseña
4. Verificar que email está verificado
5. Verificar que cuenta no está bloqueada
6. Generar tokens JWT (access + refresh)
7. Registrar sesión en base de datos
### RF-AUTH-002.4: Recuperación de Contraseña
**DEBE:**
1. Aceptar email del usuario
2. Generar token de reset (64 chars)
3. Almacenar token con TTL de 1 hora
4. Enviar link de recuperación por email
5. Validar token al cambiar contraseña
6. Invalidar todas las sesiones activas
7. Invalidar token después de uso
---
## Política de Contraseña
| Criterio | Requisito |
|----------|-----------|
| Longitud mínima | 8 caracteres |
| Longitud máxima | 128 caracteres |
| Mayúsculas | Al menos 1 |
| Minúsculas | Al menos 1 |
| Números | Al menos 1 |
| Especiales | Al menos 1 (!@#$%^&*) |
| No igual a email | Obligatorio |
| No en lista negra | Opcional (común passwords) |
```typescript
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,128}$/;
```
---
## Flujo de Registro
```
Usuario Frontend Backend DB
│ │ │ │
│─── Completa form ───────▶│ │ │
│ - email │ │ │
│ - password │ │ │
│ - firstName │ │ │
│ - lastName │ │ │
│ - acceptTerms │ │ │
│ │ │ │
│ │─── POST /auth/register ─▶│ │
│ │ │ │
│ │ │─── Check email ───────▶│
│ │ │◀── Not exists ─────────│
│ │ │ │
│ │ │─── Hash password ──────│
│ │ │ │
│ │ │─── INSERT user ───────▶│
│ │ │◀── user created ───────│
│ │ │ │
│ │ │─── Generate token ─────│
│ │ │─── Store in Redis ─────│
│ │ │─── Send email ─────────│
│ │ │ │
│ │◀── 201 Created ──────────│ │
│ │ { message } │ │
│ │ │ │
│◀── "Verifica email" ─────│ │ │
│ │ │ │
│═══ Recibe email ═════════════════════════════════════ │
│ │ │ │
│─── Click link ──────────▶│ │ │
│ │─── GET /verify-email ───▶│ │
│ │ ?token=xxx │ │
│ │ │ │
│ │ │─── Validate token ─────│
│ │ │─── UPDATE verified ───▶│
│ │ │─── Delete token ───────│
│ │ │ │
│ │◀── 200 OK ───────────────│ │
│ │ │ │
│◀── Redirect to login ────│ │ │
```
---
## Flujo de Login
```
Usuario Frontend Backend DB
│ │ │ │
│─── Email + Password ────▶│ │ │
│ │ │ │
│ │─── POST /auth/login ────▶│ │
│ │ │ │
│ │ │─── Find user ─────────▶│
│ │ │◀── user data ──────────│
│ │ │ │
│ │ │─── Compare hash ───────│
│ │ │ │
│ │ │─── Check verified ─────│
│ │ │ │
│ │ │─── Check 2FA ──────────│
│ │ │ │
│ │ │ [Si 2FA enabled] │
│ │◀── 200 requires_2fa ─────│ │
│◀── Show 2FA input ───────│ │ │
│ │ │ │
│ │ │ [Si NO 2FA] │
│ │ │─── Generate JWT ───────│
│ │ │─── Create session ────▶│
│ │ │ │
│ │◀── 200 OK ───────────────│ │
│ │ { tokens, user } │ │
│ │ │ │
│◀── Dashboard ────────────│ │ │
```
---
## Flujo de Recuperación
```
Usuario Frontend Backend DB
│ │ │ │
│─── Email ───────────────▶│ │ │
│ │ │ │
│ │─── POST /forgot-password─▶ │
│ │ │ │
│ │ │─── Find user ─────────▶│
│ │ │◀── user exists ────────│
│ │ │ │
│ │ │─── Generate token ─────│
│ │ │─── Store in Redis ─────│
│ │ │─── Send email ─────────│
│ │ │ │
│ │◀── 200 OK ───────────────│ │
│ │ { message } │ │
│ │ │ │
│◀── "Revisa email" ───────│ │ │
│ │ │ │
│═══ Recibe email ═════════════════════════════════════ │
│ │ │ │
│─── Click link ──────────▶│ │ │
│ │─── GET /reset-password ─▶│ │
│ │ ?token=xxx │ │
│ │ │ │
│◀── Form nueva password ──│ │ │
│ │ │ │
│─── Nueva password ──────▶│ │ │
│ │─── POST /reset-password ▶│ │
│ │ { token, password } │ │
│ │ │ │
│ │ │─── Validate token ─────│
│ │ │─── Hash password ──────│
│ │ │─── UPDATE password ───▶│
│ │ │─── Invalidate sessions▶│
│ │ │─── Delete token ───────│
│ │ │ │
│ │◀── 200 OK ───────────────│ │
│ │ │ │
│◀── Redirect to login ────│ │ │
```
---
## Templates de Email
### Verificación de Email
```html
Asunto: Verifica tu cuenta de Trading Platform
Hola {{firstName}},
Gracias por registrarte en Trading Platform.
Para completar tu registro, verifica tu email haciendo click aquí:
{{verificationUrl}}
Este link expira en 24 horas.
Si no creaste esta cuenta, ignora este email.
Saludos,
Equipo Trading Platform
```
### Recuperación de Contraseña
```html
Asunto: Recupera tu contraseña de Trading Platform
Hola {{firstName}},
Recibimos una solicitud para restablecer tu contraseña.
Haz click aquí para crear una nueva contraseña:
{{resetUrl}}
Este link expira en 1 hora.
Si no solicitaste este cambio, ignora este email.
Tu contraseña actual seguirá funcionando.
Saludos,
Equipo Trading Platform
```
---
## Manejo de Errores
| Error | Código | Mensaje Usuario |
|-------|--------|-----------------|
| Email existe | 409 | Este email ya está registrado |
| Email no encontrado | 401 | Credenciales inválidas |
| Contraseña incorrecta | 401 | Credenciales inválidas |
| Email no verificado | 403 | Por favor verifica tu email |
| Cuenta bloqueada | 403 | Cuenta bloqueada temporalmente |
| Token inválido | 400 | Link inválido o expirado |
| Token expirado | 400 | Link expirado, solicita uno nuevo |
| Password débil | 400 | La contraseña no cumple requisitos |
**Nota:** No revelar si el email existe en errores de login (seguridad).
---
## Bloqueo por Intentos Fallidos
| Intentos | Acción |
|----------|--------|
| 3 | Warning en UI |
| 5 | Bloqueo 15 minutos |
| 10 | Bloqueo 1 hora |
| 15 | Bloqueo 24 horas |
| 20+ | Requiere contactar soporte |
---
## Seguridad
### Password Hashing
```typescript
import bcrypt from 'bcryptjs';
const SALT_ROUNDS = 12;
async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, SALT_ROUNDS);
}
async function verifyPassword(password: string, hash: string): Promise<boolean> {
return bcrypt.compare(password, hash);
}
```
### Token Generation
```typescript
import crypto from 'crypto';
function generateSecureToken(): string {
return crypto.randomBytes(32).toString('hex'); // 64 chars
}
```
---
## Criterios de Aceptación
- [ ] Usuario puede registrarse con email válido
- [ ] Contraseña se valida contra política
- [ ] Email de verificación se envía correctamente
- [ ] Usuario puede verificar email con link
- [ ] Usuario puede hacer login después de verificar
- [ ] Login falla si email no está verificado
- [ ] Usuario puede solicitar recuperación de contraseña
- [ ] Link de recuperación funciona una sola vez
- [ ] Sesiones se invalidan al cambiar contraseña
- [ ] Cuenta se bloquea después de intentos fallidos
---
## Especificación Técnica Relacionada
- [ET-AUTH-002: JWT Tokens](../especificaciones/ET-AUTH-002-jwt.md)
## Historias de Usuario Relacionadas
- [US-AUTH-001: Registro con Email](../historias-usuario/US-AUTH-001-registro-email.md)
- [US-AUTH-002: Login con Email](../historias-usuario/US-AUTH-002-login-email.md)
- [US-AUTH-011: Recuperar Contraseña](../historias-usuario/US-AUTH-011-password-reset.md)