# RootNode Academy — Platform API (Phase 2B) Lightweight service: no k3s, no `--privileged`, no Lab terminal runtime. See `docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` for the design; this is the operational reference. ## Configuration reference | Variable | Required | Meaning | |---|---|---| | `PLATFORM_DB_URL` | no (defaults to local dev Postgres) | Postgres connection string | | `PROVISIONER_URL` | no | Provisioner base URL | | `PROVISIONER_SHARED_SECRET` | **yes** | Internal Provisioner auth — process refuses to start without it | | `ADMIN_PASSWORD` | **yes** | Instructor login credential — process refuses to start without it. Verified via scrypt+timing-safe compare, never stored or logged in plaintext | | `PLATFORM_API_PORT` | no | Listen port, default 4300 | | `FRONTEND_DIST_DIR` | no | Where the built frontend lives — set by the Dockerfile, override for local non-Docker dev | | `SCENARIOS_DIR` / `BUNDLES_DIR` / `CURRICULUM_PATH_FILE` | no | Override the default `scenarios/` locations, mainly for local dev outside Docker | ## Local dev ```bash cd platform echo "PROVISIONER_SHARED_SECRET=$(openssl rand -hex 32)" > .env echo "ADMIN_PASSWORD=$(openssl rand -hex 12)" >> .env docker compose -f docker-compose.dev.yml build docker compose -f docker-compose.dev.yml up -d ``` Everything is reachable through the Gateway at `http://localhost:4200` — students at `/`, instructors at `/admin`. Platform API itself isn't meant to be hit directly by a browser (same boundary as the Provisioner relative to Platform API), though nothing stops you from curling it directly at `:4300` for local debugging. ## SQLite migration One-time cutover, run against the real data volume: ```bash docker run --rm -v :/data \ -e SQLITE_PATH=/data/progress.db -e PLATFORM_DB_URL=postgres://postgres:postgres@:5433/rootnode_platform \ node migrate-sqlite.js ``` Always backs up the SQLite file first, is safe to re-run, and writes a JSON report — see `docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` §2/§3 for the full guarantees and rollback procedure. ## Tests `platform/test/e2e-phase2a.js` (student-flow regression, cookie-based) and `platform/test/e2e-phase2b.js` (the classroom acceptance workflow: cohort → students → curriculum → Prepare Labs → complete scenarios → reset → destroy-labs → progress survives). Both need the full stack up and `ADMIN_PASSWORD` set — see `platform/README.md`. ## Known limitations See `docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` §13 — in-memory sessions (a restart logs everyone out), exam mode's live bookkeeping stays Lab-local, single shared admin credential rather than per-instructor accounts.