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]>
108 lines
7.5 KiB
Markdown
108 lines
7.5 KiB
Markdown
# 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`.
|