Master overview (PHASE4_1_PREPRODUCTION_HARDENING.md) covering all 27 substantive items, plus REMOTE_AND_SELF_PACED_ARCHITECTURE.md (reviews what already works for remote/self-paced delivery - student-driven provisioning, cohort-less students, idle-reaper-destroy-then-continue - and the one real gap: student authentication, explicitly Phase 5 scope, not built here). Updated PRODUCTION_NETWORK_SECURITY.md (the Gateway-to-Lab gap is now RESOLVED, with the full design writeup and a new control-plane-vs-data-plane section), PRODUCTION_DEPLOYMENT.md (four-cert TLS bundle), PRODUCTION_VALIDATION_CHECKLIST.md (Router mTLS check, admission control checks), PHASE4_PRODUCTION_INFRASTRUCTURE.md and ENGINEERING_SOP.md and LAB_ARCHITECTURE.md (stale 'known gap' pointers updated to point at the resolution), BACKUP_DR.md (destructive drill), README.md and platform/README.md (Phase 4.1 pointers, lab-router component, updated known-limitations). Also fixes a real pre-existing bug found while auditing what gets committed: infra/.gitignore's patterns were written repo-root-relative (e.g. "infra/terraform/...") but the file lives in infra/, so git resolved them relative to THAT directory and none of them ever matched anything - a real .terraform/ provider cache showed up as untracked when it should have been ignored. Fixed by dropping the redundant leading "infra/" from every pattern. Status: PHASE 4.1 COMPLETE / PRE-PRODUCTION HARDENING COMPLETE / READY FOR HARDWARE DEPLOYMENT.
86 lines
5.8 KiB
Markdown
86 lines
5.8 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.** A student row is created only by an instructor
|
|
(`POST /api/admin/students`, admin/owner RBAC-gated). There is no public "sign up" surface.
|
|
This is almost certainly the right call to leave alone for now — it's explicitly a Phase 5+
|
|
product/business decision (course commerce, is it free, who's allowed to enroll), not an
|
|
infrastructure gap.
|
|
|
|
2. **No real student authentication.** A student session is created from a bare `student_id`
|
|
(`POST /api/login`, no password) — deliberately, since today every `student_id` is issued and
|
|
controlled by an instructor via the roster, not chosen or known by the public. A genuinely
|
|
remote/self-paced product where students access their account without an instructor in the
|
|
loop needs real credentials (email+password, or a magic link) — reusing the same
|
|
`password_hash`/`scrypt` machinery `instructors` already has (`src/auth/password.js`) would
|
|
be the natural extension, not a new auth system. **This is the one item on this list that
|
|
would actually block self-paced delivery today** — everything else already works or is a
|
|
product decision, not an infrastructure one.
|
|
|
|
3. **`curriculum_assignments.student_id` is schema-ready but unwired.** The table has supported
|
|
a direct per-student curriculum assignment (independent of any cohort) since Phase 2B
|
|
(`CONSTRAINT curriculum_assignment_target CHECK (cohort_id IS NOT NULL OR student_id IS NOT
|
|
NULL)`) — but nothing in the application ever reads or writes that column today; there's only
|
|
one curriculum path, so nothing has needed to differentiate yet. Not a gap that blocks
|
|
self-paced delivery now (every student already sees the one path with no gate), but the
|
|
moment a second curriculum path exists, this is where per-individual assignment lands — the
|
|
schema was designed for exactly this and doesn't need a migration to support it.
|
|
|
|
4. **No delivery-mode concept anywhere.** In-person, remote, and self-paced sessions aren't
|
|
distinguished in any data model today, and nothing currently needs them to be — capacity
|
|
planning, the reaper, and academic records all behave identically regardless of how a student
|
|
is attending. Worth being aware this is unmodeled, not worth building a taxonomy for before a
|
|
real product reason exists (YAGNI).
|
|
|
|
## 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. This document exists so Phase 5 planning
|
|
starts from an accurate picture of the gap (one real item: student authentication) instead of a
|
|
guess.
|