Merge SERVICE role into AGENT
Build & Push / Test (client) (push) Successful in 31s
Build & Push / Test (server) (push) Successful in 38s
Build & Push / Build Client (push) Successful in 1m17s
Build & Push / Build Server (push) Successful in 1m18s

Every AGENT now gets an auto-generated API key on creation, shown once
in a modal. AGENTs log in with password and authenticate to the API
with X-Api-Key. pre-push.sql defensively migrates any residual SERVICE
rows to AGENT before Prisma rewrites the enum. Goddard is no longer
baked into the seed — create agents via Admin → Users.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 22:44:32 -04:00
parent a9ba74f1af
commit d8785a964d
18 changed files with 73 additions and 130 deletions
+23 -22
View File
@@ -19,21 +19,20 @@ Internal ticketing system with CTI-based routing, severity levels, role-based ac
- **Command palette + keyboard shortcuts** — ⌘K palette, `j/k` navigation, `g d/t/m/n/s` leaders, `?` help
- **PWA** — installable on mobile, offline app shell
- **Comments** — GitHub/Gitea-style threads with markdown, draft autosave, Ctrl+Enter submit
- **Roles** — Admin, Agent, User, Service (API key auth for automation)
- **Roles** — Admin, Agent, User
- **Audit log** — every action tracked with actor, timestamp, and expandable detail
- **Admin panel** — manage users, CTI hierarchy, and webhooks via UI
- **n8n ready** — service accounts authenticate via `X-Api-Key` header
- **n8n ready** — every Agent gets an auto-generated API key for `X-Api-Key` header auth
---
## Roles
| Role | Access |
| ----------- | ---------------------------------------------------------------------------- |
| **Admin** | Full access — manage users, CTI config, webhooks, 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, webhooks, close and delete tickets |
| **Agent** | Manage tickets — create, update, assign, comment, change status (not Closed). Logs in with password and can authenticate via `X-Api-Key` header (key shown once at creation) |
| **User** | Basic access — view tickets and add comments only |
> Only **Admins** can manually set a ticket status to **Closed**.
@@ -99,7 +98,9 @@ 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
- Sample CTI hierarchy (categories, types, items)
Automation accounts are no longer seeded. Create an **Agent** via Admin → Users to get an API key for n8n / scripts — the key is shown once in a modal at creation time.
### Upgrading from v0.9
@@ -140,7 +141,7 @@ cd server
cp .env.example .env # set DATABASE_URL and JWT_SECRET
npm install
npm run db:push # creates tables + search indexes
npm run db:seed # seeds admin + Goddard + sample CTI
npm run db:seed # seeds admin user + sample CTI
npm run dev # http://localhost:3000
npm test # vitest (service layer)
npm run typecheck
@@ -165,7 +166,7 @@ CI runs typecheck + tests on both packages before building Docker images.
All endpoints (except `/api/auth/*` and `/healthz`) require authentication via one of:
- **JWT**: `Authorization: Bearer <token>` (obtained from `POST /api/auth/login`)
- **API Key**: `X-Api-Key: sk_<key>` (Service accounts only)
- **API Key**: `X-Api-Key: sk_<key>` (on any Agent account)
Base URL: `https://tickets.thewrightserver.net/api`
@@ -234,7 +235,7 @@ List tickets, sorted by severity (ASC) then created date (DESC).
}
```
**Response (unpaginated — `page` omitted):** Array of ticket objects with nested `category`, `type`, `item`, `assignee`, `createdBy`, and `_count.comments`. This preserves compatibility with v0.9 clients and the Goddard integration.
**Response (unpaginated — `page` omitted):** Array of ticket objects with nested `category`, `type`, `item`, `assignee`, `createdBy`, and `_count.comments`. This preserves compatibility with v0.9 clients and API-key integrations.
---
@@ -246,7 +247,7 @@ Fetch a single ticket by internal ID or display ID (e.g. `V325813929`). Includes
#### `POST /api/tickets`
Create a new ticket. Requires **Agent**, **Admin**, or **Service** role.
Create a new ticket. Requires **Agent** or **Admin** role.
**Body:**
@@ -268,7 +269,7 @@ Create a new ticket. Requires **Agent**, **Admin**, or **Service** role.
#### `PATCH /api/tickets/:id`
Update a ticket. Accepts any combination of fields. Requires **Agent**, **Admin**, or **Service** role.
Update a ticket. Accepts any combination of fields. Requires **Agent** or **Admin** role.
> Setting `status` to `CLOSED` requires **Admin** role.
@@ -468,12 +469,12 @@ Create a user.
"username": "string",
"email": "string",
"displayName": "string",
"password": "string (not required for SERVICE role)",
"role": "ADMIN | AGENT | USER | SERVICE"
"password": "string (min 8 chars)",
"role": "ADMIN | AGENT | USER"
}
```
Service accounts receive an auto-generated API key returned in the response. Copy it immediately — it is not shown again.
Agent accounts receive an auto-generated API key returned in the response. Copy it immediately — it is not shown again. Use `PATCH /api/users/:id` with `{ "regenerateApiKey": true }` to rotate.
#### `PATCH /api/users/:id`
@@ -485,15 +486,15 @@ Delete a user. Cannot delete your own account.
---
## n8n Integration (Goddard)
## n8n Integration
The `goddard` service account authenticates via API key — no login flow needed.
Create an **Agent** account via Admin → Users. The API key is shown once in a modal at creation — copy it into n8n's credentials as the `X-Api-Key` header value. Every Agent can authenticate via both password (for the UI) and API key (for automation).
**Create a ticket from n8n:**
```
POST /api/tickets
X-Api-Key: sk_<goddard api key>
X-Api-Key: sk_<agent api key>
Content-Type: application/json
{
@@ -503,7 +504,7 @@ Content-Type: application/json
"categoryId": "<TheWrightServer category ID>",
"typeId": "<Automation type ID>",
"itemId": "<Backup item ID>",
"assigneeId": "<Goddard user ID>"
"assigneeId": "<agent user ID>"
}
```
@@ -513,7 +514,7 @@ CTI IDs can be fetched from:
- `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.
To rotate an Agent's API key: Admin → Users → refresh icon next to the Agent. The old key stops working immediately.
---