Files
TicketingSystem/README.md
josh 429a530fc8
All checks were successful
Build & Push / Build Server (push) Successful in 1m35s
Build & Push / Build Client (push) Successful in 40s
Use prisma db push instead of migrate deploy on startup
Eliminates the need to generate and commit migration files locally
before first deploy. Schema is synced directly from schema.prisma
on container start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:59:55 -04:00

4.9 KiB
Raw Blame History

TicketingSystem

Internal ticketing system with CTI-based routing, severity levels, and n8n/automation integration.

Features

  • CTI routing — tickets are categorised by Category → Type → Item, reroutable at any time
  • Severity 15 — SEV 1 (critical) through SEV 5 (minimal); dashboard sorts by severity
  • Status lifecycle — Open → In Progress → Resolved → Closed; resolved tickets auto-close after 14 days
  • Comments — threaded comments per ticket with author attribution
  • Roles — Admin, Agent, Service (API key auth for automation accounts)
  • Admin panel — manage users and the full CTI hierarchy via UI
  • n8n ready — service accounts authenticate via X-Api-Key header

Production Deployment

Prerequisites

  • Docker + Docker Compose
  • Nginx Proxy Manager pointed at the host port (default 3080)
  • Access to your Gitea container registry

1. Copy files to your server

scp docker-compose.yml .env.example user@your-server:~/ticketing/

2. Configure environment

cd ~/ticketing
cp .env.example .env

Edit .env:

REGISTRY=gitea.thewrightserver.net
TAG=latest
POSTGRES_PASSWORD=<strong password>
JWT_SECRET=<output of: openssl rand -hex 64>
CLIENT_URL=http://tickets.thewrightserver.net
PORT=3080

Point NPM at http://<host-ip>:3080 for the proxy host.

3. Deploy

docker compose pull
docker compose up -d

5. Seed (first deploy only)

docker compose exec server npm run db:seed

This creates:

  • admin user (password: admin123) — change this immediately
  • goddard service account — API key is printed to the console; copy it now

Development

Requirements

  • Node.js 22+
  • PostgreSQL (local or via Docker)

Start Postgres

docker run -d \
  --name ticketing-pg \
  -e POSTGRES_DB=ticketing \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=postgres \
  -p 5432:5432 \
  postgres:16-alpine

Server

cd server
cp .env.example .env        # set DATABASE_URL and JWT_SECRET
npm install
npm run db:migrate          # creates tables + migration files
npm run db:seed             # seeds admin + Goddard + sample CTI
npm run dev                 # http://localhost:3000

Client

cd client
npm install
npm run dev                 # http://localhost:5173 (proxies /api to :3000)

n8n Integration (Goddard)

The goddard service account authenticates via API key — no login flow needed.

Create a ticket from n8n:

POST https://tickets.thewrightserver.net/api/tickets
X-Api-Key: sk_<goddard api key>
Content-Type: application/json

{
  "title": "[Plex] Backup - 2026-03-30T02:00:00",
  "overview": "Automated nightly Plex backup completed.",
  "severity": 5,
  "categoryId": "<TheWrightServer category ID>",
  "typeId": "<Automation type ID>",
  "itemId": "<Backup item ID>",
  "assigneeId": "<Goddard user ID>"
}

CTI IDs can be fetched from:

  • GET /api/cti/categories
  • GET /api/cti/types?categoryId=<id>
  • GET /api/cti/items?typeId=<id>

To regenerate the Goddard API key: Admin → Users → refresh icon next to Goddard.


CI/CD

Push to main triggers .gitea/workflows/build.yml, which builds and pushes two images in parallel:

Image Tag
$REGISTRY/josh/ticketing-server latest, <git sha>
$REGISTRY/josh/ticketing-client latest, <git sha>

Gitea repository secrets/variables required:

Name Type Value
REGISTRY Variable gitea.thewrightserver.net
REGISTRY_TOKEN Secret Gitea personal access token with write:packages

Set these under Repository → Settings → Actions → Variables / Secrets.

To deploy a specific commit SHA instead of latest:

TAG=<sha> docker compose up -d

Environment Variables

Variable Required Description
DATABASE_URL Yes PostgreSQL connection string
JWT_SECRET Yes Secret for signing JWTs — use openssl rand -hex 64
CLIENT_URL Yes Allowed CORS origin (your domain)
PORT No Server port (default: 3000)
REGISTRY Deploy Container registry hostname
POSTGRES_PASSWORD Deploy Postgres password
DOMAIN Deploy Public domain for Traefik routing
TAG Deploy Image tag to deploy (default: latest)

Ticket Severity

Level Label Meaning
1 SEV 1 Critical — immediate action required
2 SEV 2 High — significant impact
3 SEV 3 Medium — standard priority
4 SEV 4 Low — minor issue
5 SEV 5 Minimal — informational / automated

Tickets are sorted SEV 1 → SEV 5 on the dashboard. Paging by severity is planned for a future release.


Ticket Status Lifecycle

OPEN → IN_PROGRESS → RESOLVED ──(14 days)──→ CLOSED
                         ↑
                    re-opens reset
                    the 14-day timer