Admin Dashboard¶
A minimal operations dashboard served by the API at /dashboard — service status, logs, and
read-only database inspection. No build step: plain HTML/CSS/JS in
src/server/dashboard/, mounted by _api_module.py (/ also
redirects here).
Auth¶
Every endpoint requires the X-Admin-Token header matching ADMIN_TOKEN. In production the
token comes from SSM (/diplomacy/admin_token); the dashboard is reachable through nginx on
port 80, so the token is the only thing protecting it.
Endpoints (src/server/api/routes/dashboard.py)¶
| Endpoint | Purpose |
|---|---|
GET /dashboard/api/services/status |
Status and uptime of the managed systemd units. |
POST /dashboard/api/services/restart |
Restart one unit. Body: {"service": "diplomacy-bot"}. |
GET /dashboard/api/logs/{service}?lines=N |
Recent journal lines via journalctl -u <unit> --no-pager -n N. |
GET /dashboard/api/database/tables |
List inspectable tables. |
GET /dashboard/api/database/table/{name}?limit=&offset= |
Paginated rows plus schema info. |
GET /dashboard/api/database/stats |
Totals: games, active games, players, recent activity. |
Safety constraints¶
- Service names are whitelisted (
ALLOWED_SERVICES) —systemctlis never handed user input. - Table names are whitelisted (
ALLOWED_TABLES:games,players,users,orders,messages,game_snapshots,turn_history) and queries are SELECT only. Pagination is mandatory so a large table can't be dumped in one request. - Subprocess calls (
systemctl,journalctl) parse their output defensively and surface failures as HTTP errors rather than tracebacks.
Known mismatch:
ALLOWED_SERVICESlists systemd units (["diplomacy", "diplomacy-bot"]), but since the split deployment (Track J) nothing runs under systemd — both hosts run Docker Compose, and the API and bot are on different machines. The service status and log queries do not work in production; this spec is aspirational (seefix_plan.mdOut of scope).
Out of scope¶
Live log streaming (SSE), a query editor, log export, historical metrics or graphs. If the dashboard needs to grow past read-only inspection plus restart, it wants real auth first.