- Add 5 frontend specification documents (ET-*-frontend.md): - ET-AUTH-006: Authentication module frontend spec - ET-ML-008: ML Signals module frontend spec - ET-LLM-007: LLM Agent module frontend spec - ET-PFM-008: Portfolio Manager frontend spec (design) - ET-MKT-003: Marketplace frontend spec (design) - Add 8 new user stories: - US-AUTH-013: Global logout - US-AUTH-014: Device management - US-ML-008: Ensemble signal view - US-ML-009: ICT analysis view - US-ML-010: Multi-symbol scan - US-LLM-011: Execute trade from chat - US-PFM-013: Rebalance alerts - US-PFM-014: PDF report generation - Update task index with completed analysis Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
506 lines
20 KiB
Markdown
506 lines
20 KiB
Markdown
---
|
|
id: "US-AUTH-014"
|
|
title: "Gestión de Dispositivos"
|
|
type: "User Story"
|
|
status: "To Do"
|
|
priority: "Media"
|
|
epic: "OQI-001"
|
|
story_points: 5
|
|
created_date: "2026-01-25"
|
|
updated_date: "2026-01-25"
|
|
---
|
|
|
|
# US-AUTH-014: Gestión de Dispositivos
|
|
|
|
**Version:** 1.0.0
|
|
**Fecha:** 2026-01-25
|
|
**Estado:** Pendiente
|
|
**Story Points:** 5
|
|
**Prioridad:** P2 (Media)
|
|
**Épica:** [OQI-001](../_MAP.md)
|
|
|
|
---
|
|
|
|
## Historia de Usuario
|
|
|
|
**Como** usuario de Trading Platform
|
|
**Quiero** ver y administrar los dispositivos donde tengo sesión activa
|
|
**Para** mantener control total sobre mi cuenta y detectar accesos no autorizados
|
|
|
|
---
|
|
|
|
## Criterios de Aceptación
|
|
|
|
### AC-001: Listado de dispositivos activos
|
|
|
|
**Dado** que estoy autenticado
|
|
**Cuando** accedo a Configuración > Seguridad > Dispositivos
|
|
**Entonces** debería ver una lista de todos mis dispositivos con sesión activa
|
|
|
|
### AC-002: Información de cada dispositivo
|
|
|
|
**Dado** que estoy viendo mi lista de dispositivos
|
|
**Cuando** observo cada dispositivo listado
|
|
**Entonces** debería ver:
|
|
- Icono del navegador (Chrome, Safari, Firefox, etc.)
|
|
- Sistema operativo (Windows, macOS, iOS, Android, Linux)
|
|
- Modelo/Nombre del dispositivo (si está disponible)
|
|
- Ubicación aproximada (Ciudad, País)
|
|
- Dirección IP
|
|
- Fecha y hora de última actividad
|
|
- Badge "Dispositivo actual" si es la sesión activa
|
|
|
|
### AC-003: Cierre de sesión individual
|
|
|
|
**Dado** que identifico un dispositivo que no reconozco
|
|
**Cuando** hago click en "Cerrar sesión"
|
|
**Entonces** debería:
|
|
1. Ver diálogo de confirmación
|
|
2. Al confirmar, cerrar sesión en ese dispositivo
|
|
3. Ver notificación "Dispositivo desconectado"
|
|
4. El dispositivo desaparece de la lista
|
|
5. Si ese dispositivo intenta hacer request, recibe 401 Unauthorized
|
|
|
|
### AC-004: Información detallada del navegador
|
|
|
|
**Dado** que quiero investigar un dispositivo sospechoso
|
|
**Cuando** hago click en el dispositivo para ver más detalles
|
|
**Entonces** debería ver:
|
|
- Versión exacta del navegador
|
|
- Versión exacta del SO
|
|
- User Agent (para auditoría)
|
|
- Historial de actividad en últimas 7 días (gráfico de línea)
|
|
- Ubicaciones desde las que se accedió
|
|
- Primer acceso registrado
|
|
- Último acceso registrado
|
|
|
|
### AC-005: Indicador de dispositivo actual
|
|
|
|
**Dado** que estoy viendo mis dispositivos
|
|
**Cuando** identifico el dispositivo desde el cual estoy accediendo
|
|
**Entonces** debería estar claramente marcado con:
|
|
- Badge "🟢 Este dispositivo"
|
|
- Ubicado al inicio de la lista
|
|
- Color diferenciado (verde o azul)
|
|
- SIN botón "Cerrar sesión"
|
|
|
|
### AC-006: Ordenes de dispositivos
|
|
|
|
**Dado** que tengo múltiples dispositivos activos
|
|
**Cuando** veo la lista
|
|
**Entonces** debería:
|
|
- Mostrar "Este dispositivo" primero
|
|
- Los demás ordenados por última actividad (descendente)
|
|
- Mostrar fecha/hora relativa (Hace 2 min, Hace 3 horas, etc.)
|
|
|
|
### AC-007: Detección de navegadores
|
|
|
|
**Dado** que accedo desde diferentes navegadores
|
|
**Cuando** reviso mis dispositivos
|
|
**Entonces** debería ver iconos apropiados:
|
|
- 🌐 Chrome
|
|
- 🔴 Firefox
|
|
- 🧭 Safari
|
|
- 🌌 Edge
|
|
- 📱 Mobile browsers
|
|
- ❓ Desconocido
|
|
|
|
### AC-008: Datos de sesión activa
|
|
|
|
**Dado** que tengo una sesión activa
|
|
**Cuando** veo los detalles del dispositivo
|
|
**Entonces** debería ver:
|
|
- Token actual (primeros 10 caracteres) para referencia
|
|
- Fecha de creación de la sesión
|
|
- Próxima fecha de expiración
|
|
- Último refresh de token (si aplica)
|
|
|
|
### AC-009: Patrón de actividad
|
|
|
|
**Dado** que quiero monitorear actividad
|
|
**Cuando** hago click en "Ver actividad" de un dispositivo
|
|
**Entonces** debería ver:
|
|
- Gráfico de actividad por hora/día
|
|
- Número de requests por período
|
|
- Últimas 10 acciones (endpoint, timestamp)
|
|
- Horarios de pico de uso
|
|
|
|
### AC-010: Alertas de nuevos dispositivos
|
|
|
|
**Dado** que inicio sesión desde un nuevo dispositivo
|
|
**Cuando** completo el login
|
|
**Entonces** debería:
|
|
1. Ver notificación in-app "Nuevo dispositivo conectado"
|
|
2. Recibir email con detalles: navegador, SO, ubicación, IP
|
|
3. Link en email para cerrar sesión inmediatamente si no fui yo
|
|
|
|
---
|
|
|
|
## Mockup
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Configuración > Seguridad > Dispositivos │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Dispositivos activos │
|
|
│ Administra dónde está abierta tu sesión │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ 🌐 Chrome en Windows 🟢 Este │ │
|
|
│ │ dispositivo │ │
|
|
│ │ San Francisco, Estados Unidos • 201.45.67.89 │ │
|
|
│ │ Última actividad: Hace 2 minutos │ │
|
|
│ │ │ │
|
|
│ │ [Ver más detalles] │ │
|
|
│ └─────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ 📱 Safari en iPhone [Cerrar] │ │
|
|
│ │ │ │
|
|
│ │ Ciudad de México, México • 189.203.45.12 │ │
|
|
│ │ Última actividad: Hace 3 horas │ │
|
|
│ │ │ │
|
|
│ │ [Ver más detalles] │ │
|
|
│ └─────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ 🔴 Firefox en Linux [Cerrar] │ │
|
|
│ │ │ │
|
|
│ │ Madrid, España • 85.123.45.67 │ │
|
|
│ │ Última actividad: Hace 2 días │ │
|
|
│ │ │ │
|
|
│ │ [Ver más detalles] │ │
|
|
│ └─────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ──────────────────────────────────────────────────── │
|
|
│ │
|
|
│ Información de seguridad │
|
|
│ • Total de sesiones activas: 3 │
|
|
│ • Última sesión nueva: 3 horas atrás │
|
|
│ • Si ves un dispositivo desconocido, ciérralo │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
|
|
Modal de detalles:
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ Detalles del dispositivo │
|
|
│ │
|
|
│ 🌐 Chrome 130.0.0.0 │
|
|
│ Windows 11 (Build 23631) │
|
|
│ │
|
|
│ Ubicación: │
|
|
│ San Francisco, Estados Unidos (37.7749°, -122.4194°) │
|
|
│ │
|
|
│ IP: 201.45.67.89 │
|
|
│ ISP: Verizon Communications │
|
|
│ │
|
|
│ Sesión: │
|
|
│ Creada: 25 Ene 2026, 14:30 CST │
|
|
│ Última actividad: Hace 2 minutos │
|
|
│ Próxima expiración: 24 Feb 2026, 14:30 CST │
|
|
│ Token: abc123def... │
|
|
│ │
|
|
│ Actividad (últimas 24 horas): │
|
|
│ [Gráfico de línea con actividad por hora] │
|
|
│ │
|
|
│ Últimos requests: │
|
|
│ 14:45 - GET /api/portfolio │
|
|
│ 14:43 - GET /api/market/BTC │
|
|
│ 14:41 - POST /api/orders │
|
|
│ │
|
|
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
│ │ Volver │ │ Cerrar sesión │ │
|
|
│ └──────────────────────┘ └──────────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
|
|
Modal de confirmación:
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ ⚠️ Cerrar sesión en dispositivo? │
|
|
│ │
|
|
│ Se cerrará la sesión de: │
|
|
│ 📱 Safari en iPhone │
|
|
│ Ciudad de México, México │
|
|
│ │
|
|
│ Esta acción no se puede deshacer. El dispositivo │
|
|
│ deberá iniciar sesión nuevamente. │
|
|
│ │
|
|
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
│ │ Cancelar │ │ Cerrar sesión │ │
|
|
│ └──────────────────────┘ └──────────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
|
|
Email de nuevo dispositivo:
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ De: Trading Platform Security <security@trading.com> │
|
|
│ Asunto: Nuevo dispositivo conectado a tu cuenta │
|
|
│ │
|
|
│ Hola Juan, │
|
|
│ │
|
|
│ Se inició sesión en tu cuenta desde un nuevo │
|
|
│ dispositivo: │
|
|
│ │
|
|
│ 🌐 Chrome en Windows │
|
|
│ 📍 San Francisco, Estados Unidos │
|
|
│ 🕐 25 de Enero, 2026 a las 14:30 CST │
|
|
│ 🌐 IP: 201.45.67.89 │
|
|
│ │
|
|
│ ¿Fuiste tú? │
|
|
│ Si reconoces esta actividad, puedes ignorar este │
|
|
│ email. │
|
|
│ │
|
|
│ ¿No fuiste tú? │
|
|
│ ┌──────────────────────────────────────────────┐ │
|
|
│ │ Cerrar sesión en este dispositivo │ │
|
|
│ └──────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Ver todos mis dispositivos: │
|
|
│ [https://trading.example.com/settings/devices] │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Tareas Técnicas
|
|
|
|
### Database (DB)
|
|
|
|
- [ ] Tabla `user_sessions` (ver US-AUTH-012):
|
|
- Verificar campos: device_type, device_name, browser, os, ip_address, location_city, location_country
|
|
- Agregar si falta: user_agent (TEXT para auditoría)
|
|
- Agregar si falta: last_activity_details (JSONB para tracking fino)
|
|
|
|
- [ ] Tabla `device_activity_log`:
|
|
```sql
|
|
CREATE TABLE device_activity_log (
|
|
id UUID PRIMARY KEY,
|
|
session_id UUID REFERENCES user_sessions(id) ON DELETE CASCADE,
|
|
endpoint VARCHAR(255),
|
|
method VARCHAR(10), -- GET, POST, PUT, DELETE, etc.
|
|
status_code INTEGER,
|
|
response_time_ms INTEGER,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
INDEX idx_session_created (session_id, created_at),
|
|
INDEX idx_created (created_at)
|
|
);
|
|
```
|
|
|
|
### Backend (BE)
|
|
|
|
- [ ] Endpoint `GET /api/auth/devices`
|
|
- Listar todos los dispositivos activos del usuario
|
|
- Marcar dispositivo actual
|
|
- Ordenar por última actividad DESC
|
|
- Incluir: device_type, device_name, os, browser, ip, location, last_activity
|
|
- Response: HTTP 200
|
|
|
|
- [ ] Endpoint `GET /api/auth/devices/:id`
|
|
- Obtener detalles completos de un dispositivo
|
|
- Incluir: user_agent, histórico de actividad (7 días), primero/último acceso
|
|
- Incluir: gráfico de actividad por hora
|
|
- Incluir: últimos 10 requests
|
|
- Response: HTTP 200 o 404
|
|
|
|
- [ ] Endpoint `DELETE /api/auth/devices/:id`
|
|
- Cerrar sesión en dispositivo específico
|
|
- Invalidar tokens asociados
|
|
- Loguear la acción en audit trail
|
|
- Enviar email al usuario
|
|
- Response: HTTP 204 o 401/404
|
|
|
|
- [ ] Service `DeviceService`
|
|
- `getAllDevices(userId)`
|
|
- `getDeviceDetails(userId, deviceId)`
|
|
- `terminateDevice(userId, deviceId)`
|
|
- `isCurrentDevice(userId, sessionId)`
|
|
- `getDeviceActivitySummary(deviceId, days)`
|
|
- `getLastNRequests(deviceId, limit)`
|
|
|
|
- [ ] Service `DeviceDetectionService` (mejorado)
|
|
- `parseUserAgent()` - ya existe en US-AUTH-012
|
|
- `extractBrowserIcon()` - nuevo
|
|
- `getDeviceFingerprint()` - nuevo para consistencia
|
|
|
|
- [ ] Logging de actividad
|
|
- Hook/middleware para loguear cada request en `device_activity_log`
|
|
- Incluir: endpoint, método, status code, tiempo de respuesta
|
|
- Asociar a session_id actual
|
|
|
|
- [ ] Email de notificación
|
|
- Template "Nuevo dispositivo conectado"
|
|
- Incluir link para cerrar sesión desde email
|
|
- Usar SendGrid o similar
|
|
|
|
- [ ] Tests unitarios (12 casos)
|
|
- [ ] Tests de integración (8 escenarios)
|
|
|
|
### Frontend (FE)
|
|
|
|
- [ ] Página `Settings/Security/Devices.tsx` (nueva)
|
|
- [ ] Componente `DeviceCard.tsx` (nuevo)
|
|
- [ ] Componente `DeviceDetailsModal.tsx` (nuevo)
|
|
- [ ] Modal de confirmación de cierre
|
|
- [ ] Gráfico de actividad (line chart con lightweight-charts)
|
|
- [ ] Tabla de últimos requests
|
|
- [ ] Función para obtener icono de navegador
|
|
- [ ] Badge "Este dispositivo" con lógica de sesión actual
|
|
- [ ] Ordenamiento automático por última actividad
|
|
- [ ] Tests con React Testing Library
|
|
|
|
### Testing (QA)
|
|
|
|
- [ ] E2E: Ver lista de dispositivos
|
|
- [ ] E2E: Ver detalles de dispositivo
|
|
- [ ] E2E: Cerrar sesión en dispositivo individual
|
|
- [ ] E2E: Confirmar cierre desde modal
|
|
- [ ] E2E: Dispositivo desaparece después de cerrar
|
|
- [ ] E2E: Email se envía en nuevo dispositivo
|
|
- [ ] Performance: Lista de dispositivos < 300ms
|
|
- [ ] Performance: Detalles de dispositivo < 500ms
|
|
- [ ] Seguridad: No mostrar tokens completos
|
|
- [ ] Seguridad: Solo usuario propietario puede ver/cerrar
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
- **Bloqueantes:**
|
|
- US-AUTH-012: Gestión de Sesiones (tabla user_sessions)
|
|
- Sistema de geolocalización (de US-AUTH-012)
|
|
|
|
- **Relacionadas:**
|
|
- US-AUTH-002: Login (sesión inicial)
|
|
- US-AUTH-013: Cambio de contraseña (seguridad complementaria)
|
|
|
|
---
|
|
|
|
## Definition of Ready (DoR)
|
|
|
|
- [ ] API contract definido y aprobado
|
|
- [ ] Mockups validados con UX
|
|
- [ ] Esquema de BD detallado
|
|
- [ ] Servicio de email configurado
|
|
- [ ] Estructura de logs de actividad definida
|
|
|
|
---
|
|
|
|
## Definition of Done (DoD)
|
|
|
|
- [ ] Endpoint GET /api/auth/devices implementado
|
|
- [ ] Endpoint GET /api/auth/devices/:id implementado
|
|
- [ ] Endpoint DELETE /api/auth/devices/:id implementado
|
|
- [ ] Tabla device_activity_log creada
|
|
- [ ] Logging de actividad funcional
|
|
- [ ] Página Settings/Security/Devices.tsx implementada
|
|
- [ ] Componentes DeviceCard y DeviceDetailsModal implementados
|
|
- [ ] Gráfico de actividad funcional
|
|
- [ ] Email de notificación configurable
|
|
- [ ] Tests unitarios con 80%+ cobertura
|
|
- [ ] Tests de integración pasando
|
|
- [ ] Tests E2E implementados
|
|
- [ ] Documentación actualizada
|
|
- [ ] QA aprobado en staging
|
|
- [ ] Deploy a producción exitoso
|
|
|
|
---
|
|
|
|
## Notas Técnicas
|
|
|
|
### Device Identification
|
|
|
|
```typescript
|
|
interface DeviceInfo {
|
|
id: string; // session_id
|
|
browser: string; // "Chrome 130"
|
|
os: string; // "Windows 11"
|
|
device_type: "desktop" | "mobile" | "tablet" | "unknown";
|
|
device_name: string; // "Chrome on Windows"
|
|
ip_address: string;
|
|
location: {
|
|
city: string;
|
|
country: string;
|
|
latitude?: number;
|
|
longitude?: number;
|
|
};
|
|
user_agent: string;
|
|
is_current: boolean;
|
|
last_activity: Date;
|
|
created_at: Date;
|
|
expires_at: Date;
|
|
}
|
|
```
|
|
|
|
### Browser Icons Mapping
|
|
|
|
```typescript
|
|
const BROWSER_ICONS = {
|
|
'Chrome': '🌐',
|
|
'Firefox': '🔴',
|
|
'Safari': '🧭',
|
|
'Edge': '🌌',
|
|
'Opera': '⭕',
|
|
'Mobile': '📱',
|
|
'Unknown': '❓'
|
|
};
|
|
```
|
|
|
|
### Activity Graph Data
|
|
|
|
```typescript
|
|
interface ActivityDataPoint {
|
|
hour: number; // 0-23
|
|
date: string; // "2026-01-25"
|
|
request_count: number;
|
|
timestamp: Date;
|
|
}
|
|
|
|
// Graficar: últimas 24 horas con actividad por hora
|
|
// Líneas suave, mostrar puntos de máxima actividad
|
|
```
|
|
|
|
### Current Device Detection
|
|
|
|
El dispositivo "actual" se detecta comparando:
|
|
1. Session token actual en localStorage/cookie
|
|
2. Session ID del request
|
|
3. El primer dispositivo con `expires_at > now()` y session_id === actual es "Este dispositivo"
|
|
|
|
### Email Trigger
|
|
|
|
Se dispara email de "Nuevo dispositivo" cuando:
|
|
```typescript
|
|
const isNewDevice = !existingSession ||
|
|
(existingSession.device_name !== currentDevice.device_name) ||
|
|
(existingSession.ip_address !== currentDevice.ip_address);
|
|
```
|
|
|
|
### Audit Trail
|
|
|
|
Cada acción se registra:
|
|
```
|
|
- Dispositivo X cerrado por usuario Y
|
|
- Timestamp: 2026-01-25 14:30:00
|
|
- Reason: manual_close
|
|
- IP del usuario que cerró: admin_ip
|
|
```
|
|
|
|
---
|
|
|
|
## Requerimientos Relacionados
|
|
|
|
- [RF-AUTH-007: Gestión de Dispositivos](../requerimientos/RF-AUTH-007-devices.md)
|
|
|
|
## Especificaciones Relacionadas
|
|
|
|
- [ET-AUTH-002: JWT Tokens](../especificaciones/ET-AUTH-002-jwt.md)
|
|
- [ET-AUTH-003: Database](../especificaciones/ET-AUTH-003-database.md)
|
|
- [ET-AUTH-006: Session Management](../especificaciones/ET-AUTH-006-sessions.md)
|