Merge SERVICE role into AGENT
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:
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user