Add ESLint + Prettier + EditorConfig tooling at repo root
v1.0 Phase 1.1 — repo-wide lint/format baseline. - eslint.config.mjs (flat config) lints server, client, shared - .prettierrc.json, .prettierignore, .editorconfig, .nvmrc - Root package.json holds shared devDeps; per-package scripts keep their typecheck + test runners - Fix 7 lint issues surfaced by the baseline run: - TicketDetail.tsx: replace ternary-with-side-effects with if/else - admin/Users.tsx: escape apostrophe in JSX - errorHandler.ts: typed err as unknown with ErrorLike refinement - users.ts: Prisma.UserUpdateInput instead of Record<string, any> - seed.ts: drop unused goddard binding - Run prettier across tracked sources for a clean formatting baseline
This commit is contained in:
@@ -19,12 +19,12 @@ Internal ticketing system with CTI-based routing, severity levels, role-based ac
|
||||
|
||||
## Roles
|
||||
|
||||
| Role | Access |
|
||||
|---|---|
|
||||
| **Admin** | Full access — manage users, CTI config, close and delete tickets |
|
||||
| **Agent** | Manage tickets — create, update, assign, comment, change status (not Closed) |
|
||||
| **User** | Basic access — view tickets and add comments only |
|
||||
| **Service** | Automation account — authenticates via API key, no password login |
|
||||
| Role | Access |
|
||||
| ----------- | ---------------------------------------------------------------------------- |
|
||||
| **Admin** | Full access — manage users, CTI config, close and delete tickets |
|
||||
| **Agent** | Manage tickets — create, update, assign, comment, change status (not Closed) |
|
||||
| **User** | Basic access — view tickets and add comments only |
|
||||
| **Service** | Automation account — authenticates via API key, no password login |
|
||||
|
||||
> Only **Admins** can manually set a ticket status to **Closed**.
|
||||
|
||||
@@ -78,6 +78,7 @@ 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
|
||||
|
||||
@@ -141,15 +142,23 @@ Base URL: `https://tickets.thewrightserver.net/api`
|
||||
Authenticate and receive a JWT.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "username": "string", "password": "string" }
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "eyJ...",
|
||||
"user": { "id": "...", "username": "admin", "displayName": "Admin", "email": "...", "role": "ADMIN" }
|
||||
"user": {
|
||||
"id": "...",
|
||||
"username": "admin",
|
||||
"displayName": "Admin",
|
||||
"email": "...",
|
||||
"role": "ADMIN"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -167,13 +176,13 @@ List all tickets, sorted by severity (ASC) then created date (DESC).
|
||||
|
||||
**Query parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `status` | string | Filter by status: `OPEN`, `IN_PROGRESS`, `RESOLVED`, `CLOSED` |
|
||||
| `severity` | number | Filter by severity: `1`–`5` |
|
||||
| `categoryId` | string | Filter by category (queue) |
|
||||
| `assigneeId` | string | Filter by assignee user ID |
|
||||
| `search` | string | Full-text search on title, overview, and display ID |
|
||||
| Parameter | Type | Description |
|
||||
| ------------ | ------ | ------------------------------------------------------------- |
|
||||
| `status` | string | Filter by status: `OPEN`, `IN_PROGRESS`, `RESOLVED`, `CLOSED` |
|
||||
| `severity` | number | Filter by severity: `1`–`5` |
|
||||
| `categoryId` | string | Filter by category (queue) |
|
||||
| `assigneeId` | string | Filter by assignee user ID |
|
||||
| `search` | string | Full-text search on title, overview, and display ID |
|
||||
|
||||
**Response:** Array of ticket objects with nested `category`, `type`, `item`, `assignee`, `createdBy`, and `_count.comments`.
|
||||
|
||||
@@ -190,6 +199,7 @@ Fetch a single ticket by internal ID or display ID (e.g. `V325813929`). Includes
|
||||
Create a new ticket. Requires **Agent**, **Admin**, or **Service** role.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "string",
|
||||
@@ -213,6 +223,7 @@ Update a ticket. Accepts any combination of fields. Requires **Agent**, **Admin*
|
||||
> Setting `status` to `CLOSED` requires **Admin** role.
|
||||
|
||||
**Body (all fields optional):**
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "string",
|
||||
@@ -247,6 +258,7 @@ Delete a ticket and all associated comments and audit logs. **Admin only.**
|
||||
Add a comment to a ticket. Supports markdown. All authenticated roles may comment.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "body": "string (markdown)" }
|
||||
```
|
||||
@@ -270,6 +282,7 @@ Delete a comment. Authors may delete their own comments; Admins may delete any.
|
||||
Retrieve the full audit log for a ticket, ordered newest first.
|
||||
|
||||
**Response:** Array of audit log entries:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
@@ -284,41 +297,43 @@ Retrieve the full audit log for a ticket, ordered newest first.
|
||||
|
||||
**Action types:**
|
||||
|
||||
| Action | Detail |
|
||||
|---|---|
|
||||
| `CREATED` | — |
|
||||
| `STATUS_CHANGED` | e.g. `Open → In Progress` |
|
||||
| `SEVERITY_CHANGED` | e.g. `SEV 3 → SEV 1` |
|
||||
| `ASSIGNEE_CHANGED` | e.g. `Unassigned → Josh` |
|
||||
| `REROUTED` | e.g. `OldCat › OldType › OldItem → NewCat › NewType › NewItem` |
|
||||
| `TITLE_CHANGED` | New title |
|
||||
| `OVERVIEW_CHANGED` | — |
|
||||
| `COMMENT_ADDED` | Comment body |
|
||||
| `COMMENT_DELETED` | Deleted comment body |
|
||||
| Action | Detail |
|
||||
| ------------------ | -------------------------------------------------------------- |
|
||||
| `CREATED` | — |
|
||||
| `STATUS_CHANGED` | e.g. `Open → In Progress` |
|
||||
| `SEVERITY_CHANGED` | e.g. `SEV 3 → SEV 1` |
|
||||
| `ASSIGNEE_CHANGED` | e.g. `Unassigned → Josh` |
|
||||
| `REROUTED` | e.g. `OldCat › OldType › OldItem → NewCat › NewType › NewItem` |
|
||||
| `TITLE_CHANGED` | New title |
|
||||
| `OVERVIEW_CHANGED` | — |
|
||||
| `COMMENT_ADDED` | Comment body |
|
||||
| `COMMENT_DELETED` | Deleted comment body |
|
||||
|
||||
---
|
||||
|
||||
### CTI (Category / Type / Item)
|
||||
|
||||
#### `GET /api/cti/categories`
|
||||
|
||||
#### `GET /api/cti/types?categoryId=<id>`
|
||||
|
||||
#### `GET /api/cti/items?typeId=<id>`
|
||||
|
||||
Read the CTI hierarchy. Used to resolve IDs when creating/rerouting tickets.
|
||||
|
||||
**Admin-only write operations:**
|
||||
|
||||
| Method | Endpoint | Body |
|
||||
|---|---|---|
|
||||
| `POST` | `/api/cti/categories` | `{ "name": "string" }` |
|
||||
| `PUT` | `/api/cti/categories/:id` | `{ "name": "string" }` |
|
||||
| `DELETE` | `/api/cti/categories/:id` | — |
|
||||
| `POST` | `/api/cti/types` | `{ "name": "string", "categoryId": "string" }` |
|
||||
| `PUT` | `/api/cti/types/:id` | `{ "name": "string" }` |
|
||||
| `DELETE` | `/api/cti/types/:id` | — |
|
||||
| `POST` | `/api/cti/items` | `{ "name": "string", "typeId": "string" }` |
|
||||
| `PUT` | `/api/cti/items/:id` | `{ "name": "string" }` |
|
||||
| `DELETE` | `/api/cti/items/:id` | — |
|
||||
| Method | Endpoint | Body |
|
||||
| -------- | ------------------------- | ---------------------------------------------- |
|
||||
| `POST` | `/api/cti/categories` | `{ "name": "string" }` |
|
||||
| `PUT` | `/api/cti/categories/:id` | `{ "name": "string" }` |
|
||||
| `DELETE` | `/api/cti/categories/:id` | — |
|
||||
| `POST` | `/api/cti/types` | `{ "name": "string", "categoryId": "string" }` |
|
||||
| `PUT` | `/api/cti/types/:id` | `{ "name": "string" }` |
|
||||
| `DELETE` | `/api/cti/types/:id` | — |
|
||||
| `POST` | `/api/cti/items` | `{ "name": "string", "typeId": "string" }` |
|
||||
| `PUT` | `/api/cti/items/:id` | `{ "name": "string" }` |
|
||||
| `DELETE` | `/api/cti/items/:id` | — |
|
||||
|
||||
Deleting a category cascades to all child types and items.
|
||||
|
||||
@@ -391,6 +406,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
CTI IDs can be fetched from:
|
||||
|
||||
- `GET /api/cti/categories`
|
||||
- `GET /api/cti/types?categoryId=<id>`
|
||||
- `GET /api/cti/items?typeId=<id>`
|
||||
@@ -401,27 +417,27 @@ To regenerate the Goddard API key: Admin → Users → refresh icon next to Godd
|
||||
|
||||
## 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 |
|
||||
| `TAG` | Deploy | Image tag to deploy (default: `latest`) |
|
||||
| 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 |
|
||||
| `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 |
|
||||
| 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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user