# CASAN Ops Console (Plan-13 Track 1) — read-only Control Panel Real **NestJS API + React UI** that surfaces CASAN harness telemetry. This is the Level-3 `casan-platform` **Control Panel** component. **Read-only** ("Đọc ≠ Ghi"): it never writes settings or bypasses a gate — management (settings/RBAC/approval) is Plan-13 Track 2/3 (future, soft-blocked by Plan-14). ``` backend/ NestJS read-only API (/api/v1 + /healthz) over .specify telemetry frontend/ React + Vite + Tailwind + TanStack Query Ops Console ``` ## Run (local) ```bash npm install # from repo root (picks up the workspaces) npm run console:api # NestJS API → http://127.0.0.1:3010/api/v1 npm run console:ui # Vite UI → http://127.0.0.1:5174 (proxies to the API) ``` Open http://127.0.0.1:5174 — panels show REAL metrics from `.specify/logs/**`. ## API (all read-only, `ok()`-enveloped except `/healthz`) `GET /api/v1/overview` · `runs` (+ `runs/:traceId`) · `governance` · `security` · `incidents` · `tools` · `traceability` · `drift` · `cost` · `GET /healthz` (200 fresh / 503 stale — fail-loud, mirrors `dashboard-server.py`). Data sources + aggregation mirror `packages/casan-harness/tests/generate-agentops-dashboard.py`. App root + telemetry paths resolve via the same marker walk-up as `casan-paths.sh` (`.specify` or `packages/casan-harness`) and honor `CASAN_DASHBOARD_*` env overrides. ## Security posture (MVP) Binds `127.0.0.1`, no auth (read-only local ops). Refuses a non-loopback bind under `CASAN_PROFILE=prod` / `CASAN_CP_STRICT=1` — off-loopback exposure needs TLS/OIDC (Plan-13 Track 4). Auth/login (reuse OKR JWT) is a follow-up. ## Test ```bash npm run console:test # backend telemetry reader/service + healthz logic ``` ## Not in this pass Track 2 settings writes (wrap `control-plane-settings.py`), Track 3 RBAC + approval inbox (Plan-14), Track 4 docker/deploy + TLS/OIDC + FinOps/SLO. See `docs/plans/CASAN_PLAN_13_CONTROL_PLANE.md`.