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>
455 lines
17 KiB
Markdown
455 lines
17 KiB
Markdown
---
|
|
id: "US-AUTH-008"
|
|
title: "Autenticacion con SMS (Twilio)"
|
|
type: "User Story"
|
|
status: "To Do"
|
|
priority: "Alta"
|
|
epic: "OQI-001"
|
|
story_points: 5
|
|
created_date: "2025-12-05"
|
|
updated_date: "2026-01-04"
|
|
---
|
|
|
|
# US-AUTH-008: Autenticación con SMS (Twilio)
|
|
|
|
**Version:** 1.0.0
|
|
**Fecha:** 2025-12-05
|
|
**Estado:** Pendiente
|
|
**Story Points:** 5
|
|
**Prioridad:** P1 (Alta)
|
|
**Épica:** [OQI-001](../_MAP.md)
|
|
|
|
---
|
|
|
|
## Historia de Usuario
|
|
|
|
**Como** usuario de Trading Platform
|
|
**Quiero** poder registrarme e iniciar sesión usando mi número de teléfono y un código SMS
|
|
**Para** tener un acceso rápido sin necesidad de recordar contraseñas
|
|
|
|
---
|
|
|
|
## Criterios de Aceptación
|
|
|
|
### AC-001: Formulario de teléfono
|
|
|
|
**Dado** que estoy en la página de registro/login
|
|
**Cuando** selecciono la opción de teléfono
|
|
**Entonces** debería ver:
|
|
- Selector de país con banderas (+1, +52, +34, etc.)
|
|
- Campo para número de teléfono
|
|
- Formato visual según el país seleccionado
|
|
- Botón "Enviar código"
|
|
|
|
### AC-002: Validación de número
|
|
|
|
**Dado** que ingreso un número de teléfono
|
|
**Cuando** el número no es válido para el país seleccionado
|
|
**Entonces** debería ver un mensaje de error
|
|
**Y** el botón "Enviar código" debería estar deshabilitado
|
|
|
|
### AC-003: Envío de código SMS
|
|
|
|
**Dado** que ingresé un número válido
|
|
**Cuando** hago click en "Enviar código"
|
|
**Entonces** debería:
|
|
1. Ver un mensaje "Enviando código..."
|
|
2. Recibir un SMS con un código de 6 dígitos
|
|
3. Ver pantalla de verificación de código
|
|
4. El código debería expirar en 10 minutos
|
|
|
|
### AC-004: Formato del SMS
|
|
|
|
**Dado** que solicité un código
|
|
**Cuando** recibo el SMS
|
|
**Entonces** debería tener el formato:
|
|
```
|
|
Tu código de Trading Platform es: 123456
|
|
|
|
Válido por 10 minutos.
|
|
No compartas este código.
|
|
```
|
|
|
|
### AC-005: Ingreso de código
|
|
|
|
**Dado** que recibí el código por SMS
|
|
**Cuando** ingreso el código en la app
|
|
**Entonces** debería:
|
|
- Autoformatear con espacios (123 456)
|
|
- Auto-enviar al completar 6 dígitos
|
|
- Validar el código en tiempo real
|
|
|
|
### AC-006: Código correcto - Primer registro
|
|
|
|
**Dado** que es mi primera vez usando este número
|
|
**Cuando** ingreso el código correcto
|
|
**Entonces** debería:
|
|
1. Ver formulario para completar perfil (nombre, apellido, email opcional)
|
|
2. Crear mi cuenta
|
|
3. Recibir un JWT token
|
|
4. Ser redirigido al dashboard
|
|
|
|
### AC-007: Código correcto - Login existente
|
|
|
|
**Dado** que ya tengo una cuenta con este número
|
|
**Cuando** ingreso el código correcto
|
|
**Entonces** debería:
|
|
1. Iniciar sesión automáticamente
|
|
2. Recibir un JWT token
|
|
3. Ser redirigido al dashboard
|
|
|
|
### AC-008: Código incorrecto
|
|
|
|
**Dado** que ingreso un código incorrecto
|
|
**Cuando** envío el código
|
|
**Entonces** debería:
|
|
- Ver mensaje "Código incorrecto"
|
|
- Poder intentar nuevamente
|
|
- Después de 3 intentos fallidos, invalidar el código
|
|
- Poder solicitar un nuevo código
|
|
|
|
### AC-009: Código expirado
|
|
|
|
**Dado** que pasaron más de 10 minutos desde el envío
|
|
**Cuando** intento usar el código
|
|
**Entonces** debería ver mensaje "Código expirado"
|
|
**Y** debería poder solicitar un nuevo código
|
|
|
|
### AC-010: Reenvío de código
|
|
|
|
**Dado** que no recibí el código o expiró
|
|
**Cuando** hago click en "Reenviar código"
|
|
**Entonces** debería:
|
|
- Esperar 60 segundos antes de permitir reenvío
|
|
- Ver contador regresivo "Reenviar en 59s..."
|
|
- Recibir un nuevo código (el anterior se invalida)
|
|
|
|
### AC-011: Rate limiting
|
|
|
|
**Dado** que solicité 5 códigos en 1 hora
|
|
**Cuando** intento solicitar otro
|
|
**Entonces** debería ver mensaje:
|
|
- "Demasiados intentos. Intenta en 1 hora"
|
|
|
|
### AC-012: Número ya registrado con email
|
|
|
|
**Dado** que mi número ya está vinculado a una cuenta de email
|
|
**Cuando** completo la verificación SMS
|
|
**Entonces** debería iniciar sesión en esa cuenta
|
|
**Y** tener ambos métodos de autenticación disponibles
|
|
|
|
---
|
|
|
|
## Mockup
|
|
|
|
```
|
|
Paso 1: Ingreso de teléfono
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ 🌟 Ingresa con tu número de teléfono │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ Número de teléfono │ │
|
|
│ │ ┌────────┐ ┌──────────────────────────────────────┐ │ │
|
|
│ │ │ 🇺🇸 +1 ▾│ │ (555) 123-4567 │ │ │
|
|
│ │ └────────┘ └──────────────────────────────────────┘ │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ Enviar código │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ─────────────────── O continúa con ─────────────────── │
|
|
│ │
|
|
│ [Email] [Google] [Facebook] [Apple] │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
Paso 2: Verificación de código
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ 📱 Ingresa el código que enviamos │
|
|
│ │
|
|
│ Enviamos un código a +1 (555) 123-4567 │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ │
|
|
│ │ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ 5 │ │ 6 │ │ │
|
|
│ │ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ │ │
|
|
│ │ │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ¿No recibiste el código? │
|
|
│ Reenviar código (disponible en 58s) │
|
|
│ │
|
|
│ ← Cambiar número │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
Paso 3: Completar perfil (solo registro nuevo)
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ 🎉 ¡Bienvenido! Completa tu perfil │
|
|
│ │
|
|
│ ┌────────────────────────┐ ┌────────────────────────┐ │
|
|
│ │ Nombre │ │ Apellido │ │
|
|
│ │ ┌──────────────────┐ │ │ ┌──────────────────┐ │ │
|
|
│ │ │ Juan │ │ │ │ Pérez │ │ │
|
|
│ │ └──────────────────┘ │ │ └──────────────────┘ │ │
|
|
│ └────────────────────────┘ └────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ Email (opcional) │ │
|
|
│ │ ┌─────────────────────────────────────────────────┐ │ │
|
|
│ │ │ juan@email.com │ │ │
|
|
│ │ └─────────────────────────────────────────────────┘ │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ☑ Acepto los Términos de Servicio │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ Crear mi cuenta │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Tareas Técnicas
|
|
|
|
### Database (DB)
|
|
|
|
- [ ] Agregar campos a tabla `users`:
|
|
```sql
|
|
ALTER TABLE users ADD COLUMN phone_number VARCHAR(20) UNIQUE;
|
|
ALTER TABLE users ADD COLUMN phone_verified_at TIMESTAMP;
|
|
ALTER TABLE users ADD COLUMN phone_country_code VARCHAR(5);
|
|
```
|
|
- [ ] Tabla `phone_verification_codes`:
|
|
```sql
|
|
CREATE TABLE phone_verification_codes (
|
|
id UUID PRIMARY KEY,
|
|
phone_number VARCHAR(20) NOT NULL,
|
|
code VARCHAR(6) NOT NULL,
|
|
attempts INT DEFAULT 0,
|
|
expires_at TIMESTAMP NOT NULL,
|
|
used_at TIMESTAMP,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
INDEX idx_phone_expires (phone_number, expires_at)
|
|
);
|
|
```
|
|
- [ ] Tabla `phone_rate_limits`:
|
|
```sql
|
|
CREATE TABLE phone_rate_limits (
|
|
id UUID PRIMARY KEY,
|
|
phone_number VARCHAR(20) NOT NULL,
|
|
ip_address VARCHAR(45),
|
|
attempts INT DEFAULT 1,
|
|
window_start TIMESTAMP DEFAULT NOW(),
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
INDEX idx_phone_window (phone_number, window_start)
|
|
);
|
|
```
|
|
|
|
### Backend (BE)
|
|
|
|
- [ ] Configurar cuenta de Twilio
|
|
- [ ] Obtener Account SID y Auth Token
|
|
- [ ] Configurar Twilio Phone Number
|
|
- [ ] Endpoint `POST /api/v1/auth/phone/send-code`
|
|
- Validar número con libphonenumber
|
|
- Rate limiting (5 códigos / hora)
|
|
- Generar código aleatorio de 6 dígitos
|
|
- Guardar en DB con expiración
|
|
- Enviar SMS via Twilio
|
|
- [ ] Endpoint `POST /api/v1/auth/phone/verify-code`
|
|
- Validar código
|
|
- Verificar no expirado
|
|
- Verificar intentos < 3
|
|
- Crear o actualizar usuario
|
|
- Generar JWT token
|
|
- [ ] Endpoint `POST /api/v1/auth/phone/resend-code`
|
|
- Invalidar código anterior
|
|
- Generar nuevo código
|
|
- Verificar cooldown de 60s
|
|
- [ ] Service `TwilioSMSService`
|
|
- `sendVerificationCode()`
|
|
- `verifyCode()`
|
|
- `formatPhoneNumber()`
|
|
- [ ] Librería: `twilio` SDK
|
|
- [ ] Librería: `libphonenumber-js` para validación
|
|
- [ ] Tests unitarios (12 casos)
|
|
- [ ] Tests de integración con mock de Twilio
|
|
|
|
### Frontend (FE)
|
|
|
|
- [ ] Componente `PhoneAuth.tsx`
|
|
- [ ] Selector de país con banderas
|
|
- [ ] Input de teléfono con formato automático
|
|
- [ ] Componente `CodeInput.tsx` (6 dígitos)
|
|
- [ ] Componente `CompleteProfile.tsx`
|
|
- [ ] Validación con React Hook Form
|
|
- [ ] Librería: `react-phone-number-input`
|
|
- [ ] Contador regresivo para reenvío
|
|
- [ ] Tests con React Testing Library
|
|
|
|
### Testing (QA)
|
|
|
|
- [ ] E2E: Registro con teléfono completo
|
|
- [ ] E2E: Login con teléfono existente
|
|
- [ ] E2E: Código incorrecto (3 intentos)
|
|
- [ ] E2E: Código expirado
|
|
- [ ] E2E: Reenvío de código
|
|
- [ ] E2E: Rate limiting
|
|
- [ ] Test de integración con Twilio Test Credentials
|
|
- [ ] Test de seguridad: Brute force protection
|
|
- [ ] Performance: Envío de SMS < 2s
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
- **Bloqueantes:**
|
|
- Cuenta de Twilio activa
|
|
- Twilio Phone Number comprado
|
|
- Presupuesto para SMS (aprox $0.0075 USD por SMS)
|
|
|
|
- **Deseables:**
|
|
- US-AUTH-001: Para vinculación de cuentas
|
|
|
|
---
|
|
|
|
## Definition of Ready (DoR)
|
|
|
|
- [ ] Cuenta de Twilio configurada
|
|
- [ ] Twilio Phone Number asignado
|
|
- [ ] Presupuesto aprobado para SMS
|
|
- [ ] Mockups aprobados
|
|
- [ ] API contract definido
|
|
- [ ] Estrategia de rate limiting definida
|
|
|
|
---
|
|
|
|
## Definition of Done (DoD)
|
|
|
|
- [ ] Código implementado y revisado
|
|
- [ ] Tests unitarios con 80%+ cobertura
|
|
- [ ] Tests de integración pasando
|
|
- [ ] Tests E2E implementados
|
|
- [ ] Twilio configurado en todos los ambientes
|
|
- [ ] Rate limiting implementado
|
|
- [ ] Logs y monitoring de SMS
|
|
- [ ] Costos monitoreados
|
|
- [ ] Documentación actualizada
|
|
- [ ] QA aprobado en staging
|
|
- [ ] Deploy a producción exitoso
|
|
|
|
---
|
|
|
|
## Notas Técnicas
|
|
|
|
### Twilio SMS Flow
|
|
|
|
1. Usuario ingresa número de teléfono
|
|
2. Frontend valida formato
|
|
3. Frontend llama `POST /api/v1/auth/phone/send-code`
|
|
4. Backend valida número con libphonenumber
|
|
5. Backend verifica rate limits
|
|
6. Backend genera código aleatorio (6 dígitos)
|
|
7. Backend guarda código en DB (expira en 10 min)
|
|
8. Backend envía SMS via Twilio API
|
|
9. Usuario recibe SMS e ingresa código
|
|
10. Frontend llama `POST /api/v1/auth/phone/verify-code`
|
|
11. Backend valida código
|
|
12. Backend crea/actualiza usuario
|
|
13. Backend genera JWT token
|
|
|
|
### Environment Variables
|
|
|
|
```env
|
|
TWILIO_ACCOUNT_SID=AC...
|
|
TWILIO_AUTH_TOKEN=your_auth_token
|
|
TWILIO_PHONE_NUMBER=+15551234567
|
|
TWILIO_VERIFY_SERVICE_SID=VA... # Opcional: usar Twilio Verify
|
|
```
|
|
|
|
### Twilio API Usage
|
|
|
|
```typescript
|
|
import twilio from 'twilio';
|
|
|
|
const client = twilio(accountSid, authToken);
|
|
|
|
// Enviar SMS
|
|
await client.messages.create({
|
|
body: `Tu código de Trading Platform es: ${code}\n\nVálido por 10 minutos.`,
|
|
from: twilioPhoneNumber,
|
|
to: userPhoneNumber
|
|
});
|
|
```
|
|
|
|
### Phone Number Validation
|
|
|
|
```typescript
|
|
import { parsePhoneNumber } from 'libphonenumber-js';
|
|
|
|
const phoneNumber = parsePhoneNumber(input, countryCode);
|
|
if (!phoneNumber || !phoneNumber.isValid()) {
|
|
throw new Error('Invalid phone number');
|
|
}
|
|
```
|
|
|
|
### Code Generation
|
|
|
|
```typescript
|
|
// Generar código de 6 dígitos
|
|
const code = Math.floor(100000 + Math.random() * 900000).toString();
|
|
```
|
|
|
|
### Rate Limiting Strategy
|
|
|
|
- 5 códigos por número de teléfono por hora
|
|
- 10 códigos por IP por hora
|
|
- Cooldown de 60 segundos entre reenvíos
|
|
- Máximo 3 intentos de verificación por código
|
|
|
|
### Security Considerations
|
|
|
|
- Códigos de 6 dígitos (1 millón de combinaciones)
|
|
- Expiración de 10 minutos
|
|
- Invalidar después de 3 intentos fallidos
|
|
- Rate limiting estricto
|
|
- Logs de todos los intentos
|
|
- Validación de número en backend
|
|
- No devolver información si el número existe o no
|
|
|
|
### Cost Optimization
|
|
|
|
- SMS en USA: ~$0.0075 USD
|
|
- SMS internacional: $0.0075 - $0.10 USD
|
|
- Usar Twilio Verify Service para mejor pricing
|
|
- Implementar captcha para prevenir abuso
|
|
- Alertas si se excede presupuesto mensual
|
|
|
|
### Alternative: Twilio Verify Service
|
|
|
|
En lugar de manejar códigos manualmente, considerar usar Twilio Verify:
|
|
- Manejo automático de códigos
|
|
- Rate limiting incluido
|
|
- Mejor pricing
|
|
- Reenvíos automáticos
|
|
- Múltiples canales (SMS, Voice, WhatsApp)
|
|
|
|
---
|
|
|
|
## 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)
|