Ticket Platform API
Plataforma centralizada para la gestión, asignación y resolución de tickets de soporte técnico.
Ticket Platform API es una solución backend robusta construida con NestJS y TypeScript, diseñada para orquestar flujos de trabajo de atención al cliente de inicio a fin. Implementa un sistema RBAC jerárquico (User, Agent, Admin), una máquina de estados para el ciclo de vida de tickets, chat en tiempo real vía WebSocket (Socket.IO), un sistema de invitaciones con resolución de conflictos, mensajería interna para staff, gestión de adjuntos con soft-delete y un timeline de 30 tipos de eventos para auditoría completa. Diseñada con un enfoque "Security by Default", garantizando trazabilidad completa y automatizando flujos de auditoría.
Capturas de pantalla próximamente
1. Arquitectura
Controllers (HTTP Layer)
Capa HTTP delgada que maneja concerns de HTTP, extracción de parámetros, aplicación de guards y decoradores Swagger. Toda la lógica se delega a servicios.
Services (Business Logic)
Capa de lógica de negocio con reglas de dominio ricas, gestión de transacciones y registro de eventos. Cada módulo tiene su propio servicio (TicketsService, MessagesService, etc.).
Prisma (Data Access)
Capa de acceso a datos con Prisma v7 usando @prisma/adapter-pg. PrismaModule es @Global() para disponibilidad en todos los módulos sin importación explícita.
2. Características
Core del Sistema
Arquitectura Modular con NestJS
Cada dominio (tickets, messages, participants, invitations, attachments, events, categories, users) tiene su propio módulo con Controller, Service, DTOs y tests. Dependency injection estructurada bajo principios SOLID.
Máquina de Estados
Transiciones de estado controladas por rol: Staff puede OPEN→IN_PROGRESS→RESOLVED→CLOSED y reabrir. Usuarios solo pueden OPEN→CLOSED. Cada transición genera un evento de auditoría con payload JSON.
RBAC Jerárquico Avanzado
Tres roles (USER, AGENT, ADMIN) con guards globales: JwtAuthGuard, ActiveUserGuard, RolesGuard. TicketAccessPolicy centraliza todas las decisiones de acceso. Roles duales: JWT externo vs internalRole local.
Generación de Ticket Numbers
Formato TCK-YYYY-NNNNN con manejo de race conditions: mecanismo de retry (hasta 3 intentos) que captura violaciones de constraint único P2002 y regenera el número.
Colaboración y Mensajería
Chat en Tiempo Real (WebSocket)
Socket.IO con rooms por ticket (ticket:{number}). Eventos broadcast: new-message, message-updated, message-deleted, new-attachment, attachment-deleted, ticket-event. Autenticación WS independiente con verificación de acceso.
Sistema de Mensajería
Mensajes públicos e internos (solo staff). Paginación, filtros por visibilidad. Posting en ticket cerrado reabre automáticamente el ticket. Soft-delete con borrado de contenido para privacidad.
Sistema de Invitaciones
Workflow completo: crear, aceptar, rechazar, cancelar. Flags de permisos (can_edit, can_comment). Resolución de conflictos: si el usuario ya fue agregado por otro medio, la invitación se auto-cancela.
Gestión de Archivos Adjuntos
Upload, validación y administración de documentos vinculados a mensajes. Soft-delete con borrado de URL para cleanup futuro (S3). Filtros por messageId.
Seguridad y Auditoría
Timeline de Eventos (30 tipos)
Cada mutación genera un TicketEvent inmutable con payload JSON. 30 tipos de evento cubriendo todo: creación, mensajes, asignaciones, cambios de estado, prioridad, categoría, permisos, invitaciones, locks.
Soft-Delete con Borrado de Contenido
Mensajes: contenido borrado + deleted_at preservado. Adjuntos: deleted_at + deleted_by, URL preservada para cleanup async. Usuarios: is_active=false, nunca eliminados físicamente.
Mecanismos de Lock
Tres locks independientes: priority_locked (AGENT/ADMIN), category_locked (AGENT/ADMIN), assignment_locked (ADMIN only). Previenen cambios en el campo bloqueado incluso por participantes con permisos de edición.
Auto-Enrollment de Staff
Cuando staff (AGENT/ADMIN) actúa en un ticket donde no participa, se agrega automáticamente como participante vía ensureStaffParticipant(). Garantiza completitud del audit trail.
Infraestructura
Observabilidad Completa
Prometheus metrics: http_requests_total, http_request_duration_seconds, tickets_total, messages_total. Logging estructurado con Pino y redacción automática de headers sensibles. Exception filters para Prisma y errores generales.
Documentación Swagger/OpenAPI
Todos los endpoints documentados con @ApiOperation, @ApiResponse, @ApiParam. Bearer auth configurado globalmente. Disponible en /api/docs.
Suite de Testing Exhaustiva
21 spec files cubriendo controllers, services, guards y configuración. Tests unitarios con mocks de Prisma, guards sobreescribidos en controller tests. Configuración Jest v30 con ts-jest.
Docker y Despliegue
Dockerfile multi-stage con Node.js Alpine. Docker Compose con red externa "backend". prisma migrate deploy automático al inicio. Variables de entorno desde .env.
3. Tech Stack
4. Referencia API
| Módulo | Endpoints |
|---|---|
| Tickets | 18 |
| Participantes | 4 |
| Invitaciones | 7 |
| Mensajes | 7 |
| Adjuntos | 5 |
| Eventos | 2 |
| Categorías | 9 |
| Usuarios | 9 |
| Health | 2 |
5. Decisiones de Diseño
JIT User Sync
Los usuarios no se pre-registran. En cada validación JWT, el sistema verifica si el UID externo existe localmente y lo crea si no. Esto desacopla la gestión de identidades de la plataforma de tickets, permitiendo que AuthService sea la única fuente de verdad para autenticación.
Sistema de Visibilidad de Eventos
Eventos pueden ser públicos (visibles para todos los participantes) o personales (visibles solo para usuarios taggeados y staff). PARTICIPANT_PERMISSIONS_CHANGED es el único evento personal, asegurando que cambios de permisos solo sean visibles para el usuario afectado.
Auto-Reopen al Recibir Mensaje
Cuando se postea un mensaje en un ticket CLOSED, el ticket se reabre automáticamente (status→OPEN, closed_at→null) con un evento STATUS_CHANGED. Esto asegura que los tickets no se pierdan si un cliente responde después del cierre.
Sistema de Roles Dual
Los usuarios tienen dos sistemas de roles: JWT role (del auth externo: USER/ADMIN) e internalRole (de la DB local: USER/AGENT/ADMIN). El internalRole es la autoridad para todas las decisiones de autorización, permitiendo un modelo más granular (AGENT) que el proveedor de identidad externo.