workspace/projects/gamilit/docs/03-fase-extensiones/EXT-003-notificaciones/historias-usuario/US-NOT-001a-websocket-infrastructure.md
rckrdmrd ea1879f4ad feat: Initial workspace structure with multi-level Git configuration
- Configure workspace Git repository with comprehensive .gitignore
- Add Odoo as submodule for ERP reference code
- Include documentation: SETUP.md, GIT-STRUCTURE.md
- Add gitignore templates for projects (backend, frontend, database)
- Structure supports independent repos per project/subproject level

Workspace includes:
- core/ - Reusable patterns, modules, orchestration system
- projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.)
- knowledge-base/ - Reference code and patterns (includes Odoo submodule)
- devtools/ - Development tools and templates
- customers/ - Client implementations template

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 10:44:23 -06:00

13 KiB

US-NOT-001a: Infraestructura WebSocket y Sistema de Entrega en Tiempo Real

Épica: EXT-003 - Sistema de Notificaciones Sprint: Mes 3, Semana 1-2 Story Points: 10 SP Presupuesto: $13,160 MXN Prioridad: Alta (Extensión Fase 3) Estado: 📋 Planificada Relación: Parte de US-NOT-001 (dividida en a/b/c por PF-001)


Descripción

Como desarrollador del sistema Quiero implementar la infraestructura completa de WebSocket con Socket.IO, Redis adapter, autenticación JWT y sistema de entrega de notificaciones Para permitir comunicación en tiempo real confiable, escalable y segura entre el servidor y los clientes

Contexto: Esta user story es parte del sistema completo de notificaciones (EXT-003), dividida para cumplir con PF-001. Esta parte implementa la infraestructura técnica base para comunicación en tiempo real.

Alcance:

  • WebSocket server con Socket.IO en puerto dedicado (3001)
  • Autenticación JWT para conexiones WebSocket
  • Redis adapter para horizontal scaling (multi-instance)
  • Sistema de rooms por usuario (user:${userId})
  • Heartbeat y reconnection automática
  • Sistema de prioridades de notificaciones (P0-P3)
  • Rate limiting y anti-spam
  • Persistencia y sincronización de notificaciones offline
  • Analytics y monitoring de métricas críticas
  • Seguridad y encriptación de comunicación

Valor de Negocio

  • WebSocket Latency: <500ms entrega de notificaciones (SLA)
  • Delivery Rate: >99% notificaciones entregadas exitosamente
  • WebSocket Uptime: >99.9% disponibilidad de servicio
  • Scalability: Soporte para 10,000+ conexiones concurrentes
  • Infraestructura reutilizable para features futuras (chat, live updates)

Criterios de Aceptación

CA-01: Infraestructura WebSocket con Socket.IO

Dado que se requiere comunicación en tiempo real Cuando un usuario se conecta a la plataforma Entonces debe establecerse conexión WebSocket:

Configuración del Servidor:

  • Socket.IO server en puerto 3001 (separado de API REST en 3000)
  • Autenticación vía JWT token en handshake
  • Rooms por usuario: user:${userId} para envío directo
  • Reconnection automática con backoff exponencial (1s → 5s)
  • Heartbeat cada 25 segundos para mantener conexión activa
  • Redis adapter para horizontal scaling (múltiples servidores)
  • Compression habilitada para reducir bandwidth (gzip)
  • CORS configurado correctamente para dominio frontend
  • Soporte de fallback a long polling si WebSocket no disponible
  • Graceful shutdown en deploy (desconectar clientes con warning)

Validación:

  • Usuario autenticado se conecta y se une a room user:123
  • Notificación enviada a user:123 llega solo a ese usuario
  • Redis distribuye mensajes a todas las instancias del servidor
  • Reconexión automática funciona tras pérdida de conexión

CA-02: Sistema de Prioridades

Dado que existen múltiples notificaciones con diferentes urgencias Cuando el sistema decide orden de entrega Entonces debe priorizar según:

Niveles de Prioridad:

  1. Crítico (P0): Sistema en mantenimiento, errores de seguridad
  2. Alto (P1): Solicitudes de amistad, invitaciones de gremio
  3. Medio (P2): Logros raros/épicos, desafíos de gremio
  4. Bajo (P3): Logros comunes, actividades de amigos

Comportamiento:

  • P0/P1: Envío inmediato, bypass de rate limiting
  • P2: Envío inmediato, toast normal
  • P3: Batch cada 5 minutos (agrupar para reducir ruido)
  • Agrupación: Si >10 del mismo tipo en 1 minuto → consolidar

Validación:

  • Notificación P0 entregada antes que P3 aunque P3 llegó primero
  • Notificaciones P3 agrupadas en batches de 5 minutos

CA-03: Rate Limiting y Anti-Spam

Dado que se previene spam de notificaciones Cuando el sistema genera notificaciones Entonces debe aplicar límites:

