- PHASE5A_STUDENT_IDENTITY_REMOTE_CLASSROOM.md: the full design doc. - RUNBOOK_STUDENT_ACCOUNT_LIFECYCLE.md, RUNBOOK_REMOTE_CLASSROOM.md: operational runbooks. - REMOTE_AND_SELF_PACED_ARCHITECTURE.md: closes the 'no real student authentication' gap this doc previously flagged as the one item blocking self-paced delivery. - ENGINEERING_SOP.md §5 rewritten (was describing a pre-Phase-2A state no longer true of any deployed version of this codebase) plus a new §14; roadmap item 3 updated. - LAB_ARCHITECTURE.md, PRODUCTION_VALIDATION_CHECKLIST.md, README.md, platform/README.md: cross-references and a Phase 5A production-validation section.
103 lines
6.8 KiB
Markdown
103 lines
6.8 KiB
Markdown
# 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, real student credentials + remote classrooms
|
||
(Phase 5A), 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),
|
||
`docs/PHASE5A_STUDENT_IDENTITY_REMOTE_CLASSROOM.md` (student credentials, remote classroom).
|
||
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.
|
||
- `lab-router/` — Phase 4.1 addition. Runs on the Lab Host VM (or `dev-local`'s stand-in in
|
||
local dev, though `direct` mode there never exercises it); resolves an opaque routing token
|
||
to a local Lab container purely from Docker state, over mTLS, so the Gateway never needs a
|
||
Docker-internal address. Design: `docs/PHASE4_1_PREPRODUCTION_HARDENING.md` §1-3.
|
||
- `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 [email protected] "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. Phase 3B's "no automatic abandoned-attempt detection" and "no per-cohort
|
||
needs-attention threshold configuration" limitations were both closed in Phase 4.1 (§13/§17 of
|
||
`docs/PHASE4_1_PREPRODUCTION_HARDENING.md`); its raw-JSON pool_spec limitation was replaced with
|
||
a structured editor (§18) with an owner-only raw-JSON fallback still available. Phase 4.1's own
|
||
known limitation: real remote/self-paced delivery needs student email/password authentication,
|
||
not built — see `docs/REMOTE_AND_SELF_PACED_ARCHITECTURE.md`.
|
||
|
||
## 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 — and a new `lab-router` service
|
||
(`../platform/lab-router/`) — on a separate `rn-lab-host-01` VM. See
|
||
`../docs/PHASE4_PRODUCTION_INFRASTRUCTURE.md` for the overview and
|
||
`../docs/PHASE4_1_PREPRODUCTION_HARDENING.md` for how Gateway-to-Lab reachability across two
|
||
real VMs was closed (a Lab Host Router + mTLS data plane, simulation-tested in
|
||
`../infra/scripts/simulate-two-host/`) and for the rest of Phase 4.1's pre-production hardening.
|