# US-AUTH-009: Autenticación con WhatsApp

**Version:** 1.0.0
**Fecha:** 2025-12-05
**Estado:** Pendiente
**Story Points:** 3
**Prioridad:** P2 (Media)
**Épica:** [OQI-001](../_MAP.md)

---

## Historia de Usuario

**Como** usuario de OrbiQuant
**Quiero** poder registrarme e iniciar sesión recibiendo el código por WhatsApp
**Para** usar una aplicación que ya tengo instalada y me resulta más familiar que SMS

---

## Criterios de Aceptación

### AC-001: Opción de WhatsApp

**Dado** que estoy en la pantalla de ingreso de teléfono
**Cuando** ingreso mi número
**Entonces** debería ver dos opciones:
- "Enviar por SMS"
- "Enviar por WhatsApp"
**Y** debería poder seleccionar mi preferencia

### AC-002: Validación de WhatsApp

**Dado** que seleccioné la opción de WhatsApp
**Cuando** hago click en "Enviar código"
**Entonces** el sistema debería:
1. Verificar que el número tiene WhatsApp activo
2. Si no tiene WhatsApp, mostrar mensaje y ofrecer SMS
3. Si tiene WhatsApp, enviar el código

### AC-003: Mensaje de WhatsApp

**Dado** que solicité código por WhatsApp
**Cuando** recibo el mensaje
**Entonces** debería tener el formato:
```
¡Hola! 👋

Tu código de verificación de OrbiQuant es:

*123456*

Válido por 10 minutos.
No compartas este código con nadie.

OrbiQuant - Inversiones Inteligentes
```

### AC-004: Código recibido

**Dado** que recibí el código por WhatsApp
**Cuando** vuelvo a la app e ingreso el código
**Entonces** debería funcionar igual que con SMS
**Y** completar el registro o login

### AC-005: WhatsApp no disponible

**Dado** que mi número no tiene WhatsApp activo
**Cuando** intento usar la opción de WhatsApp
**Entonces** debería ver un mensaje:
- "Este número no tiene WhatsApp activo"
**Y** debería ver botón "Enviar por SMS"

### AC-006: Fallback a SMS

**Dado** que seleccioné WhatsApp pero el envío falló
**Cuando** ocurre un error en WhatsApp
**Entonces** debería:
1. Ver mensaje "No pudimos enviar por WhatsApp"
2. Ver opción "Enviar por SMS"
3. Poder continuar con SMS sin reingresar el número

### AC-007: Preferencia guardada

**Dado** que usé WhatsApp exitosamente
**Cuando** vuelvo a hacer login
**Entonces** WhatsApp debería ser la opción preseleccionada

### AC-008: Rate limiting compartido

**Dado** que solicité códigos por SMS y WhatsApp
**Cuando** sumo los intentos
**Entonces** debería contar ambos hacia el límite de 5 por hora

---

## Mockup

