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>
365 lines
17 KiB
Markdown
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)
|