# US-MGN002-005: Cambio de Email

## Identificacion

| Campo | Valor |
|-------|-------|
| **ID** | US-MGN002-005 |
| **Modulo** | MGN-002 Users |
| **Sprint** | Sprint 3 |
| **Prioridad** | P1 - Alta |
| **Story Points** | 6 |
| **Estado** | Ready |
| **Autor** | System |
| **Fecha** | 2025-12-06 |
| **RF Asociado** | RF-USER-003 |

---

## Historia de Usuario

**Como** usuario autenticado del sistema
**Quiero** poder cambiar mi direccion de email de forma segura
**Para** mantener mi cuenta actualizada y proteger el acceso a mi informacion

---

## Descripcion

El usuario necesita un proceso seguro para cambiar su email registrado. El sistema debe verificar la identidad del usuario con su password actual y validar la propiedad del nuevo email antes de aplicar el cambio. Esto protege contra cambios no autorizados.

### Contexto

- El email es el identificador principal de login
- Se usa para recuperacion de password y notificaciones
- Requiere doble verificacion por seguridad (password + email)
- Todas las sesiones se invalidan despues del cambio

---

## Criterios de Aceptacion

### Escenario 1: Solicitar cambio de email exitosamente

```gherkin
Given un usuario autenticado con email "viejo@empresa.com"
When solicita cambiar a "nuevo@empresa.com"
  And confirma con su password actual
  And el nuevo email no esta registrado
Then el sistema genera token de verificacion
  And envia email de verificacion a "nuevo@empresa.com"
  And el email actual permanece sin cambios
  And responde con status 200
  And el body contiene "expiresAt" con fecha +24h
```

### Escenario 2: Verificar nuevo email

```gherkin
Given un usuario con solicitud de cambio pendiente
  And un token de verificacion valido (< 24 horas)
When hace clic en enlace de verificacion
Then el sistema actualiza el email del usuario
  And invalida todas las sesiones activas
  And envia notificacion al email anterior
  And redirige al login con mensaje de exito
```

### Escenario 3: Nuevo email ya registrado

```gherkin
Given un email "existente@empresa.com" ya en uso
When un usuario intenta cambiar a ese email
Then el sistema responde con status 409
  And el mensaje es "Email no disponible"
```

### Escenario 4: Password incorrecto

```gherkin
Given un usuario autenticado
When solicita cambio de email con password incorrecto
Then el sistema responde con status 400
  And el mensaje es "Password incorrecto"
  And no se crea solicitud de cambio
```

### Escenario 5: Token de verificacion expirado

```gherkin
Given un token de verificacion emitido hace mas de 24 horas
When el usuario intenta usarlo
Then el sistema responde con status 400
  And el mensaje es "Token expirado, solicita nuevo cambio"
```

### Escenario 6: Cancelar solicitud pendiente

```gherkin
Given un usuario con cambio de email pendiente
When solicita un nuevo cambio
Then la solicitud anterior se invalida
  And se crea nueva solicitud con nuevo token
```

---

## Mockup / Wireframe

```
Pagina: Mi Perfil - Seccion Email
┌──────────────────────────────────────────────────────────────────┐
│  Email actual: juan@empresa.com                                   │
│                                          [Cambiar Email]          │
└──────────────────────────────────────────────────────────────────┘

Modal: Cambiar Email
┌──────────────────────────────────────────────────────────────────┐
│                     CAMBIAR EMAIL                                 │
├──────────────────────────────────────────────────────────────────┤
│                                                                   │
│  Email actual        juan@empresa.com (no editable)              │
│                                                                   │
│  Nuevo email*        [_______________________________]           │
│                                                                   │
│  Confirmar password* [_______________________________]           │
│                                                                   │
│  ⚠️ Se enviara un link de verificacion al nuevo email.           │
│     Tu email no cambiara hasta que verifiques el enlace.         │
│     Todas tus sesiones seran cerradas despues del cambio.        │
│                                                                   │
│  [  Cancelar  ]                    [ Enviar Verificacion ]       │
└──────────────────────────────────────────────────────────────────┘

Pagina: Verificacion Exitosa
┌──────────────────────────────────────────────────────────────────┐
│                                                                   │
│                     ✅ Email Actualizado                          │
│                                                                   │
│     Tu email ha sido cambiado a: nuevo@empresa.com               │
│                                                                   │
│     Por seguridad, todas tus sesiones han sido cerradas.         │
│                                                                   │
│                   [ Ir al Login ]                                 │
│                                                                   │
└──────────────────────────────────────────────────────────────────┘
```

