New: PHASE6F_ROOT_V1_PILOT_READINESS.md (phase summary), ROOT_V1_CURRICULUM_MANIFEST.md (canonical V1 scope), ROOT_V1_PREREQUISITE_MAP.md, ROOT_V1_ASSESSMENT_MAP.md, ROOT_V1_SYLLABUS.md, ROOT_V1_INSTRUCTOR_GUIDE.md, ROOT_V1_STUDENT_REQUIREMENTS.md, ROOT_V1_INSTRUCTOR_LED_PILOT.md, WINTER_BREAK_CAMP_CURRICULUM_OPTIONS.md. Updated: ROOT_PROGRAM_ARCHITECTURE.md (course-sequence table reflects real V1 statuses), ROOT_PILOT_CURRICULUM.md (self-paced-readiness correction), ROOT_PROGRAM_DURATION_MODEL.md (real post-integration totals: 64.2 V1 hours / 68.3 program-wide), ROOT_CAPSTONE_READINESS.md (§1b, the new root-09 course-layer gate), platform/README.md (test list). Co-Authored-By: Claude Sonnet 5 <[email protected]>
152 lines
11 KiB
Markdown
152 lines
11 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 and cohort membership, 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), self-paced programs/enrollment + the website integration boundary (Phase 5B), and
|
||
a provider-neutral enrollment-communications pipeline (activation/enrollment-confirmation/
|
||
password-reset email, Phase 5C), the ROOT_ course/module/activity content model layered over
|
||
curriculum/assessments (Phase 6A) with real teaching content across most of the Kubernetes
|
||
courses and a server-side capstone unlock enforcement fix (Phase 6B), 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),
|
||
`docs/PHASE5B_SELF_PACED_ENROLLMENT.md` (programs, enrollment, website integration boundary),
|
||
`docs/PHASE5C_ENROLLMENT_COMMUNICATIONS.md` (notifications, email delivery),
|
||
`docs/PHASE6A_ROOT_COURSE_FOUNDATION.md` (course/module/activity content model, gold-standard
|
||
module), `docs/PHASE6B_ROOT_CURRICULUM_EXPANSION.md` (curriculum authoring across ROOT
|
||
05-10/12/Capstone, the capstone unlock fix). 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.
|
||
- `test/e2e-phase5a.js` — real student credentials (activation/password reset/login), remote
|
||
classroom sessions (join/heartbeat/announcements/help requests), and instructor conversion of
|
||
a pilot student to a credentialed account.
|
||
- `test/e2e-phase5b.js` — programs/enrollment, entitlement gating (pending/future/expired/
|
||
cancelled), server-derived completion, disposable-Lab persistence across destroy/recreate, and
|
||
the website/commerce integration boundary (idempotency, concurrency, RBAC).
|
||
- `test/e2e-phase5c.js` — the notification lifecycle (queue/retry/failure/exhaustion),
|
||
activation/enrollment-confirmation/password-reset email delivery via the deterministic dev
|
||
provider, minor/no-email contact-email resolution, and admin notification RBAC.
|
||
- `test/e2e-phase6a.js` — course/module/activity hierarchy and ordering, prerequisite-based
|
||
locking, all three completion behaviors (manual marker/scenario/assessment-derived), resume,
|
||
cross-student isolation, RBAC for self-paced (no-cohort) students, and draft-content hiding.
|
||
- `test/e2e-phase6b.js` — hierarchy for the 13 new modules across ROOT 05-10/12/Capstone,
|
||
prerequisite chains through the newly-inserted front-door modules, the optional-vs-required
|
||
(`is_required`) completion rule, and the capstone server-side unlock fix in both directions
|
||
(a direct bypass attempt rejected, a legitimately unlocked attempt still accepted).
|
||
- `test/e2e-phase6c.js` — curriculum completion upgrades, the security assessment bank, and
|
||
ROOT 11's honest lesson-only scope.
|
||
- `test/e2e-phase6d.js` — ROOT 01 (Computing & Linux Foundations) as the program's real front
|
||
door, and the real ROOT 01-04 foundational prerequisite chain.
|
||
- `test/e2e-phase6e.js` — ROOT 02/03/04 completion, the full ROOT 01->02->03->04->05 chain
|
||
proven via direct API, and the course/module lock-enforcement fix on the manual-completion
|
||
route.
|
||
- `test/e2e-phase6f.js` — the ROOT_ V1 curriculum manifest (inclusions/exclusions), the full V1
|
||
prerequisite graph (no cycles, no missing nodes), the strengthened Capstone gate (ROOT 09 AND
|
||
ROOT 12 both required) in both directions, the new orientation module, and an explicit check
|
||
that no age/grade gate exists anywhere in enrollment.
|
||
|
||
`infra/scripts/drills/` also holds real-Lab dress rehearsals per phase (Phase 6D/6E foundations,
|
||
Phase 6F's multi-student pilot and full end-to-end V1 journey) — see each script's own header
|
||
and `docs/PHASE6F_ROOT_V1_PILOT_READINESS.md` for what they prove beyond what the e2e suites
|
||
above already cover via direct API.
|
||
|
||
All 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. Run each suite against its own freshly-reset stack, not chained one after another
|
||
against the same Postgres — several routes (the admin dashboard's running-lab count, a course's
|
||
percent-complete) read GLOBAL state on purpose, and chaining suites produces false failures from
|
||
shared state, not real regressions (found and documented during Phase 6A's own regression pass).
|
||
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. Two exceptions get a real-Lab
|
||
dress rehearsal instead: Phase 6A's gold-standard module
|
||
(`infra/scripts/drills/run-phase6a-course-rehearsal.sh`) and Phase 6B's curriculum expansion,
|
||
including a real `kubectl expose` and a real instructor/classroom narrative
|
||
(`infra/scripts/drills/run-phase6b-root-course-rehearsal.sh`).
|
||
|
||
## 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.
|