Files
rootnode-academy/docs/REMOTE_AND_SELF_PACED_ARCHITECTURE.md
ced4568andClaude Sonnet 5 2db136875f docs(phase6b): document curriculum expansion
PHASE6B_ROOT_CURRICULUM_EXPANSION.md — the phase summary: what was
authored per course, the is_required extension, the capstone unlock
fix, verified scenario coverage before/after (44 -> 88 of 98, 89.8%,
by direct query not estimate), and honest known limitations/Phase 6C
recommendations.

ROOT_CAPSTONE_READINESS.md — the readiness module and the server-side
unlock fix in full detail, including why the module's completion and
the real assessment's unlock gate are deliberately independent systems.

Updated ROOT_CURRICULUM_INVENTORY.md (Phase 6B coverage numbers),
ROOT_PROGRAM_ARCHITECTURE.md (ROOT 08/09 PARTIAL, new module lists per
course), COURSE_CONTENT_MODEL.md (is_required completion rule, a new
content-versioning section per this phase's own requirement),
COURSE_AUTHORING_STANDARD.md (classifying near-duplicate/advanced
scenarios), ENGINEERING_SOP.md (new Phase 6B section),
REMOTE_AND_SELF_PACED_ARCHITECTURE.md (cross-reference), and
platform/README.md (e2e-phase6b.js, the Phase 6B rehearsal, isolation-
per-suite regression guidance).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:09:47 -05:00

7.5 KiB

Remote & Self-Paced Delivery Architecture

Phase 4.1 §12. This is an architecture review, not a new product — no self-registration, payments, or public enrollment is built here (explicit non-goal). The question this document answers: does the infrastructure and application assume "an instructor always provisions the Lab," and if so, where, and what would need to change for self-paced delivery to work.

The short answer: less of that assumption exists than expected

RootNode Academy's Lab lifecycle was built student-driven from Phase 1 — POST /api/environment/launch is called by the STUDENT'S OWN session, not by an instructor action. "Prepare Labs" (POST /api/admin/cohorts/:id/prepare-labs) is a classroom convenience that front-loads several students' launches at once before a synchronous class session, not the only path to a running Lab. This was true before Phase 4.1 and confirmed still true by this phase's own regression suites (platform/test/e2e-phase2a.js roster's two students with cohort_id: null and takes them through login → curriculum → launch → scenario work with zero cohort involvement) and by two new Phase 4.1 drills built specifically to exercise the remote/returning -student narrative:

  • infra/scripts/drills/test-lab-host-loss.js — student launches, makes progress, their Lab is destroyed out from under them (standing in for an idle-reaper destroy), Platform stays up, progress is untouched, they launch again unprompted and continue.
  • infra/scripts/drills/test-fake-cohort-rehearsal.js — the same "returns later, fresh Lab, curriculum continues" narrative as part of a fuller classroom rehearsal.

Both pass today, with zero application code changes needed for the self-paced-relevant parts of this flow specifically — see the Phase 4.1 report for the full run results.

What already works, unmodified

  • Student-initiated provisioning — no instructor step is required between "student wants to work" and "Lab exists." (platform/api/src/server.js's /api/environment/launch.)
  • Cohort-less students — cohort_id is nullable on student creation (POST /api/admin/students); a student with no cohort logs in, sees the curriculum, launches Labs, and makes progress identically to a cohorted one. Confirmed by inspection AND by the existing regression suite, not just by schema reading.
  • Idle reaper → academic state survives → return → continue — the exact lifecycle this section describes as the target self-paced experience is what Phase 1's reaper + Phase 2B's Postgres-backed academic data (separate from the disposable Lab) were already designed to produce. Phase 4.1 proved it end-to-end, twice (see above).
  • Curriculum content itself is not cohort-gated — GET /api/curriculum/path reads the one curriculum path file directly (curriculum.loadCurriculumPath()); it never checks curriculum_assignments or cohort membership at all. A self-paced student sees the full curriculum with no instructor action required to "unlock" it.

What's genuinely missing for a real self-paced product (Phase 5, not built here)

  1. No self-registration / public enrollment surface. Still true, still deliberate — Phase 5B built the boundary a separate public website will call (POST /api/integrations/enrollments, see docs/PHASE5B_SELF_PACED_ENROLLMENT.md §11 and docs/WEBSITE_ENROLLMENT_INTEGRATION.md) rather than a public sign-up form here. A student row can now be created automatically by a trusted server-to-server enrollment event, but there is still no browser-facing "sign up" page anywhere in this codebase — that's the website's job.

  2. No real student authentication. Closed in Phase 5A. Students now have real credentials (email+password or login-identifier+password, password_hash/scrypt reusing instructors' exact src/auth/password.js), a first-login/reset token flow, and Postgres- backed rate-limited/CSRF-protected sessions on the same sessions table instructors use — see docs/PHASE5A_STUDENT_IDENTITY_REMOTE_CLASSROOM.md. The old bare-student_id POST /api/login still works for not-yet-converted pilot rows only; it's rejected (409) the moment an account has real credentials or a pending activation token.

  3. curriculum_assignments.student_id is schema-ready but unwired. Addressed differently in Phase 5B. curriculum_assignments itself remains unwired, unchanged — but the real problem it was meant to eventually solve (which curriculum a given student sees) is now solved at the enrollment layer instead: enrollments.curriculum_path snapshots programs.curriculum_path per enrollment. curriculum_assignments is still available for a future direct per-student assignment need outside the program/enrollment model — it wasn't removed, just not the mechanism Phase 5B ended up using. See docs/PHASE5B_SELF_PACED_ENROLLMENT.md §4.

  4. No delivery-mode concept anywhere. Closed in Phase 5B. programs.delivery_mode/enrollments.delivery_mode (self_paced/cohort/hybrid) is now a real, snapshotted field. Capacity planning, the reaper, and Lab lifecycle mechanics still behave identically regardless of delivery mode — this only affects how enrollment/entitlement is modeled, not infrastructure.

  5. No self-paced enrollment/entitlement model. Closed in Phase 5B — see docs/PHASE5B_SELF_PACED_ENROLLMENT.md for programs/enrollments, server-enforced entitlement (pending/future/expired/cancelled), server-derived completion, and the resulting self-paced student dashboard.

  6. No enrollment communication. Closed in Phase 5C. An enrolled student now actually gets told — real activation/enrollment-confirmation/password-reset email, delivered asynchronously through a provider-neutral notification worker (Google Workspace via the Gmail API in production, a deterministic dev provider everywhere else). See docs/PHASE5C_ENROLLMENT_COMMUNICATIONS.md.

  7. No notion of a lesson, only a flat scenario list per curriculum stage. Closed in Phase 6A, for root_ only. A self-paced enrollment now resolves to a real course/module/ activity tree (lessons, demonstrations, knowledge checks, guided exercises, labs, reflections, assessments/capstone) instead of just a bare scenario id list — the same tree an instructor-led classroom student sees, consumed through the identical buildCourseTree(). See docs/COURSE_CONTENT_MODEL.md and docs/PHASE6A_ROOT_COURSE_FOUNDATION.md. Populated with real teaching content across most of the Kubernetes/operations courses in Phase 6B — see docs/PHASE6B_ROOT_CURRICULUM_EXPANSION.md. The architecture itself (this closed gap) didn't change; what a self-paced student actually finds inside it did.

What Phase 4.1 deliberately did NOT do here

No signup flow, no student password/email auth implementation, no per-student curriculum assignment route, no payments, no public course catalog, no held/premium scenario content. All explicit non-goals per this phase's authorization. Student authentication (Phase 5A), the self-paced enrollment/entitlement model (Phase 5B), and enrollment/account-lifecycle communication (Phase 5C) have all since been built; a public self-registration page, real payment processing, and a Parent/Guardian portal remain deliberately out of scope — see docs/PHASE5B_SELF_PACED_ENROLLMENT.md §12 and docs/PHASE5C_ENROLLMENT_COMMUNICATIONS.md.