Refresh repository documentation
Some checks failed
Deploy to Production / test (push) Failing after 33s

- Rewrite AGENTS and README files to match the current app layout
- Document API routes, trivia UI, and the active panel design language
This commit is contained in:
syntaxbullet
2026-04-09 21:10:10 +02:00
parent 8369d10bab
commit 6abbd4652a
17 changed files with 893 additions and 639 deletions

View File

@@ -1,30 +1,130 @@
# Aurora Web API
# Aurora API
The web API provides a REST interface and WebSocket support for accessing Aurora bot data and configuration.
Aurora's API is a Bun server that runs inside the same process as the Discord bot. It serves REST routes, the authenticated WebSocket endpoint, static assets, and built panel files.
## API Endpoints
## Runtime model
- `GET /api/stats` - Real-time bot statistics
- `GET /api/settings` - Bot configuration
- `GET /api/users` - User data
- `GET /api/items` - Item catalog
- `GET /api/quests` - Quest information
- `GET /api/transactions` - Economy data
- `GET /api/health` - Health check
- Entry point: `api/src/server.ts`
- Route dispatcher: `api/src/routes/index.ts`
- Auth: Discord OAuth with in-memory session cookies
- WebSocket: `/ws`
- Static assets: `/assets/*`
- Built panel fallback: `panel/dist`
## Access model
Public:
- `GET /api/health`
- `/auth/discord`
- `/auth/callback`
- `POST /auth/logout`
- `GET /auth/me`
Player-accessible API routes:
- `GET /api/stats`
- `GET /api/health`
- `GET /api/me`
- `GET /api/me/inventory`
Admin-only API routes:
- everything else under `/api/*`
Admin vs player is derived from `ADMIN_USER_IDS`. A user must already exist in the `users` table to complete panel login.
## Route summary
### Auth
- `GET /auth/discord`
- `GET /auth/callback`
- `POST /auth/logout`
- `GET /auth/me`
### Dashboard and system
- `GET /api/health`
- `GET /api/stats`
- `GET /api/stats/activity`
- `POST /api/actions/reload-commands`
- `POST /api/actions/clear-cache`
- `POST /api/actions/maintenance-mode`
### Settings
- `GET /api/settings`
- `POST /api/settings`
- `GET /api/settings/meta`
- `GET /api/guilds/:guildId/settings`
- `PUT|PATCH /api/guilds/:guildId/settings`
- `DELETE /api/guilds/:guildId/settings`
### Users, classes, and inventory
- `GET /api/me`
- `GET /api/me/inventory`
- `GET /api/users`
- `GET /api/users/:id`
- `PUT /api/users/:id`
- `GET /api/users/:id/inventory`
- `POST /api/users/:id/inventory`
- `DELETE /api/users/:id/inventory/:itemId`
- `GET /api/classes`
- `POST /api/classes`
- `PUT /api/classes/:id`
- `DELETE /api/classes/:id`
### Game content
- `GET /api/items`
- `POST /api/items`
- `GET /api/items/:id`
- `PUT /api/items/:id`
- `DELETE /api/items/:id`
- `POST /api/items/:id/icon`
- `GET /api/quests`
- `POST /api/quests`
- `PUT /api/quests/:id`
- `DELETE /api/quests/:id`
- `GET /api/lootdrops`
- `POST /api/lootdrops`
- `DELETE /api/lootdrops/:messageId`
### Moderation and economy history
- `GET /api/moderation`
- `POST /api/moderation`
- `GET /api/transactions`
## WebSocket
Connect to `/ws` for real-time updates:
- Stats broadcasts every 5 seconds
- Event notifications via system bus
- PING/PONG heartbeat support
`/ws` requires a valid `aurora_session` cookie.
Current behavior:
- dashboard clients subscribe to `dashboard`
- game clients also use lobby and room-scoped traffic through `GameServer`
- `PING` from the client returns `PONG`
- dashboard stats are broadcast every 5 seconds while at least one client is connected
- hard limits in `api/src/server.ts`:
- 200 concurrent connections
- 16 KB max payload
- 60 second idle timeout
## Development
The API runs automatically when you start the bot:
Start the backend:
```bash
bun run dev
```
The API will be available at `http://localhost:3000`
Optional panel dev server:
```bash
bun run panel:dev
```
Panel dev runs on `http://localhost:5173` and proxies API/auth/assets/WebSocket requests to `http://localhost:3000`.