Límites Globales por Usuario:

  • Máximo 50 notificaciones/usuario/hora
  • Máximo 200 notificaciones/usuario/día
  • Deduplicación: No enviar 2x la misma notificación en 5 minutos
  • Agrupación automática: Consolidar notificaciones similares

Límites por Tipo:

  • friend:request: Max 10 solicitudes/hora
  • guild:*: Max 20 notificaciones/gremio/hora
  • system:*: Sin límite (alta prioridad)
  • achievement:unlocked: Max 30/hora

Comportamiento al Exceder Límites:

  • Notificaciones adicionales puestas en cola
  • Log de notificaciones suprimidas
  • Alert a admins si usuario excede límites consistentemente

Implementación:

  • Redis para rate limiting (counter con TTL)
  • Sliding window algorithm
  • Cache de deduplicación (hash de contenido)

Validación:

  • Usuario que excede 50 notif/hora → siguientes en cola
  • Duplicado en 5 minutos → bloqueado

CA-04: Persistencia y Sincronización

Dado que un usuario puede estar offline Cuando se reconecta a la plataforma Entonces debe sincronizar notificaciones:

Sincronización al Reconectar:

  • Cargar notificaciones no leídas desde última conexión (max 50)
  • Actualizar contador de badge inmediatamente
  • Mostrar notificaciones importantes (P0/P1) como toasts
  • Marcar notificaciones >7 días como vistas automáticamente

Persistencia:

  • Notificaciones guardadas en PostgreSQL (tabla notifications)
  • Retención de 30 días (auto-eliminadas vía cron job)
  • Índices en user_id + read para queries rápidas

Validación:

  • Usuario offline recibe 10 notificaciones → al reconectar, las ve todas
  • Badge muestra número correcto tras reconexión

CA-05: Analytics y Monitoring

Dado que se monitorea el sistema Cuando se recolectan métricas en tiempo real Entonces debe trackear:

Métricas de Performance:

  • Latencia de entrega: P50, P95, P99 (objetivo: P95 <500ms)
  • Tasa de entrega exitosa: % (objetivo: >99%)
  • Conexiones WebSocket activas
  • Tasa de desconexión/reconexión (objetivo: <2%)
  • Throughput: Notificaciones procesadas por segundo
  • Queue depth: Tamaño de cola pendientes
  • Redis latency

Alertas Críticas:

  • Latencia >1s por más de 5 minutos
  • Tasa de error >1%
  • WebSocket server caído
  • Redis adapter desconectado
  • Queue depth >1000

Herramientas: Sentry (errors), DataDog/Prometheus (métricas)

CA-06: Seguridad y Privacidad

Dado que se manejan notificaciones sensibles Cuando el sistema procesa y entrega notificaciones Entonces debe garantizar seguridad:

Seguridad:

  • Autenticación JWT obligatoria en handshake
  • Encriptación TLS/SSL en tránsito (wss://)
  • Validación de permisos antes de enviar notificación
  • Usuario solo puede conectarse a su propia room
  • Sanitización de contenido (prevenir XSS)

Privacidad (GDPR/CCPA):

  • Usuarios solo reciben sus propias notificaciones
  • Respeto de preferencias de privacidad
  • Right to delete: Usuario puede borrar todas sus notificaciones
  • Logs anonimizados para analytics

Validación:

  • Token JWT inválido → conexión rechazada
  • Contenido con script XSS → sanitizado

Especificaciones Técnicas

Backend - WebSocket Server

Tecnologías: Socket.IO 4.x, Redis 7.x, ioredis, PostgreSQL 15

Setup Principal (server/websocket/notificationServer.ts):

import { Server } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import Redis from 'ioredis';

const io = new Server(3001, {
  cors: { origin: process.env.FRONTEND_URL },
  transports: ['websocket', 'polling'],
  pingTimeout: 60000,
  pingInterval: 25000
});

// Redis adapter for horizontal scaling
const pubClient = new Redis(process.env.REDIS_URL);
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));

// Authentication middleware
io.use(async (socket, next) => {
  const token = socket.handshake.auth.token;
  try {
    const user = await verifyJWT(token);
    socket.userId = user.id;
    socket.join(`user:${user.id}`);
    next();
  } catch (error) {
    next(new Error('Authentication failed'));
  }
});

// Connection handler
io.on('connection', async (socket) => {
  const unreadNotifications = await NotificationService.getUnread(socket.userId);
  socket.emit('notifications:sync', unreadNotifications);

  socket.on('disconnect', (reason) => {
    console.log(`User ${socket.userId} disconnected: ${reason}`);
  });
});

// Emit notification to user
export function emitNotification(userId: string, notification: Notification) {
  io.to(`user:${userId}`).emit(notification.type, notification);
}

NotificationService (resumen):