---

## Notas Tecnicas

### API Endpoints

```typescript
// Solicitar cambio de email
POST /api/v1/users/me/email/request-change
{
  "newEmail": "nuevo@empresa.com",
  "currentPassword": "MiPasswordActual123!"
}

// Response 200
{
  "message": "Se ha enviado un email de verificacion a nuevo@empresa.com",
  "expiresAt": "2025-12-07T10:30:00Z"
}

// Response 400 - Password incorrecto
{
  "statusCode": 400,
  "message": "Password incorrecto"
}

// Response 409 - Email existe
{
  "statusCode": 409,
  "message": "Email no disponible"
}

// Verificar cambio de email
GET /api/v1/users/email/verify-change?token=abc123...

// Response 200 (redirect)
// Redirect to: /login?emailChanged=true

// Response 400 - Token invalido
{
  "statusCode": 400,
  "message": "Token invalido o expirado"
}
```

### Permisos Requeridos

| Accion | Permiso |
|--------|---------|
| Solicitar cambio | Autenticado (propio email) |
| Verificar cambio | Token valido |

### Schema de Base de Datos

```sql
CREATE TABLE core_users.email_change_requests (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES core_users.users(id),
  tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id),
  current_email VARCHAR(255) NOT NULL,
  new_email VARCHAR(255) NOT NULL,
  token_hash VARCHAR(255) NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  completed_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  CONSTRAINT uq_pending_email_change UNIQUE (user_id, completed_at)
    WHERE completed_at IS NULL
);

CREATE INDEX idx_email_change_user ON core_users.email_change_requests(user_id);
CREATE INDEX idx_email_change_token ON core_users.email_change_requests(token_hash);
```

---

## Definicion de Done

- [ ] Endpoint POST /api/v1/users/me/email/request-change implementado
- [ ] Endpoint GET /api/v1/users/email/verify-change implementado
- [ ] Tabla email_change_requests creada con RLS
- [ ] Validacion de password actual
- [ ] Validacion de email unico en tenant
- [ ] Generacion de token seguro (32 bytes hex)
- [ ] Envio de email de verificacion
- [ ] Envio de notificacion al email anterior
- [ ] Invalidacion de sesiones post-cambio
- [ ] Frontend: ChangeEmailForm integrado en perfil
- [ ] Frontend: Pagina de verificacion exitosa
- [ ] Tests unitarios (>80% coverage)
- [ ] Tests e2e pasando
- [ ] Code review aprobado

---

## Dependencias

| ID | Descripcion |
|----|-------------|
| RF-USER-001 | CRUD Usuarios (tabla users) |
| RF-AUTH-001 | Login para autenticacion |
| RF-AUTH-004 | Logout para invalidar sesiones |
| EmailService | Para enviar verificacion |

---

## Estimacion

| Tarea | Story Points |
|-------|--------------|
| Database: Tabla email_change_requests | 1 |
| Backend: Endpoint request-change | 1.5 |
| Backend: Endpoint verify-change | 1.5 |
| Backend: Tests | 1 |
| Frontend: ChangeEmailForm | 0.5 |
| Frontend: Pagina verificacion | 0.5 |
| **Total** | **6** |

---

## Reglas de Negocio

| ID | Regla | Validacion |
|----|-------|------------|
| RN-001 | Requiere password actual | Verificacion bcrypt |
| RN-002 | Nuevo email unico en tenant | UNIQUE constraint |
| RN-003 | Token expira en 24 horas | expires_at check |
| RN-004 | Una solicitud activa a la vez | Invalidar anteriores |
| RN-005 | Notificar email anterior | Email de seguridad |
| RN-006 | Logout-all post-cambio | Revocar tokens |
| RN-007 | Formato email valido | Regex validation |

---

## Historial

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