# API layer

## Server shape

- 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.

## Authentication and authorization

- OAuth routes live in `api/src/routes/auth.routes.ts`.
- Sessions are stored in signed `aurora_session` cookies.
- 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

- 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

- Some runtime 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.
