Volver al portfolio

Ticket Platform API

Plataforma centralizada para la gestión, asignación y resolución de tickets de soporte técnico.

Backend NestJS RBAC Ticketing Microservice

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.

50+
Endpoints
8
Modelos
13
Migraciones
21 spec files
Tests

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

TypeScript
NestJS
PostgreSQL
Docker
Prisma Prisma
Jest

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.