View File

@@ -1,31 +1,68 @@
# API Layer
# API layer
## Server
- Bun's native `serve()` API — no Express/Fastify. Custom `handleRequest()` dispatcher with pathname prefix matching.
- Route modules export `{ name: string, handler: RouteHandler }`. Handlers return `null` for non-matching paths.
## Server shape
## Authentication
- Discord OAuth2 with session cookies (`aurora_session`, HttpOnly, 7-day TTL).
- In-memory session store — sessions lost on restart.
- Role-based: `admin` vs `player` (admins set via `ADMIN_USER_IDS` env var).
- Non-enrolled users (not in DB) get 403 even with valid Discord auth.
- Call `getSession(req)` for all protected routes.
- Aurora uses Bun's native `serve()` API in `api/src/server.ts`.
- Route modules are aggregated in `api/src/routes/index.ts`.
- A route module returns `null` when it does not match so the dispatcher can continue.
- After route handling, the server tries `panel/dist` for SPA/static files.
## Response Conventions
- Success: `jsonResponse(data, status)` — uses custom BigInt-safe JSON replacer.
- Error: `errorResponse(message, status, details?)``{ error, details? }`
- Validation: `validationErrorResponse(zodError)``{ error: "Invalid payload", issues: [...] }`
- Zod schemas centralized in `schemas.ts`.
## Authentication and authorization
- OAuth routes live in `api/src/routes/auth.routes.ts`.
- Sessions are stored in memory and keyed by the `aurora_session` cookie.
- Session TTL is 7 days.
- Login succeeds only for users already present in the `users` table.
- Role is `admin` if the Discord ID is in `ADMIN_USER_IDS`, otherwise `player`.
- Redirects after login are intentionally restricted to localhost or relative paths.
Current access rules from `api/src/routes/index.ts`:
- public: `/auth/*`, `/api/health`
- player allow-list: `/api/stats`, `/api/health`, `/api/me`
- everything else under `/api/*`: admin-only
`/api/me/inventory` is handled by `users.routes.ts` and still depends on a valid session.
## Response conventions
- `jsonResponse()` serializes `bigint` values as strings.
- `errorResponse()` returns `{ error, details? }`.
- `parseBody()` and `parseQuery()` validate with Zod and return a `Response` on failure.
- The API does not use a framework-level middleware stack; each route handles its own parsing and branching.
## WebSocket
- Upgrade via `/ws` endpoint (requires auth).
- Pub/sub via Bun's `.publish()` / `.subscribe()` on channels: `dashboard`, `lobby`, `room:${roomId}`.
- Dashboard stats broadcast every 5 seconds. Game events are room-scoped.
- Hard limit: 200 concurrent WS connections (429 rejection), 16KB max payload, 60s idle timeout.
- Fire-and-forget broadcasts — no ack mechanism.
- Endpoint: `/ws`
- Requires an authenticated session
- Dashboard channel: `dashboard`
- Lobby channel: `lobby`
- Room-specific messaging is handled inside `GameServer`
- Dashboard broadcasts `STATS_UPDATE` every 5 seconds while clients are connected
- `NEW_EVENT` broadcasts are wired from `shared/lib/events`
Hard limits:
- max connections: 200
- max payload: 16 KB
- idle timeout: 60 seconds
## Static files
- Built panel assets are served from `panel/dist`
- `/assets/*` serves files from `bot/assets/graphics`
- `/api/*`, `/auth/*`, `/ws`, and `/assets/*` bypass the SPA fallback
## Route notes
- `items.routes.ts` supports both JSON and multipart form data for item creation.
- `settings.routes.ts` writes DB-backed game settings and emits the reload-commands event.
- `guild-settings.routes.ts` invalidates the guild config cache after writes.
- `lootdrops.routes.ts` delegates spawning/deletion to bot-side handlers because Discord message creation happens there.
## Gotchas
- All DB IDs are BigInt — JSON responses must use the custom `jsonReplacer`.
- No rate limiting on HTTP routes.
- Some routes accept multipart form data (e.g., item icon upload) — manual parsing, not abstracted.
- Asset directories resolve relative to `import.meta.dir`.
- Sessions and some caches are in-memory only and are lost on restart.
- The server registers game plugins at startup; duplicate registration throws.
- BigInt-safe JSON matters for nearly every domain route.
- The panel's auth flow depends on `PANEL_BASE_URL` matching the OAuth callback origin.