# US-MGN001-004: Recuperacion de Password

## Identificacion

| Campo | Valor |
|-------|-------|
| **ID** | US-MGN001-004 |
| **Modulo** | MGN-001 Auth |
| **Sprint** | Sprint 2 |
| **Prioridad** | P1 - Alta |
| **Story Points** | 8 |
| **Estado** | Ready |
| **Autor** | System |
| **Fecha** | 2025-12-05 |

---

## Historia de Usuario

**Como** usuario que olvido su contraseña
**Quiero** poder recuperar el acceso a mi cuenta mediante un proceso seguro
**Para** no quedar bloqueado del sistema sin necesidad de contactar soporte

---

## Descripcion

El usuario que olvido su contraseña debe poder solicitar un enlace de recuperacion por email. Este enlace le permitira establecer una nueva contraseña de forma segura, invalidando el acceso anterior.

### Contexto

- Los usuarios olvidan contraseñas con frecuencia
- El proceso debe ser autoservicio
- Debe ser seguro contra ataques de enumeracion de emails

---

## Criterios de Aceptacion

### Escenario 1: Solicitud de recuperacion exitosa

```gherkin
Given un usuario registrado con email "user@example.com"
When solicita recuperacion de password en POST /api/v1/auth/password/request-reset
Then el sistema responde con status 200
  And el mensaje es "Si el email esta registrado, recibiras instrucciones"
  And se genera un token de recuperacion con expiracion de 1 hora
  And se envia email con enlace de recuperacion
  And tokens anteriores de ese usuario son invalidados
```

### Escenario 2: Solicitud para email inexistente (seguridad)

```gherkin
Given un email "noexiste@example.com" que NO existe en el sistema
When solicita recuperacion de password
Then el sistema responde con status 200
  And el mensaje es IDENTICO al caso exitoso
  And NO se revela que el email no existe
  And NO se envia ningun email
```

### Escenario 3: Cambio de password exitoso

```gherkin
Given un usuario con token de recuperacion valido
  And el token no ha expirado (<1 hora)
  And el token no ha sido usado
When envia nuevo password cumpliendo requisitos
Then el sistema actualiza el password hasheado
  And invalida el token de recuperacion
  And cierra TODAS las sesiones activas del usuario
  And envia email confirmando el cambio
  And responde con status 200
```

### Escenario 4: Token de recuperacion expirado

```gherkin
Given un token de recuperacion emitido hace mas de 1 hora
When el usuario intenta usarlo
Then el sistema responde con status 400
  And el mensaje es "Token de recuperacion expirado"
```

### Escenario 5: Token ya utilizado

```gherkin
Given un token de recuperacion que ya fue usado
When el usuario intenta usarlo nuevamente
Then el sistema responde con status 400
  And el mensaje es "Token de recuperacion ya utilizado"
```

### Escenario 6: Password no cumple requisitos

```gherkin
Given un token de recuperacion valido
When el usuario envia un password que no cumple requisitos
  | Escenario | Password | Error |
  | Muy corto | "abc123" | "Password debe tener minimo 8 caracteres" |
  | Sin mayuscula | "password123!" | "Debe incluir una mayuscula" |
  | Sin numero | "Password!!" | "Debe incluir un numero" |
  | Sin especial | "Password123" | "Debe incluir caracter especial" |
Then el sistema responde con status 400
  And el mensaje indica el requisito faltante
  And se incrementa el contador de intentos del token
```

### Escenario 7: Password igual a anterior

```gherkin
Given un token de recuperacion valido
  And el usuario tiene historial de passwords
When envia un password igual a uno de los ultimos 5
Then el sistema responde con status 400
  And el mensaje es "No puedes usar una contraseña anterior"
```

### Escenario 8: Validacion de token

```gherkin
Given un token de recuperacion
When el usuario navega a la pagina de reset con ese token
Then el frontend valida el token GET /api/v1/auth/password/validate-token/:token
  And si es valido muestra el formulario
  And si no es valido muestra mensaje de error apropiado
```

---

## Mockup / Wireframe

### Pagina de Solicitud

```
+------------------------------------------------------------------+
|                         ERP SUITE                                 |
+------------------------------------------------------------------+
|                                                                   |
|              ╔═══════════════════════════════════╗               |
|              ║    RECUPERAR CONTRASEÑA           ║               |
|              ╚═══════════════════════════════════╝               |
|                                                                   |
|              Ingresa tu correo electronico y te enviaremos       |
|              instrucciones para restablecer tu contraseña.       |
|                                                                   |
|              Correo electronico                                  |
|              +---------------------------+                       |
|              | user@example.com          |                       |
|              +---------------------------+                       |
|                                                                   |
|              [===== ENVIAR INSTRUCCIONES =====]                  |
|                                                                   |
|              ← Volver al login                                   |
|                                                                   |
+------------------------------------------------------------------+
```

### Confirmacion de Envio

```
+------------------------------------------------------------------+
|                         ERP SUITE                                 |
+------------------------------------------------------------------+
|                                                                   |
|              ╔═══════════════════════════════════╗               |
|              ║         EMAIL ENVIADO ✉️          ║               |
|              ╚═══════════════════════════════════╝               |
|                                                                   |
|              Si el email esta registrado, recibiras             |
|              instrucciones en los proximos minutos.              |
|                                                                   |
|              Revisa tu bandeja de entrada y la carpeta           |
|              de spam.                                             |
|                                                                   |
|              [===== VOLVER AL LOGIN =====]                       |
|                                                                   |
|              ¿No recibiste el email?                             |
|              Espera 5 minutos y vuelve a intentar.               |
|                                                                   |
+------------------------------------------------------------------+
```

### Pagina de Reset