```
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│          🌟 Ingresa con tu número de teléfono              │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ Número de teléfono                                   │   │
│  │ ┌────────┐ ┌──────────────────────────────────────┐ │   │
│  │ │ 🇺🇸 +1 ▾│ │ (555) 123-4567                       │ │   │
│  │ └────────┘ └──────────────────────────────────────┘ │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ¿Cómo quieres recibir el código?                          │
│                                                             │
│  ┌─────────────────────────┐ ┌─────────────────────────┐   │
│  │   📱 SMS                │ │   💬 WhatsApp           │   │
│  └─────────────────────────┘ └─────────────────────────┘   │
│                   (Recomendado - más rápido)                │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │               Enviar código                          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Mensaje de WhatsApp:
┌─────────────────────────────────────────────────────────────┐
│  WhatsApp                                        🔍 ⋮       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ◀ OrbiQuant                                          ✓✓    │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ ¡Hola! 👋                                             │  │
│  │                                                       │  │
│  │ Tu código de verificación de OrbiQuant es:           │  │
│  │                                                       │  │
│  │ *123456*                                              │  │
│  │                                                       │  │
│  │ Válido por 10 minutos.                                │  │
│  │ No compartas este código con nadie.                   │  │
│  │                                                       │  │
│  │ OrbiQuant - Inversiones Inteligentes                  │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                      15:42  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Pantalla si WhatsApp no disponible:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│          ⚠️ WhatsApp no disponible                         │
│                                                             │
│  Este número no tiene WhatsApp activo.                     │
│  ¿Quieres recibir el código por SMS?                       │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │               Enviar por SMS                         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ← Cambiar número                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

---

## Tareas Técnicas

### Database (DB)

- [ ] Agregar campo a tabla `users`:
  ```sql
  ALTER TABLE users ADD COLUMN preferred_auth_channel VARCHAR(20) DEFAULT 'sms';
  -- Valores: 'sms', 'whatsapp'
  ```
- [ ] Agregar campo a `phone_verification_codes`:
  ```sql
  ALTER TABLE phone_verification_codes
  ADD COLUMN channel VARCHAR(20) DEFAULT 'sms';
  -- Valores: 'sms', 'whatsapp'
  ```

### Backend (BE)

- [ ] Configurar WhatsApp Business API o Twilio WhatsApp
- [ ] Endpoint `POST /api/v1/auth/phone/send-code` (modificar)
  - Agregar parámetro `channel: 'sms' | 'whatsapp'`
  - Verificar si número tiene WhatsApp (usando Twilio Lookup)
  - Enviar por canal seleccionado
- [ ] Service `WhatsAppService`
  - `hasWhatsApp(phoneNumber)`
  - `sendVerificationCode(phoneNumber, code)`
  - `formatMessage(code)`
- [ ] Librería: `twilio` SDK (WhatsApp support)
- [ ] Fallback automático a SMS si WhatsApp falla
- [ ] Tests unitarios (8 casos)
- [ ] Tests de integración con mock

### Frontend (FE)

- [ ] Modificar `PhoneAuth.tsx`
  - Agregar selector de canal (SMS/WhatsApp)
  - Mostrar logo de WhatsApp
  - Manejo de error si WhatsApp no disponible
- [ ] Recordar preferencia del usuario
- [ ] Tests con React Testing Library

### Testing (QA)

- [ ] E2E: Registro con WhatsApp
- [ ] E2E: WhatsApp no disponible (fallback a SMS)
- [ ] E2E: Error en WhatsApp (fallback a SMS)
- [ ] E2E: Preferencia guardada
- [ ] Test de integración con Twilio WhatsApp Sandbox
- [ ] Mock de Twilio Lookup API

---

## Dependencias

- **Bloqueantes:**
  - US-AUTH-008: Infraestructura de SMS ya implementada
  - Twilio WhatsApp habilitado (requiere aprobación de Meta)
  - WhatsApp Business Profile aprobado

- **Alternativa:**
  - Usar Twilio WhatsApp Sandbox para desarrollo
  - Solicitar WhatsApp Business API access para producción

---

## Definition of Ready (DoR)

- [ ] Twilio WhatsApp configurado
- [ ] WhatsApp Business Profile creado
- [ ] Message templates aprobados por Meta (para producción)
- [ ] Mockups aprobados
- [ ] API contract definido

---

## Definition of Done (DoD)

- [ ] Código implementado y revisado
- [ ] Tests unitarios con 80%+ cobertura
- [ ] Tests de integración pasando
- [ ] Tests E2E implementados
- [ ] Twilio WhatsApp configurado en todos los ambientes
- [ ] Fallback a SMS funcional
- [ ] Documentación actualizada
- [ ] Logs y monitoring
- [ ] QA aprobado en staging
- [ ] Deploy a producción exitoso

---

## Notas Técnicas

### WhatsApp vs SMS

**Ventajas de WhatsApp:**
- Más familiar para usuarios
- Gratis para el usuario
- Mayor tasa de apertura
- Confirmación de entrega y lectura
- Soporte para rich media

**Desventajas:**
- Requiere número verificado de WhatsApp Business
- Proceso de aprobación de Meta
- Templates deben ser pre-aprobados (producción)
- No todos tienen WhatsApp

### Twilio WhatsApp Integration

```typescript
import twilio from 'twilio';