export class NotificationService {
  static async send(userId: string, notification: NotificationPayload) {
    // Check rate limit
    if (!await rateLimiter.check(userId, notification.type)) return null;

    // Check duplicates
    if (await this.checkDuplicate(userId, notification)) return null;

    // Persist to database
    const saved = await db.notifications.create({ userId, ...notification });

    // Add to priority queue
    priorityQueue.add(notification.priority, () => {
      emitNotification(userId, saved);
    });

    return saved;
  }

  static async getUnread(userId: string, limit = 50) {
    return db.notifications.findMany({
      where: { userId, read: false },
      orderBy: { createdAt: 'desc' },
      take: limit
    });
  }
}

Database Schema

CREATE TABLE notifications (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  type VARCHAR(50) NOT NULL,
  priority VARCHAR(10) CHECK (priority IN ('critical', 'high', 'medium', 'low')) DEFAULT 'medium',
  title VARCHAR(100) NOT NULL,
  message TEXT,
  data JSONB,
  action_url VARCHAR(255),
  read BOOLEAN DEFAULT false,
  read_at TIMESTAMP,
  expires_at TIMESTAMP DEFAULT (NOW() + INTERVAL '30 days'),
  created_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_notifications_user_unread ON notifications(user_id, read) WHERE read = false;
CREATE INDEX idx_notifications_created ON notifications(created_at DESC);
CREATE INDEX idx_notifications_type ON notifications(type);

API Endpoints

GET    /api/notifications                // Get user's notifications (paginated)
GET    /api/notifications/unread/count   // Get unread count
PUT    /api/notifications/:id/read       // Mark as read
PUT    /api/notifications/read-all       // Mark all as read
DELETE /api/notifications/:id            // Delete notification

Dependencias

Requiere:

  • Infraestructura de autenticación JWT (AUTH-001)
  • Base de datos PostgreSQL configurada
  • Redis configurado para producción

Relacionada:

  • US-NOT-001b: Centro de Notificaciones - consume esta infraestructura
  • US-NOT-001c: Preferencias - usa rate limiting

Bloquea:

  • Cualquier feature que necesite notificaciones en tiempo real

Definición de Hecho (DoD)

Desarrollo

  • WebSocket server (Socket.IO) implementado en puerto 3001
  • Redis adapter configurado con 2+ instancias
  • Autenticación JWT en handshake
  • Sistema de prioridades (P0-P3) implementado
  • Rate limiting con Redis funcional
  • Persistencia en PostgreSQL con índices
  • Cron job de limpieza de notificaciones expiradas
  • API REST endpoints implementados

Testing

  • Tests unitarios: WebSocket server, Rate limiter, Priority queue
  • Tests de integración: Redis adapter (multi-instance)
  • Load testing: 1000+ conexiones WebSocket concurrentes
  • Tests de latency (verificar <500ms P95)
  • Tests de seguridad: JWT inválido rechazado, XSS sanitización

Monitoreo

  • Sentry configurado para error tracking
  • DataDog/Prometheus métricas expuestas
  • Alertas configuradas (latencia, errors, uptime)
  • Dashboard con métricas en tiempo real

Documentación

  • API docs (REST endpoints)
  • WebSocket events documentation
  • Guía de deployment (Redis, multi-instance)

Estimación

  • Backend - WebSocket Server: 24 horas
  • Backend - Rate Limiting & Priority: 12 horas
  • Backend - Persistencia & Sync: 8 horas
  • Backend - Security & Auth: 8 horas
  • Testing (Unit + Integration + Load): 16 horas
  • Monitoring & Alertas: 8 horas
  • Documentación: 4 horas

Total: 80 horas (10 SP @ 8h/SP)


Riesgos y Mitigaciones

Riesgo Probabilidad Impacto Mitigación
WebSocket no escala con miles de usuarios Media Alto Redis adapter, horizontal scaling, load testing
Alta latencia en notificaciones (>500ms) Baja Alto Monitoring estricto, Redis en mismo datacenter
Desconexiones frecuentes Media Medio Reconnection automática con backoff exponencial
Redis adapter failure Baja Alto Fallback a single-server mode, auto-restart

Notas

  • Archivo modularizado desde US-NOT-001-FULL.md (2025-11-02)
  • Cumple PF-001 (<400L)
  • Esta es la parte más compleja (10 SP de 19 SP total)
  • Implementar primero esta infraestructura antes que US-NOT-001b/c
  • ⚠️ Requiere Redis en producción (costo adicional de infraestructura)
  • 🔒 Priorizar seguridad: JWT obligatorio, TLS/SSL, sanitización

Stack Tecnológico

Backend: Socket.IO 4.x, Redis 7.x, ioredis, PostgreSQL 15, pg-cron Monitoring: Sentry, DataDog/Prometheus, PagerDuty Testing: Jest, Socket.IO Client, Artillery (load testing)


Tags: #websocket #socket-io #redis #real-time #infrastructure #backend #ext-003 #fase3