```
+------------------------------------------------------------------+
|                         ERP SUITE                                 |
+------------------------------------------------------------------+
|                                                                   |
|              ╔═══════════════════════════════════╗               |
|              ║    NUEVA CONTRASEÑA               ║               |
|              ╚═══════════════════════════════════╝               |
|                                                                   |
|              Nueva contraseña                                    |
|              +---------------------------+                       |
|              | ••••••••••••             |  [👁]                  |
|              +---------------------------+                       |
|              [████████░░] Fuerte                                 |
|                                                                   |
|              ✓ Minimo 8 caracteres                               |
|              ✓ Al menos una mayuscula                            |
|              ✗ Al menos un numero                                |
|              ✗ Al menos un caracter especial                     |
|                                                                   |
|              Confirmar contraseña                                |
|              +---------------------------+                       |
|              | ••••••••••••             |  [👁]                  |
|              +---------------------------+                       |
|                                                                   |
|              [===== CAMBIAR CONTRASEÑA =====]                    |
|                                                                   |
+------------------------------------------------------------------+
```

### Token Invalido

```
+------------------------------------------------------------------+
|                         ERP SUITE                                 |
+------------------------------------------------------------------+
|                                                                   |
|              ╔═══════════════════════════════════╗               |
|              ║      ⚠️ ENLACE INVALIDO           ║               |
|              ╚═══════════════════════════════════╝               |
|                                                                   |
|              El enlace de recuperacion ha expirado               |
|              o ya fue utilizado.                                 |
|                                                                   |
|              [===== SOLICITAR NUEVO ENLACE =====]                |
|                                                                   |
+------------------------------------------------------------------+
```

---

## Notas Tecnicas

### API

```typescript
// 1. Solicitar recuperacion
POST /api/v1/auth/password/request-reset
{
  "email": "user@example.com"
}
// Response 200
{
  "message": "Si el email esta registrado, recibiras instrucciones"
}

// 2. Validar token
GET /api/v1/auth/password/validate-token/a1b2c3d4e5f6...
// Response 200 (valido)
{
  "valid": true,
  "email": "u***@example.com"
}
// Response 200 (invalido)
{
  "valid": false,
  "reason": "expired" | "used" | "invalid"
}

// 3. Cambiar password
POST /api/v1/auth/password/reset
{
  "token": "a1b2c3d4e5f6...",
  "newPassword": "NewSecurePass123!",
  "confirmPassword": "NewSecurePass123!"
}
// Response 200
{
  "message": "Contraseña actualizada exitosamente"
}
```

### Template de Email

```html
Asunto: Recuperacion de contraseña - ERP Suite

<h2>Hola {{firstName}},</h2>

<p>Recibimos una solicitud para restablecer tu contraseña.</p>

<p>Haz clic en el siguiente enlace para crear una nueva contraseña:</p>

<a href="{{resetUrl}}" style="...">Restablecer Contraseña</a>

<p><strong>Este enlace expira en 1 hora.</strong></p>

<p>Si no solicitaste este cambio, ignora este email. Tu contraseña
permanecera sin cambios.</p>

<p>Por seguridad, nunca compartas este enlace con nadie.</p>

<hr>
<small>IP: {{ipAddress}} | Fecha: {{timestamp}}</small>
```

### Validaciones de Password

```typescript
const PASSWORD_RULES = {
  minLength: 8,
  maxLength: 128,
  requireUppercase: true,
  requireLowercase: true,
  requireNumber: true,
  requireSpecial: true,
  specialChars: '!@#$%^&*()_+-=[]{}|;:,.<>?',
  historyCount: 5, // No repetir ultimos 5
};

const PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
```

---

## Definicion de Done

- [ ] Endpoint POST /api/v1/auth/password/request-reset implementado
- [ ] Endpoint GET /api/v1/auth/password/validate-token/:token implementado
- [ ] Endpoint POST /api/v1/auth/password/reset implementado
- [ ] Token de 256 bits generado con crypto.randomBytes
- [ ] Token hasheado antes de almacenar
- [ ] Email de recuperacion enviado
- [ ] Validacion de politica de password
- [ ] Historial de passwords implementado
- [ ] Logout-all despues de cambio
- [ ] Email de confirmacion enviado
- [ ] Frontend: ForgotPasswordPage
- [ ] Frontend: ResetPasswordPage
- [ ] Frontend: Password strength indicator
- [ ] Tests unitarios (>80% coverage)
- [ ] Tests e2e pasando
- [ ] Code review aprobado

---

## Dependencias

### Requiere

| Item | Descripcion |
|------|-------------|
| EmailService | Para enviar emails |
| Tabla password_reset_tokens | Almacenar tokens |
| Tabla password_history | Historial de passwords |
| US-MGN001-002 | Logout-all functionality |

### Bloquea

| Item | Descripcion |
|------|-------------|
| - | No bloquea otras historias |

---

## Estimacion

| Tarea | Horas |
|-------|-------|
| Backend: requestPasswordReset() | 3h |
| Backend: validateResetToken() | 2h |
| Backend: resetPassword() | 4h |
| Backend: Password validation | 2h |
| Backend: Email templates | 2h |
| Backend: Tests | 3h |
| Frontend: ForgotPasswordPage | 3h |
| Frontend: ResetPasswordPage | 4h |
| Frontend: Password strength | 2h |
| Frontend: Tests | 2h |
| **Total** | **27h** |

---

## Referencias

- [RF-AUTH-005](../../01-requerimientos/RF-auth/RF-AUTH-005.md) - Requerimiento funcional
- [ET-auth-backend](../../02-modelado/especificaciones-tecnicas/ET-auth-backend.md) - Spec tecnica

---

## Historial

| Version | Fecha | Autor | Cambios |
|---------|-------|-------|---------|
| 1.0 | 2025-12-05 | System | Creacion inicial |
