Refresh repository documentation
Some checks failed
Deploy to Production / test (push) Failing after 33s
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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user