# RootNode Academy — Platform The full multi-student platform, layered on top of the Lab image at the repo root (backend/ entrypoint/Dockerfile unmodified; frontend bundle gained Phase 3B learning UX, see `docs/PHASE3B_LEARNING_AND_ASSESSMENT.md` §10–11). Start here, then go to the component you need: - `provisioner/` — Postgres-backed environment registry and lifecycle. Design: `docs/LAB_ARCHITECTURE.md`, `docs/PHASE1_PLATFORM_FOUNDATION.md`. Operational reference: `provisioner/README.md`. - `api/` — the lightweight Platform API: students, cohorts, enrollments, curriculum, detailed scenario attempt telemetry, progressive hints, curriculum completion rules, the exam + capstone assessment engine, achievements, per-instructor accounts, persistent student/ instructor sessions, RBAC, audit logging, and the instructor/admin control plane. No k3s, no `--privileged` — this replaced Phase 2A's "identity" instance, which was a full Lab image booting an unused k3s cluster just to serve these APIs. Design: `docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` (split + Postgres migration), `docs/PHASE3A_IDENTITY_AND_INSTRUCTOR_ACCESS.md` (sessions, accounts, RBAC, audit), `docs/PHASE3B_LEARNING_AND_ASSESSMENT.md` (learning/assessment engine). Operational reference: `api/README.md`. - `gateway/` — the only student-facing path to a Lab (HTTP + WebSocket proxy, environment-aware routing derived from a server-controlled session — not a client-suppliable header/param — and, as of Phase 3B, server-side gating of progressive hint reveal). Design: `docs/PHASE2A_GATEWAY_AND_STUDENT_FLOW.md` (routing), `docs/PHASE3A_IDENTITY_AND_INSTRUCTOR_ACCESS.md` (persistent sessions, CSRF), `docs/PHASE3B_LEARNING_AND_ASSESSMENT.md` §3 (hint gating). - `egress-proxy/` — shared allowlisting proxy every Lab's outbound traffic passes through. - `docker-compose.dev.yml` — the full stack (Postgres, egress proxy, Provisioner, Platform API, Gateway) on one machine. This is the Phase 1/2A/2B **local dev exception** — production is the two-VM Proxmox split described in `docs/LAB_ARCHITECTURE.md` §1. ## Running the full stack locally ```bash cd platform echo "PROVISIONER_SHARED_SECRET=$(openssl rand -hex 32)" > .env docker compose -f docker-compose.dev.yml build docker compose -f docker-compose.dev.yml up -d # First run only — create the owner account (no ADMIN_PASSWORD anymore, see # docs/PHASE3A_IDENTITY_AND_INSTRUCTOR_ACCESS.md): cd api PLATFORM_DB_URL=postgres://postgres:postgres@localhost:5433/rootnode_platform \ node bootstrap-owner.js you@example.com "Your Name" "a-real-password-12-chars-plus" ``` No k3s boot to wait for at this layer anymore (Platform API starts instantly) — the whole platform is reachable at `http://localhost:4200` (the Gateway) right away: students at `/`, instructors at `/admin` (sign in with the owner account you just bootstrapped, then create further instructor accounts from the Instructors tab). ## Tests - `provisioner/test/run.js` — fast, isolated Provisioner tests (network/container/firewall mechanics, no Gateway/Platform API involved). Run against `provisioner/docker-compose.dev.yml`. - `test/e2e-phase2a.js` — student-flow regression through real session cookies: roster → login → curriculum → launch → Gateway routing → cross-student rejection → progress relay → reset. - `test/e2e-phase2b.js` — the classroom acceptance workflow: instructor creates a cohort, adds students, assigns curriculum, Prepare Labs (concurrent), students complete different scenarios, instructor resets one, instructor destroys all cohort Labs after class — progress survives every step. - `test/e2e-phase3a.js` — persistent sessions (including a real Platform API restart), instructor auth (no enumeration, rate limiting), RBAC across owner/admin/instructor, cohort-scoped instructor access, CSRF enforcement, password change, and audit logging. - `test/e2e-phase3b.js` — attempt telemetry, progressive hint sequencing/persistence through a Lab reset, curriculum stage/Capstone lock-unlock, the exam engine (random draw, server timer, expiry, restart persistence), the Capstone workflow end to end, two-student assessment isolation, and instructor learning analytics/RBAC. All four e2e suites need `OWNER_EMAIL` / `OWNER_PASSWORD` set to a real bootstrapped instructor account (see "Running the full stack locally" above) — the old `ADMIN_PASSWORD` mechanism is gone. They're slow (real k3s boots, `e2e-phase3b.js` also runs a real API restart) and need the full stack up. None of them substitute for the manual real-Lab-image checks (node-pty, terminal WebSocket, `kubectl`, scenario validation) in `docs/PHASE2A_GATEWAY_AND_STUDENT_FLOW.md` §8 — those need a browser-equivalent client and aren't automated here. ## Known limitations See `provisioner/README.md` (Phase 1), `docs/PHASE2A_GATEWAY_AND_STUDENT_FLOW.md` §9 (Phase 2A), `docs/PHASE3A_IDENTITY_AND_INSTRUCTOR_ACCESS.md` (Phase 3A identity limitations), and `docs/PHASE3B_LEARNING_AND_ASSESSMENT.md` §20 (Phase 3B learning/assessment limitations) for the full, honest lists. ## Running this in production `../infra/` has the full production infrastructure package (Ansible, Terraform, firewall, monitoring, backup, CI/CD) for deploying the Platform API/Gateway/Provisioner/Postgres onto a dedicated `rn-platform-01` VM, with student Labs on a separate `rn-lab-host-01` VM. See `../docs/PHASE4_PRODUCTION_INFRASTRUCTURE.md` for the overview and `../docs/PRODUCTION_NETWORK_SECURITY.md` for a known gap in Gateway-to-Lab reachability across two real VMs that must be closed before production go-live.