Backend API¶
The backend is a single Express application assembled in
backend/src/app.ts. This page is a summary reference derived from the
real route definitions — for a complete, interactive, always-in-sync
reference, use the running backend's /api-docs (Swagger UI) and
/openapi.json endpoints (see backend/src/docs/swagger.ts).
Basics¶
- Base path:
/api/v1/...(a few legacy/Node-RED endpoints are the exception, see below) - Authentication:
Authorization: Bearer <JWT>header. The token is obtained viaPOST /api/v1/auth/loginand expires afterJWT_EXPIRES_IN(default12h). - Content type:
application/json, 1 MB body limit. - Global rate limit: every endpoint under
/api/*is limited to 300 requests / 60 seconds per IP. Exceeding it returns429 Too Many Requests— this is not a bug, it is intentional protection (see Performance Testing). - Login rate limit:
POST /api/v1/auth/loginadditionally has its own, stricter limit: 20 requests / 5 minutes (brute-force protection).
Endpoints¶
| Method | Path | Auth | Permission | Description |
|---|---|---|---|---|
POST |
/api/v1/auth/login |
— | — | Username/password login, returns { success, token, user } |
GET |
/api/v1/auth/me |
✅ | — | Validates the token, returns fresh user data (no password field) — prevents the "protected page flash" |
GET |
/api/v1/users |
✅ | users.read |
List personnel |
POST |
/api/v1/users |
✅ | users.create |
Create a personnel record |
PUT/PATCH |
/api/v1/users/:id |
✅ | users.update |
Update a personnel record |
DELETE |
/api/v1/users/:id |
✅ | users.delete |
Delete a personnel record |
GET |
/api/v1/dictionary |
✅ | dictionary.read or settings.read |
List/search dictionary entries |
GET |
/api/v1/dictionary/stats |
✅ | dictionary.read |
Statistics (group/subgroup distribution) |
GET |
/api/v1/dictionary/subgroups |
✅ | dictionary.read or settings.read |
Subgroups for a given group |
GET |
/api/v1/dictionary/:id |
✅ | dictionary.read |
Single entry |
POST |
/api/v1/dictionary |
✅ | dictionary.create or settings.update |
Create a new term |
PUT/PATCH |
/api/v1/dictionary/:id |
✅ | dictionary.update |
Update a term |
DELETE |
/api/v1/dictionary/:id |
✅ | dictionary.delete |
Delete a term |
GET/POST |
/list-dictionary, /create-dictionary |
✅ | (legacy) | Old aliases kept for Node-RED compatibility — same DictionaryService, no duplicated logic |
GET |
/health |
— | — | Health check, { success: true, data: { status: 'ok' } } |
GET |
/api-docs |
— | — | Swagger UI (interactive API reference) |
GET |
/openapi.json |
— | — | Raw OpenAPI schema |
Authorization model¶
Permissions (PermissionKey) are defined across three areas:
dictionary (read/create/update/delete), users
(read/create/update/delete), settings (read/update). A user's
role and/or explicitly assigned permission list resolve these keys
(backend/src/middleware/auth.ts). Self-privilege-escalation (changing
your own role/permissions/status) is blocked — see the
SECURITY REGRESSION table.
Error format¶
Unexpected (unhandled) errors return 500 with a fixed, safe message —
never leaking internal detail (stack traces, DB connection strings,
etc.). Unknown routes return 404. Validation errors return 400 with
a readable, field-level body (see the <area>.validation.ts files).
Exploring during development¶
Swagger UI lists every endpoint with its real schema and lets you send requests directly from the browser (enter your token via "Authorize").