Skip to content

Architecture

1. System Context (C4 L1)

Helpdesk is a VerifierApplication — it verifies JWTs against the identity issuer's JWKS but never issues tokens. It has no synchronous outbound calls to sister microservices; cross-domain data (products, sale orders) is read through repositories shipped by @nx/core.

2. Container View (C4 L2)

ProcessRUN_MODERuns
APIstartup (default)Hono server, controllers, EventBus, queue producers
WorkerworkerBullMQ workers consuming the 6 queues
MigrationmigrateOne-shot Drizzle migration processes

3. Component View (C4 L3) — Internal Layering

LayerResponsibility
ControllersMerchant-access gate (assertMerchantAccess() + useRequestContext()), DTO mapping; delegate to use-cases. No @authenticate decorator
Use-CasesSingle-responsibility business operations, registered as DI services; emit events / dispatch jobs
ListenersSubscribe to in-process events, fan out to BullMQ jobs / side effects
WorkersConsume BullMQ queues; run use-cases for async work (assignment, SLA, escalation, notification, enrichment, survey)
RepositoriesDrizzle queries; schemas centralized in @nx/core
ComponentsCross-cutting: EventBus, Queue, Worker, Mail, WebSocket, Redis cache

4. State Machines Index

EntityStatesDiagram
TicketOPEN, ASSIGNED, IN_PROGRESS, WAITING_USER, WAITING_AGENT, WAITING_INTERNAL, PENDING, ASSIGNMENT_FAILED, ESCALATED, RESOLVED, CLOSED, REOPENED→ jump
SlaTrackerON_TRACK → WARNING → BREACHED → CRITICAL→ SLA & Escalation

Ticket (XState v5)

TicketStatuses source: packages/core/src/models/schemas/helpdesk/ticket/schema.ts. 12 statuses; transitions enforced by UpdateTicketStatusUseCase.

PENDING is a holding state defined in TicketStatuses for not-yet-categorized work. Detailed transition table: Ticket System → Lifecycle.

5. Runtime Scenarios

5.1 Ticket creation → enrichment + assignment

StepDetail
3Ticket + audit TicketEvent written in one unit of work
4In-process emit — never blocks the HTTP response
7-8Listener fans out to BullMQ; workers (worker process) pick them up

5.2 SLA breach → escalation → notification

StepDetail
1Cron is registered by QueueComponent.scheduleSlaMonitoring() (WORKER_CONFIG.SLA_MONITOR_INTERVAL)
4-5Warning thresholds from SLA_WARNING_THRESHOLDS (75 / 90 / 100 / 150)
reassignLevel-2+ reassignment to senior agent is currently disabled in code (see Operations → Known Issues)

5.3 Ticket resolved → survey trigger

6. Crosscutting Concerns

ConcernHow this service handles it
AuthNJWT verified against identity JWKS (VerifierApplication). No issuance
AuthZPer-merchant access via assertMerchantAccess() + useRequestContext() from @nx/core; no per-route @authenticate decorator. PermissionService for helpdesk-specific checks
i18njsonb columns, { en, vi } shape (i18n() column helper) — e.g. ticket subject, description, SLA policy name
Loggingconsole.log/console.error prefixed with [Component] scope (no structured logger wired in workers/listeners)
TracingNone wired
IdempotencyBullMQ jobs use idempotency helpers (worker-idempotency.helper.ts, idempotent-worker-deps.factory.ts); SLA cron uses fixed jobId: 'sla-monitor-cron' to prevent duplicates
Soft-deletedeletedAt via centralized generateCommonColumnDefs(); default reads exclude deleted rows
IDsSnowflake via IdGenerator, worker node 12
DLQHandleDeadLetterUseCase + dlq.helper.ts for failed jobs

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.