const client = twilio(accountSid, authToken);

// Verificar si número tiene WhatsApp
const lookup = await client.lookups.v2
  .phoneNumbers(phoneNumber)
  .fetch({ fields: 'line_type_intelligence' });

const hasWhatsApp = lookup.lineTypeIntelligence?.type === 'whatsapp';

// Enviar mensaje por WhatsApp
await client.messages.create({
  body: `¡Hola! 👋\n\nTu código de verificación de OrbiQuant es:\n\n*${code}*\n\nVálido por 10 minutos.\nNo compartas este código con nadie.\n\nOrbiQuant - Inversiones Inteligentes`,
  from: 'whatsapp:+14155238886', // Twilio WhatsApp number
  to: `whatsapp:${phoneNumber}`
});
```

### Environment Variables

```env
TWILIO_WHATSAPP_NUMBER=whatsapp:+14155238886
TWILIO_WHATSAPP_ENABLED=true
```

### Development: WhatsApp Sandbox

Para desarrollo, Twilio ofrece un Sandbox que no requiere aprobación:

1. Usuario debe enviar un mensaje join code a Twilio Sandbox
2. Luego puede recibir mensajes
3. Útil para testing pero no para producción

### Production: WhatsApp Business API

Para producción:

1. Solicitar WhatsApp Business API access
2. Crear WhatsApp Business Profile
3. Verificar número de teléfono
4. Crear y aprobar message templates
5. Esperar aprobación de Meta (puede tardar días)

### Message Templates (Producción)

En producción, WhatsApp requiere templates pre-aprobados:

```
Template Name: verification_code
Category: AUTHENTICATION
Language: es

Body:
¡Hola! 👋

Tu código de verificación de OrbiQuant es:

*{{1}}*

Válido por 10 minutos.
No compartas este código con nadie.

OrbiQuant - Inversiones Inteligentes
```

### Fallback Strategy

```typescript
async function sendVerificationCode(phone, code, channel) {
  try {
    if (channel === 'whatsapp') {
      // Verificar si tiene WhatsApp
      const hasWhatsApp = await whatsappService.hasWhatsApp(phone);

      if (!hasWhatsApp) {
        // Automáticamente usar SMS
        return await smsService.sendCode(phone, code);
      }

      // Intentar enviar por WhatsApp
      return await whatsappService.sendCode(phone, code);
    } else {
      // Usar SMS
      return await smsService.sendCode(phone, code);
    }
  } catch (error) {
    // Si WhatsApp falla, fallback a SMS
    logger.warn('WhatsApp failed, falling back to SMS', { phone, error });
    return await smsService.sendCode(phone, code);
  }
}
```

### Cost Comparison

- SMS: ~$0.0075 USD por mensaje
- WhatsApp: ~$0.005 USD por mensaje (más barato)
- WhatsApp también tiene mejor deliverability

### Security Considerations

- Mismo código puede usarse para SMS o WhatsApp
- Rate limiting compartido entre canales
- Validar que el canal solicitado sea válido
- Logs separados por canal para auditoría
- Fallback automático mantiene seguridad

---

## Requerimientos Relacionados

- [RF-AUTH-004: Autenticación por Teléfono](../requerimientos/RF-AUTH-004-phone.md)

## Especificaciones Relacionadas

- [ET-AUTH-002: JWT Tokens](../especificaciones/ET-AUTH-002-jwt.md)
- [ET-AUTH-005: Phone Authentication](../especificaciones/ET-AUTH-005-phone.md)
