Ticket Platform API
Centralized platform for management, assignment, and resolution of technical support tickets.
Ticket Platform API is a robust backend solution built with NestJS and TypeScript, designed to orchestrate customer service workflows end to end. It implements a hierarchical RBAC system (User, Agent, Admin), a state machine for ticket lifecycle, real-time chat via WebSocket (Socket.IO), an invitation system with conflict resolution, internal messaging for staff, attachment management with soft-delete, and a timeline of 30 event types for complete auditability. Designed with a "Security by Default" approach, guaranteeing full traceability and automated audit flows.
Screenshots coming soon
1. Architecture
Controllers (HTTP Layer)
Thin HTTP layer handling HTTP concerns, parameter extraction, guard application, and Swagger decorators. All logic is delegated to services.
Services (Business Logic)
Business logic layer with rich domain rules, transaction management, and event logging. Each module has its own service (TicketsService, MessagesService, etc.).
Prisma (Data Access)
Data access layer with Prisma v7 using @prisma/adapter-pg. PrismaModule is @Global() for availability across all modules without explicit import.
2. Features
System Core
Modular Architecture with NestJS
Each domain (tickets, messages, participants, invitations, attachments, events, categories, users) has its own module with Controller, Service, DTOs, and tests. Structured dependency injection under SOLID principles.
State Machine
Role-controlled state transitions: Staff can OPEN→IN_PROGRESS→RESOLVED→CLOSED and reopen. Users can only OPEN→CLOSED. Each transition generates an audit event with JSON payload.
Advanced Hierarchical RBAC
Three roles (USER, AGENT, ADMIN) with global guards: JwtAuthGuard, ActiveUserGuard, RolesGuard. TicketAccessPolicy centralizes all access decisions. Dual roles: external JWT vs local internalRole.
Ticket Number Generation
TCK-YYYY-NNNNN format with race condition handling: retry mechanism (up to 3 attempts) that catches P2002 unique constraint violations and regenerates the number.
Collaboration & Messaging
Real-Time Chat (WebSocket)
Socket.IO with per-ticket rooms (ticket:{number}). Broadcast events: new-message, message-updated, message-deleted, new-attachment, attachment-deleted, ticket-event. Independent WS authentication with access verification.
Messaging System
Public and internal messages (staff only). Pagination, visibility filters. Posting on closed ticket auto-reopens it. Soft-delete with content erasure for privacy.
Invitation System
Full workflow: create, accept, reject, cancel. Permission flags (can_edit, can_comment). Conflict resolution: if user was already added by other means, invitation is auto-cancelled.
File Attachment Management
Upload, validation, and administration of documents linked to messages. Soft-delete with URL erasure for future async cleanup (S3). Filter by messageId.
Security & Audit
Event Timeline (30 types)
Every mutation generates an immutable TicketEvent with JSON payload. 30 event types covering everything: creation, messages, assignments, status changes, priority, category, permissions, invitations, locks.
Soft-Delete with Content Erasure
Messages: content erased + deleted_at preserved. Attachments: deleted_at + deleted_by, URL preserved for async cleanup. Users: is_active=false, never physically deleted.
Lock Mechanisms
Three independent locks: priority_locked (AGENT/ADMIN), category_locked (AGENT/ADMIN), assignment_locked (ADMIN only). Prevent changes to locked field even by participants with edit permissions.
Staff Auto-Enrollment
When staff (AGENT/ADMIN) acts on a ticket they're not participating in, they're automatically added as participants via ensureStaffParticipant(). Ensures audit trail completeness.
Infrastructure
Full Observability
Prometheus metrics: http_requests_total, http_request_duration_seconds, tickets_total, messages_total. Structured logging with Pino and automatic sensitive header redaction. Exception filters for Prisma and general errors.
Swagger/OpenAPI Documentation
All endpoints documented with @ApiOperation, @ApiResponse, @ApiParam. Bearer auth configured globally. Available at /api/docs.
Exhaustive Testing Suite
21 spec files covering controllers, services, guards, and configuration. Unit tests with Prisma mocks, guards overridden in controller tests. Jest v30 with ts-jest configuration.
Docker & Deployment
Multi-stage Dockerfile with Node.js Alpine. Docker Compose with external "backend" network. Automatic prisma migrate deploy at startup. Environment variables from .env.
3. Tech Stack
4. API Reference
| Module | Endpoints |
|---|---|
| Tickets | 18 |
| Participants | 4 |
| Invitations | 7 |
| Messages | 7 |
| Attachments | 5 |
| Events | 2 |
| Categories | 9 |
| Users | 9 |
| Health | 2 |
5. Design Decisions
JIT User Sync
Users are not pre-registered. On every JWT validation, the system checks if the external UID exists locally and creates it if not. This decouples identity management from the ticket platform, allowing AuthService to be the single source of truth for authentication.
Event Visibility System
Events can be public (visible to all participants) or personal (visible only to explicitly tagged users and staff). PARTICIPANT_PERMISSIONS_CHANGED is the only personal event type, ensuring permission changes are only visible to the affected user.
Auto-Reopen on Message
When a message is posted to a CLOSED ticket, the ticket is automatically reopened (status→OPEN, closed_at→null) with a STATUS_CHANGED event. This ensures tickets don't get lost if a client responds after closure.
Dual Role System
Users have two role systems: JWT role (from external auth: USER/ADMIN) and internalRole (from local DB: USER/AGENT/ADMIN). The internalRole is the authority for all authorization decisions, allowing a finer-grained model (AGENT) than the external identity provider.