Appearance
Repository Structure
The platform is split across three independently versioned repositories in the workspace, plus external services. There is no single top-level repository that ties them together; each project has its own Git history and release cadence.
| Directory | Role |
|---|---|
dps-code-api/ | Flask API, domain services, SQL migrations, contract tests, deployment documentation |
ecc-dps-dashboard/ | React 19 + TypeScript + Vite dashboard (includes the Training Center) |
discord-oauth-proxy/ | Cloudflare Worker for the Discord OAuth token exchange |
dps-code-api/ — the backend
The API repository contains the Flask application, its extracted service modules, the complete SQL migration chain, and the deployment/architecture notes.
Application and routing layer
| File | Responsibility |
|---|---|
app.py | Flask application factory, route registration, request handling, error handlers, CORS, session interface wiring. The composition/router layer — domain logic lives in the modules below. |
Domain services
| File | Responsibility |
|---|---|
reports_service.py | Report data contract (actions, statuses, patchable fields), the shared report-action domain operations (perform_report_action, conclude_investigation), and the server-side report list. |
punishment_service.py | Punishment data contract (statuses, ID format, editable/protected fields), validation helpers, and the punishment list helper. |
agents_service.py | Agent data-contract constants (create-required fields, patchable fields, valid ranks). |
event_service.py | Application-level interface for the canonical events stream (record_event, record_report_event); the EVENT_TYPES taxonomy. |
admin_service.py | Admin-domain helpers: session-derived audit identity, health-history recording. |
health_service.py | Admin health payload builder (section statuses from raw rpc_admin_health metrics). |
oauth_service.py | Discord OAuth helpers: token exchange (proxy or direct), return_to validation, Discord JSON requests. |
contact_threads.py | Contact-message reads and serialization. |
action_queue.py | Operator/supervisor action-queue logic: stale requeue, atomic claim, queue listing, Unix timestamp helpers. |
discipline_queue.py | Discipline delivery-queue logic: stale requeue, atomic claim, completion error mapping, delivery list. |
training_engine.py | Pure scenario-condition evaluation (objectives, evidence unlocks) with no database access. |
training_service.py | Training serializers, role/elapsed-time helpers, and request-scoped training reads. |
training_runtime.py | Training session orchestration: state machine, event recording + Realtime broadcast, session payload/list builders, trainer gates. |
Authentication and authorization
| File | Responsibility |
|---|---|
authz.py | Rank/clearance constants, API-key verification, browser-session agent resolution, permission checks, supervisor/reassign/Director gates, admin allowlist gate (require_admin). |
oauth_service.py | OAuth flow helpers used by the /auth/* routes. |
Database access
| File | Responsibility |
|---|---|
db_access.py | The request-scoped supabase proxy, canonical table-name constants, low-level readers (db_get_*), Discord profile normalization/serialization, report/agent/punishment serializers, and identifier scrubbing. |
environment.py | Environment configuration (production/demo), per-request environment resolution, environment-bound session cookies, request-scoped Supabase clients, optional HMAC ingress verification. |
migrations/ | The ordered SQL migration chain (000–034) — schema, RPCs, grants, RLS, triggers. See Migrations. |
apply_rpc_migrations.py | Migration application helper: reads a connection string from db.url (or DB_URL), applies the chosen SQL files in order, and records them in schema_migrations. |
demo_seed.py | Canonical fictional demo dataset and fail-closed demo reset tooling (demo environment only). |
Integrations
| File | Responsibility |
|---|---|
erlc_relay.py | ER:LC (Roblox game server) API client: relay selection, failover ordering, per-relay circuit breaker, player lookup. |
cloudflare/ingress_worker.js | Trusted-ingress Worker: strips client-supplied environment headers and (when enabled) signs the HMAC ingress assertion. |
discord-oauth-proxy/ (separate directory) | The OAuth token-exchange Worker. |
tools/erlc_relay/ | The local residential egress relay implementation used to reach the ER:LC API. |
Supporting modules
| File | Responsibility |
|---|---|
request_limits.py | Request body-size cap, report-ID validation, search-length bounds. |
health_service.py | Admin health formatting (see above). |
*_tests.py | Executable contract suites (see Testing). |
ENVIRONMENT_DEPLOYMENT.md | Production/demo environment isolation and deployment notes. |
TRAINING_DEPLOYMENT.md | Training Center deployment guide. |
DB_OWNER_CONTRACTS.md | Database/RPC owner contracts for the hardening pass (actor identity, atomic transitions). |
AUDIT_LOG_FINDINGS.md | Audit-log review findings that drove migrations 032–034. |
ecc-dps-dashboard/ — the frontend
| Path | Responsibility |
|---|---|
src/main.tsx | Entry point: mounts App in StrictMode. |
src/App.tsx | Route tree for the normal dashboard; selects the Training Center when the hostname is training.* or the path begins /training. |
src/pages/ | Page components: Dashboard, Dockets, DocketDetail, Evidence, Analytics, Agents, Agentdetail, Queue, AuditLog, Punishments, PunishmentDetail, Admin, Settings, Login. |
src/components/ | Shared components: AppLayout (sidebar/topbar), DiscordProfileCard/DiscordProfileModal, GlobalSearch, NotificationCenter, SensitiveField, AdminConfirmDialog, DataState, OverlayPortal. |
src/lib/api/ | The API client and typed endpoint wrappers: client.ts (fetch + ApiError), auth.ts, reports.ts, agents.ts, admin.ts, punishments.ts, types.ts. |
src/lib/ | Shared utilities: urlSafety.ts (URL sanitization), theme.tsx, toast.tsx, prefs.ts, format.ts, usePageTitle.ts, environment.ts, search/. |
src/auth/AuthProvider.tsx | Session state, permission flags, admin capabilities, sign-out. |
src/training/ | The Training Center: TrainingApp.tsx (routes), TrainingRoleGate.tsx (role-branching shell), realtime.ts (Realtime hook), api.ts, types.ts, pages, and the TraineeInvestigation / TrainerControlCenter components. |
tests/smoke/ | Playwright production smoke suites. |
playwright/ | Config, global setup, session capture, and E2E/diagnostic scripts. |
vite.config.ts | Vite config incl. the /api dev proxy and @/ alias. |
tsconfig*.json | TypeScript project configs. |
DEMO_ENVIRONMENT.md | Demo environment runbook for the frontend. |
discord-oauth-proxy/ — the OAuth Worker
| Path | Responsibility |
|---|---|
src/index.js | Cloudflare Worker: authenticates callers with X-Worker-Secret, forwards the authorization-code grant to Discord's token endpoint, returns the token response. Moves the outbound exchange off Render's shared IP. |
wrangler.toml | Worker configuration (name, entrypoint, observability). |
External dependencies
- Supabase — PostgreSQL database, Realtime, and the PostgREST API surface used by the
supabasePython client. - Render — hosts the Flask API.
- Cloudflare Pages — hosts the dashboard bundle (and the docs site).
- Cloudflare Workers — the OAuth proxy and the optional ingress Worker.
- Discord (OAuth + BotGhost bot) — identity provider and the bot integration.
- ER:LC API — Roblox game-server data used by the bot via the relay.
Where functionality lives — quick map
| "Where do I find…" | Location |
|---|---|
| Report lifecycle rules | reports_service.py + rpc_report_action in migrations 006/018/019/033/034 |
| Investigation begin/conclude | reports_service.perform_report_action / conclude_investigation |
| Punishment records | punishment_service.py + rpc_punishment_* in migration 029 |
| Discipline delivery queue | discipline_queue.py + migration 030/031 |
| Event taxonomy | event_service.EVENT_TYPES + migration 033 |
| Permission policy | authz.CLEARANCE_POLICY + /auth/me |
| Admin gates | authz.require_admin + admin_users (migration 009) |
| Training engine | training_engine.py |
| Training runtime | training_runtime.py |
| Realtime broadcast | training_runtime._rt_broadcast + ecc-dps-dashboard/src/training/realtime.ts |
| URL sanitization | db_access._validate_http_url + ecc-dps-dashboard/src/lib/urlSafety.ts |