Commit Graph
173 Commits
Author SHA1 Message Date
ced4568andClaude Sonnet 5 788fb197e0 docs(phase8): document enrollment operations
New: PHASE8_ENROLLMENT_OPERATIONS.md (phase summary), WINTER_BREAK_CAMP_OPERATIONS.md
(the real operational walkthrough), REGISTRATION_AND_GUARDIAN_COMMUNICATIONS.md,
OFFERING_ADMIN_GUIDE.md.

Updated: ROOTNODE_ACADEMY_BUSINESS_AND_PRODUCT_ARCHITECTURE.md (BUILT NOW/PHASE 8 BUILT
table), OFFERING_AND_REGISTRATION_MODEL.md (both ordering bugs, launch readiness,
registration enforcement), STUDENT_GUARDIAN_DATA_MODEL.md (guardian communications now
wired), WEBSITE_ENROLLMENT_INTEGRATION.md (the real, live registration contract with
worked examples, replacing the old speculative future-flow section), platform/README.md
(test list).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 23:59:42 -05:00
ced4568andClaude Sonnet 5 aa63d09fb8 test(phase8): add enrollment operations coverage and Winter Break registration rehearsal
- e2e-phase8.js (16/16): offering CRUD/transitions/readiness, registration open/closed
  enforcement, capacity + concurrent final-seat race through the real registration
  endpoints, the public serializer's safety, website integration idempotency (sequential +
  concurrent), adult/minor paths, required-agreement conversion blocking with version
  snapshotting, offering->cohort membership, guardian recipient resolution, RBAC, and
  confirmation ROOT_ V1/self-paced/classroom flows are unaffected.
- test-phase8-winter-camp-registration.js (12/12): the full commercial-path story with no
  payment code — website submits a real minor registration (real guardian created/matched),
  guardian agreement acceptance, a simulated admin-side payment confirmation, conversion to
  real enrollment/cohort, real account activation, an independent adult path, two students
  genuinely competing for the final seat, and a REAL Lab task completed by the minor
  student with the instructor then seeing the real progress.
- e2e-phase7.js: fixed two now-stale test assumptions the new server-authoritative
  registration-window enforcement broke (an offering left in draft that Phase 7's own test
  never transitioned before registering against it) and widened a file-allowlist check for
  the new, legitimate public-offerings-routes.js.

Regression: e2e-phase6f.js 17/17, e2e-phase5b.js 32/32, e2e-phase5c.js 29/29, all fresh-stack.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 23:59:32 -05:00
ced4568andClaude Sonnet 5 40362ec0c9 feat(admin): add Offerings operations UI
Offerings list + create; offering detail with overview (valid-transitions-only buttons),
server-computed launch readiness, required agreements, and registrations/roster;
registration detail with lifecycle transitions, agreement status, communication history
(masked recipients), and convert-to-enrollment. Reuses the existing Admin.module.css/
adminApi conventions exactly (ProgramsView.jsx's own list+detail pattern) — no new UI
framework or pattern introduced.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 23:59:20 -05:00
ced4568andClaude Sonnet 5 24eee80354 feat(offering): launch readiness, agreement requirements, guardian communications, website registration API
- Registration is now server-authoritative: draft/cancelled/completed/full/window-closed
  offerings reject registration attempts with distinct error codes (assertRegistrationOpen).
- offering_agreement_requirements + conversion-time blocking on missing required
  agreements; accepted_by_type gained 'registrant' for an adult self-accepting before
  their student_id exists.
- computeOfferingReadiness() — a server-derived launch checklist (curriculum, instructor,
  schedule, location, capacity, registration window, agreements, curriculum package).
- Guardian communications wired into the existing Phase 5C notification system: a guardian
  email fallback in resolveRecipient(), a parallel enqueueForRegistration()/
  resolveRegistrationRecipient() pair for pre-account registration-stage notifications
  (registration_received/confirmed/needs_action, agreement_required, camp_operational_update),
  five new RootNode-branded templates. Same table, same worker, same masked admin view —
  no second notification system.
- public-offerings-routes.js: the unauthenticated, explicitly-allowlisted offering read API.
- POST /api/integrations/registrations: the website's idempotent registration submission
  contract, same shared-secret boundary as the existing enrollment integration endpoint.

Two real bugs found and fixed during this phase's own testing before any commit:
(1) the five new notification_type values were wired into the worker before the DB's own
CHECK constraint was widened to accept them — every registration-stage notification was
silently failing until a comprehensive smoke test caught it (036 fixes the constraint;
every previously-silent notification catch now at least logs).
(2) firing a notification right after a registration's insert, before its seat reservation
could still fail and roll the row back, created a real foreign-key violation on rollback —
fixed by reordering createRegistration() to validate -> reserve -> insert -> notify.

See docs/OFFERING_AND_REGISTRATION_MODEL.md and docs/PHASE8_ENROLLMENT_OPERATIONS.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 23:59:11 -05:00
ced4568andClaude Sonnet 5 df5e39f767 docs(phase7): document the business/product architecture foundation
New: ROOTNODE_ACADEMY_BUSINESS_AND_PRODUCT_ARCHITECTURE.md (canonical business/platform
bridge — course families, delivery modes, BUILT NOW/PHASE 7 BUILT/FUTURE), OFFERING_AND_
REGISTRATION_MODEL.md (lifecycle diagrams, capacity mechanics), STUDENT_GUARDIAN_DATA_
MODEL.md (data minimization, RBAC, legal-review items), SCHOOL_AND_COMMUNITY_DELIVERY_
ARCHITECTURE.md (organization/location mapping, explicitly not multi-tenancy),
PHASE7_PRODUCT_ARCHITECTURE.md (phase summary).

Updated: WEBSITE_ENROLLMENT_INTEGRATION.md (documented future offering/registration flow,
current live contract unchanged), platform/README.md (test list).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 22:44:13 -05:00
ced4568andClaude Sonnet 5 7d870d8e2b test(phase7): add business/product architecture acceptance suite and Winter Camp rehearsal
- e2e-phase7.js (17/17): organizations/locations, guardians, curriculum packages
  (reference-only), offering capacity/transitions, registration lifecycle, agreements,
  registration-to-enrollment conversion, RBAC, age-guidance-independence, and confirmation
  that existing ROOT_ V1 self-paced/classroom flows are unaffected.
- test-phase7-winter-camp.js (18/18): the full Winter Break Camp operational path with NO
  payment code invoked — organization/location/curriculum-package/cohort/offering setup,
  guardian + adult registration, agreement acceptance, a simulated admin-side commerce
  confirmation, conversion to real enrollments and real cohort membership, real account
  activation via real one-time tokens, a real classroom session, and a REAL Lab task
  (linux-inspect-hardware) completed by the minor student inside a real disposable Lab
  container, confirmed to survive a real logout/login.

Regression: e2e-phase6f.js 17/17, e2e-phase5b.js 32/32 (including its own embedded Phase 5A
checks) on independent fresh stacks.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 22:44:02 -05:00
ced4568andClaude Sonnet 5 3510979196 feat(platform): business/product architecture — organizations, guardians, offerings, registrations
- organizations, locations, guardians, student_guardians (033) — additive, no existing
  table's meaning changes. Widens programs.family to accept 'bootcamp'.
- curriculum_packages/curriculum_package_items, offerings, instructor_offerings,
  offering_registrations, agreement_definitions/agreement_acceptances (034) — the full
  purchasable-delivery model. Server-defined status transitions only (no client-controlled
  offering/registration status). Capacity uses a single atomic UPDATE (reserved_seats),
  never a SELECT-count-then-INSERT race.
- offerings.js — business logic: reserveSeat/releaseSeat, transitionOffering/
  transitionRegistration (fixed transition tables), convertRegistrationToEnrollment
  (reuses enrollment.js's existing resolveOrCreateStudent/createManualEnrollment rather
  than duplicating student-matching logic).
- enrollment.js — resolveOrCreateStudent gains an optional, default-off returnToken param
  (used only by offerings.js's admin-only conversion route; the public website integration
  endpoint's contract is completely unchanged, per docs/WEBSITE_ENROLLMENT_INTEGRATION.md).
- admin-offerings-routes.js — the full admin/owner API surface. Registration/guardian
  detail is admin/owner only; offering/location listing is any instructor (access_notes
  stripped for a plain instructor).
- A real bug found and fixed during this phase's own smoke testing before any commit: the
  registration route originally reserved a seat BEFORE validating the registration's own
  fields, letting a validation failure consume a real seat and get masked behind a false
  OFFERING_FULL under a full offering. Fixed: validate (create) first, reserve second, roll
  back the registration row if reservation then genuinely fails.

See docs/ROOTNODE_ACADEMY_BUSINESS_AND_PRODUCT_ARCHITECTURE.md and
docs/OFFERING_AND_REGISTRATION_MODEL.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 22:43:52 -05:00
ced4568andClaude Sonnet 5 d066410451 docs(phase6f): document ROOT_ V1 pilot readiness
Release to Docker Hub / Build & Push Docker Image (push) Canceled after 0s
Release to Docker Hub / Create GitHub Release (push) Canceled after 0s
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]>
v0.6.0-root-v1
2026-08-26 18:33:46 -05:00
ced4568andClaude Sonnet 5 bd55b74b4f test(pilot): add multi-student and end-to-end ROOT_ V1 rehearsals
- test-phase6f-root-v1-pilot.js (22/22): a real cohort + live classroom session with three
  students in genuinely different states — on track, a real Lab validation failure/help-
  request/fix cycle, and a real admin Lab-reap/recreate with academic-state persistence
  proven, not assumed. Instructor visibility distinguishes all three.
- test-phase6f-root-v1-end-to-end.js (14/14): one student, entirely through the real
  student API, ROOT 01 through Capstone-eligible, including a real nested-Docker
  container-networking fix and an explicit proof that the real rootnode-capstone assessment
  is genuinely startable at the end — not just that the course tree says complete. Found and
  documented (not fixed) a real, pre-existing gap: the legacy six-stage Capstone unlock_rule
  requires two scenario sets (root-07-m01/m02) that are not course-layer prerequisites of
  anything on the path to root-capstone.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 18:33:35 -05:00
ced4568andClaude Sonnet 5 2864fe03dc test(phase6f): add V1 pilot acceptance suite; fix regression from real curriculum changes
- New platform/test/e2e-phase6f.js (17 tests): V1 manifest/exclusion correctness, the full
  V1 prerequisite graph, ROOT 01-04 re-verification, the orientation module's unlock
  behavior, optional-activity handling, the strengthened Capstone gate in both directions,
  instructor-notes RBAC on locked (not just draft) content, isolation, and an explicit
  age-independence check.
- foundations-helper.js: completeThroughRoot06/completeThroughRoot10 updated for the new
  practice-bank intro-lesson activities; new completeThroughCapstoneEligible() helper
  (ROOT 07-m03/m04 + full ROOT 09 + ROOT 12) shared by e2e-phase6f.js and both new drills.
- e2e-phase6a/6b/6d/6e.js: resume-pointer assertions updated for the new orientation
  module; e2e-phase6a.js's and e2e-phase6b.js's own inline ROOT 06/07/09/10/12 completion
  sequences updated for the new intro-lesson activities and the new root-09 Capstone
  dependency; e2e-phase6b.js's stale ROOT 09 status assertion and its draft-activity test
  (previously targeting the now fully-excluded ROOT 08) corrected.
- test-phase6d/6e-foundations-rehearsal.js: same orientation-module fix applied to the
  real-Lab dress rehearsals.

All of 6A (23/23) / 6B (26/26) / 6C (17/17) / 6D (21/21) / 6E (23/23) / 6F (17/17) verified
green on independent fresh stacks. See docs/PHASE6F_ROOT_V1_PILOT_READINESS.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 18:33:21 -05:00
ced4568andClaude Sonnet 5 f695b7c95d feat(content): author the ROOT_ V1 orientation module and three practice-bank intro lessons
- root-01-m00-welcome-to-root: program overview + Lab-lifecycle orientation (disposable
  Labs, permanent progress, hints, reset/recreate, help-requests).
- One short intro-lesson activity for each of the three bare practice-bank modules
  (root-06-m01, root-07-m01, root-10-m02), explaining what the bank is and why it has no
  per-scenario teaching of its own — the minimum real authoring needed for genuine
  self-paced readiness without reclassifying them optional (see the curriculum migrations).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 18:33:09 -05:00
ced4568andClaude Sonnet 5 e48710a0be feat(curriculum): integrate ROOT_ V1 scope — status corrections, ROOT 08 exclusion, Capstone/ROOT 09 gate, orientation
- Correct stale courses.status for ROOT 05/06/07/09/10/12/Capstone (all modules were
  already ready; the course-level field was never bumped in an earlier phase).
- Exclude ROOT 08 (Storage & Scheduling) from ROOT_ V1 via visibility=draft — nothing
  downstream requires it, and leaving it visible mid-sequence would look like a skipped course.
- Self-correct a same-phase mistake: reclassifying the three instructor-led-only practice
  banks (root-06-m01/root-07-m01/root-10-m02) as optional would have broken Capstone
  reachability, since their scenarios are the literal legacy stage-gate content. Kept them
  required and gave each a real intro-lesson activity instead.
- Strengthen root-capstone's prerequisites to require ROOT 09 (Security) alongside ROOT 12
  (Real Ops) — the Capstone's own scenario pool has zero security overlap, and ROOT 09 only
  reached genuine READY status this phase.
- Add a required orientation module (root-01-m00-welcome-to-root) explaining the program,
  the Learn/Practice/Lab/Troubleshoot/Validate loop, and Lab-lifecycle expectations — no
  orientation content existed anywhere before this phase.

See docs/ROOT_V1_CURRICULUM_MANIFEST.md and docs/PHASE6F_ROOT_V1_PILOT_READINESS.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 18:33:00 -05:00
ced4568andClaude Sonnet 5 87ad1251ce docs(phase6e): document the ROOT Foundations Completion milestone
Adds PHASE6E_ROOT_FOUNDATIONS_COMPLETION.md (the phase's own record: what was authored, the
dash-vs-bash scenario bug found and fixed, the pre-existing lock-enforcement gap found and
fixed, the regression fallout that fix revealed in earlier suites and why each was a stale test
assumption rather than a platform bug, and honest test/rehearsal/regression results).

Updates ROOT_FOUNDATIONS_PILOT_READINESS.md (full re-audit: all 4 ROOT Foundations courses now
READY, not inherited blindly from Phase 6D), ROOT_PROGRAM_DURATION_MODEL.md (real ROOT 02-04
duration data: 24.7 combined hours, landing inside Phase 6D's own estimated range; 67.9 hours
across the full authored program), ROOT_PILOT_CURRICULUM.md (ROOT 02-04 move from NOT IN PILOT
to IN PILOT with full module-level detail; the pilot is now genuinely self-paced-capable for the
entire foundational half, not just instructor-led), ROOT_PROGRAM_ARCHITECTURE.md and
ROOT_CURRICULUM_COVERAGE_MATRIX.md (course/module/scenario totals), and
ROOT_FOUNDATIONS_ARCHITECTURE.md (marked as-built, not just as-designed).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 17:09:02 -05:00
ced4568andClaude Sonnet 5 59edceea1f test(phase6e): acceptance suite, real-Lab rehearsal, and regression fixes for the lock fix
Adds platform/test/e2e-phase6e.js (23 checks): full ROOT 02/03/04 hierarchy/content/assessment-
pool verification, the complete ROOT 01->02->03->04->05 chain proven on one student (each
course's completion unlocking exactly the next), the direct-API lock bypass proven blocked on
both a Phase 6E course pair and a pre-existing unrelated pair, existing ROOT 06+/Capstone/
is_required behavior confirmed unaffected, self-paced no-instructor-deferral scan,
instructor-notes exclusion, RBAC, persistence, isolation, version stability, content validation.
23/23 pass against both a warm and a freshly-reset stack.

Adds platform/test/foundations-helper.js — a shared completeRootFoundations01Through04/
completeThroughRoot06/completeThroughRoot10 helper, extracted once multiple suites needed the
identical real-completion sequence as test setup, rather than duplicating it four times.

Adds infra/scripts/drills/{run,test}-phase6e-foundations-rehearsal — the real Platform API/
Gateway/Provisioner/disposable-Lab/nested-Docker/Git/k3s dress rehearsal: one real Lab task per
new course (nginx inspection, a real merge conflict, a real container-networking fix) plus the
full chain to a genuine ROOT 05 unlock, with k3s reconfirmed healthy and untouched at the end.
13/13 pass against a real, freshly-built stack.

Fixes the regression fallout from the (correct) course-routes.js lock fix: several earlier
suites' own historical shortcuts had accumulated small ordering/scenario gaps the missing
enforcement had been silently covering for — none were platform bugs. e2e-phase6a/6b/6c/6d.js
now inject the real ROOT 01-04 (and where needed ROOT 05/06/10) completion sequence via
foundations-helper.js before touching ROOT 05+ content; e2e-phase6b.js's bypass-student flow now
completes deployment-rollback/job-task/cronjob-task/container-logging-mcq explicitly (real
scenarios added in later phases that its original ALL_STAGES list never included); e2e-phase6a/
6d.js's own ROOT 01/05 completion tests now complete each module fully (through its lab and
reflection) before moving to the next, since those courses' own modules carry real intra-course
prerequisites. Two now-obsolete Phase-6D-era assertions in e2e-phase6d.js (ROOT 02-04 stay
PLANNED / stay vacuously unlocked) are updated to assert the opposite, with a comment explaining
Phase 6E intentionally changed that fact. All four suites re-verified green fresh.

Also fixes a real, reproducible dash-vs-bash bug caught while testing the new ROOT 01
rehearsal's ordering fix: `&>file` misparses under this image's actual /bin/sh (dash), breaking
a later `$!`-based kill — the rehearsal script now writes multi-line completion loops with
explicit status assertions, matching the discipline the other suites already use.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 17:08:48 -05:00
ced4568andClaude Sonnet 5 a09b7aaa53 fix(curriculum): enforce course/module lock on manual-marker completion
POST /api/student/activities/:activityId/complete previously checked only that the activity
exists and the student holds an active PROGRAM enrollment — never whether the activity's own
course/module was actually unlocked for that student. A direct POST could mark any
manual_marker activity (lesson/demonstration/knowledge_check/guided_exercise/reflection)
complete regardless of the real prerequisite chain, the exact class of gap Phase 6B already
fixed once for the capstone's own start route, just never closed for this more general one.

Found while proving the real ROOT 01->02->03->04->05 chain via direct API (this phase's own
explicit requirement) — and confirmed to predate Phase 6E entirely by reproducing it against an
unrelated, pre-existing ROOT 05/06 pair before touching any Phase 6E content.

Fix: the route now resolves the activity's own course/module through the exact same
buildCourseTree() lock computation every other route already trusts, and returns 403 { error:
'locked' } if either is locked — reusing the existing mechanism, not a second, duplicated check.
Verified live: both a ROOT 02 bypass attempt and a ROOT 06 bypass attempt are now correctly
rejected; legitimate unlocked completions are unaffected.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 17:08:28 -05:00
ced4568andClaude Sonnet 5 682ef2de47 feat(root04): author Containers & Docker
Adds all 8 ROOT 04 modules (why containers exist, images & containers, Docker CLI, container
networking, container storage, Dockerfile & image build, Docker Compose, containers →
Kubernetes) — 43 activities, using the nested Docker Engine Phase 6D built and tested. Modules
1, 2, and 8 are conceptual (no lab by design) — the honest bridge module (M8) explicitly names
what Kubernetes adds beyond what this course already taught, without re-teaching Kubernetes
itself.

Adds 5 new hands-on Docker scenarios plus 2 MCQs, all against the real nested Docker Engine:
docker-cli-basics (run/exec/inspect a real container), docker-container-networking (a genuine
"works internally, unreachable from host" port-publishing failure, diagnosed and fixed by
recreating the container with the correct `-p` flag), docker-container-storage (a real
destroy/recreate cycle proving named-volume persistence, not just described), docker-build-image
(a real Dockerfile, a real build, a real custom image run), and docker-compose-multiservice (a
real two-service Compose application with a real published port). All tested end-to-end via the
real scenario-validation API, including negative tests.

Wires rootnode-containers-assessment (2 required + 4 random-draw scenarios) using the existing
Phase 3B assessment engine.

This completes the entire ROOT_ Foundations sequence (ROOT 01-04) — see
docs/PHASE6E_ROOT_FOUNDATIONS_COMPLETION.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 17:08:14 -05:00
ced4568andClaude Sonnet 5 e68b6f445a feat(root03): author Git & Collaborative Development
Adds all 6 ROOT 03 modules (why version control exists, the Git mental model, everyday Git,
branching & merging, remote repositories, engineering Git workflow) — 31 activities. Uses only
real LOCAL Git repositories throughout — no Gitea account, no network access, and no
RootNode-canonical-repo credential is ever needed or exposed in a student Lab
(docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md §4). Modules 1, 2, and 6 are conceptual bookends with no
lab, matching the flexible readiness standard already used in ROOT 01/02.

Adds 3 new hands-on Git scenarios plus 2 MCQs: git-everyday-basics (init/add/commit, validated
by inspecting real `git log`/`git show` state, not just command output strings — Step 6's
explicit requirement), git-branching-and-merge (a REAL merge conflict caused on purpose by two
branches editing the same line, resolved by the student, validated by confirming the conflict
markers are gone and a real two-parent merge commit exists), and git-remote-clone-push (a real
local bare repository standing in for a remote — clone/commit/push validated by inspecting the
REMOTE side directly, not just the student's own clone). All tested end-to-end via the real
scenario-validation API, including negative tests.

Wires rootnode-git-fundamentals-assessment (2 required + 3 random-draw scenarios) using the
existing Phase 3B assessment engine.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 17:08:00 -05:00
ced4568andClaude Sonnet 5 e007bcf000 feat(root02): author Linux Administration & Networking
Adds all 6 ROOT 02 modules (Linux system administration, storage & filesystems, the
Networking Mental Model, Linux network inspection, DNS & HTTP, Linux troubleshooting) — 37
activities, each with a real lesson, demonstration/guided exercise, knowledge check, hands-on
Lab, and reflection. The Networking Mental Model module (M3) gets deliberately extra depth per
its "critical module" designation, with no lab by design — conceptual mastery via knowledge
check and guided exercise, matching root-05-m00's own precedent.

Adds 6 new hands-on Linux/networking scenarios plus 2 MCQs: linux-service-inspection (inspects
the platform's own real nginx without touching it — a genuinely safe, real service-inspection
target that avoids ever risking the Lab's own connectivity), linux-service-lifecycle (start/
verify/stop a fully controllable service), linux-storage-inspection, linux-network-inspection
(ip/ss/getent/curl, each framed as answering one specific diagnostic question),
linux-dns-http-diagnosis (a genuine DNS-resolves-but-wrong-port failure, diagnosed and fixed),
and linux-troubleshooting-framework (a real missing-config-file failure, resolved via the
RootNode Observe/Evidence/Hypothesis/Test/Repair/Validate/Prevent framework). All tested
end-to-end via the real scenario-validation API, including negative tests confirming they fail
when unsolved.

Wires rootnode-linux-networking-assessment (2 required + 4 random-draw scenarios) using the
existing Phase 3B assessment engine.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 17:07:46 -05:00
ced4568andClaude Sonnet 5 b6516a74db docs(phase6d): document the ROOT Foundations milestone
Adds PHASE6D_ROOT_FOUNDATIONS.md (the phase's own record: the generic-scenario-engine finding,
the tested container-runtime decision, what was authored, the bugs found and fixed, and honest
test/regression/rehearsal results) and ROOT_FOUNDATIONS_PILOT_READINESS.md (module-by-module
READY/DEFERRED classification for ROOT 01-04 against the unchanged Phase 6C readiness standard —
ROOT 01 READY, ROOT 02-04 DEFERRED by design).

Adds ROOT_PROGRAM_DURATION_MODEL.md — real per-course instructional-hour totals computed from
actual estimated_duration_minutes values (2,931 minutes / 48.9 hours across all authored
content), not invented, with an explicit note on why instructor-led timing isn't a separate
summable field yet.

Updates ROOT_PROGRAM_ARCHITECTURE.md (ROOT 01's new READY status and the real 01-04 prerequisite
chain), ROOT_PILOT_CURRICULUM.md (ROOT 01 added to the pilot, module-level detail), and
ROOT_CURRICULUM_COVERAGE_MATRIX.md (updated module/scenario totals) to reflect what Phase 6D
actually built, without restating Phase 6C's own Kubernetes-scenario tables.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 13:00:41 -05:00
ced4568andClaude Sonnet 5 f5379afd5c test(phase6d): acceptance suite, real-Lab rehearsal, and 6A/6B resume-point fixes
Adds platform/test/e2e-phase6d.js (20 checks): ROOT 01 hierarchy, ROOT 02-04 honestly empty
(not padded), activity ordering, lab-cannot-be-manually-completed, full course completion via
lesson/lab/assessment, the prerequisite chain proven on two students (one who completed ROOT 01,
one fresh), existing ROOT 05+/Capstone state unaffected, is_required unaffected, self-paced
no-instructor-deferral check, instructor-notes exclusion, RBAC, logout/login persistence,
cross-student isolation, version-bump stability, and content validation. 20/20 pass against both
a warm and a freshly-reset dev stack.

Adds infra/scripts/drills/{run,test}-phase6d-foundations-rehearsal — the real disposable-Lab
dress rehearsal: login -> enroll -> lesson/guided-exercise -> real Lab launch -> real bash
hardware inspection (nproc/free/df, written to a real file) -> real validation -> a genuine
permission denial (a second Linux user actually denied via `su -`) then a real chmod fix ->
remaining modules -> assessment -> course completion -> ROOT 02 unlock -> logout/login
persistence -> instructor visibility of the resulting learning state. 11/11 pass against a real
Lab container, no mocking. (First run caught a real triple-escaping bug in the hardware-report
step's inline heredoc — fixed by writing the script to a file and docker-cp-ing it in instead.)

Fixes two stale hardcoded assumptions in e2e-phase6a.js and e2e-phase6b.js that this phase's own
ROOT 01 addition broke: both suites asserted `resume` landed on ROOT 05's gold module as "the
first real content," which was true before this phase and is now ROOT 01. Both suites' original
intent (resume must never land on a bare-lab bank) is preserved, just against the current front
door. Both suites re-verified green (21/21 and 24/24) against a fresh stack.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 13:00:17 -05:00
ced4568andClaude Sonnet 5 15b616274b feat(root01): author Computing & Linux Foundations, and the real 01->05 prerequisite chain
Adds all 6 ROOT 01 modules (how computers run software, the shell, filesystem navigation,
files & text, processes, users & permissions foundations), each with a real lesson,
demonstration/guided exercise, knowledge check where warranted, a hands-on Lab, and a
reflection — 35 activities, 29 new content files.

Adds 6 new hands-on Linux scenarios (linux-inspect-hardware, linux-shell-basics,
linux-filesystem-navigation, linux-files-and-text, linux-process-management,
linux-permissions-foundations) plus 2 MCQ scenarios, using the existing generic scenario/
validation engine (docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md §1) — every one tested end-to-end via
the real scenario setup/validate API, including negative tests confirming they correctly FAIL
when not actually solved (e.g. the process-management scenario fails while the target process
is still running; the permissions scenario is tested against a real `su - labuser` denial).

Wires rootnode-linux-foundations-assessment (2 required + 4 random-draw scenarios) using the
existing Phase 3B assessment engine.

Adds a real, server-side ROOT 01->02->03->04->05 course prerequisite chain
(courses.prerequisites) — verified live on two students: one who completed ROOT 01 sees ROOT 02
unlock; a fresh student sees ROOT 02 correctly locked while 03/04/05 stay vacuously satisfied
(their own prerequisite courses are still empty). ROOT 06+ and the Capstone are unaffected.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 12:59:52 -05:00
ced4568andClaude Sonnet 5 87526bcf7f feat(labs): add a nested Docker Engine to the Lab image for ROOT 04
Installs docker.io + a static docker-compose v2 binary (same "curl a static binary" pattern
already used for k3s) inside the same already-Privileged Lab container that runs k3s.
scripts/entrypoint.sh starts dockerd (vfs storage driver, to avoid nesting overlay-on-overlay)
non-blockingly right after k3s's own API server is confirmed up — a Docker daemon failure only
logs a warning and never breaks the Kubernetes-only Labs that are the vast majority of usage.

This does not weaken the security boundary: the container was already Privileged (required for
k3s, the existing accepted threat model), so a second runtime inside it grants no new host
capability, and the Lab Host's own real Docker socket is never touched — the nested dockerd
listens on its own /var/run/docker.sock entirely inside the guest's filesystem namespace.

Tested empirically against the real production resource caps (2 vCPU, 4096MB, 512 PIDs,
Privileged: true) before merging: k3s + dockerd + a running nginx:alpine container (with a
published port, curled successfully) + a real docker build all together used 884MB/4096MB and
160/512 PIDs — comfortable headroom in every dimension. See docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md
§3 for the full test log.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 12:59:23 -05:00
ced4568andClaude Sonnet 5 3c815cfeea docs(foundations): define ROOT 01-04 architecture and Lab strategy
ROOT_FOUNDATIONS_ARCHITECTURE.md designs all 26 modules across ROOT 01 (Computing & Linux
Foundations), 02 (Linux Administration & Networking), 03 (Git & Collaborative Development), and
04 (Containers & Docker), using the existing course/module/activity model — outcomes,
prerequisites, activities, and Real Ops connections for each, per docs/COURSE_AUTHORING_STANDARD.md.

ROOT_FOUNDATIONS_LAB_STRATEGY.md documents the central finding this phase is built on: the
existing scenario engine (backend/server.js's runCommand()) executes an arbitrary shell command
string and checks its output — nothing about it is Kubernetes-specific. The existing `lab`
activity type and scenario JSON format already fully support Linux and Git exercises with real,
deterministic validation. No shell_lab/git_lab/container_lab activity type is built or needed.

Also documents the container-runtime decision for ROOT 04, evaluated and tested empirically
(not assumed) against the real Lab image and production resource caps — see the following
commit for the implementation.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 12:59:00 -05:00
ced4568andClaude Sonnet 5 bd0a10fbfb docs(phase6c): pilot readiness standard, pilot curriculum manifest, ROOT 11 scope
Adds the four required Phase 6C documents:

- ROOT_PILOT_READINESS_STANDARD.md — the explicit 8-point sufficiency bar
  used to judge every module this phase, replacing any fixed activity-count
  assumption.
- ROOT11_DEVOPS_PLATFORM_SCOPE.md — evaluates all 7 proposed ROOT 11 modules
  individually (READY TO AUTHOR NOW / PARTIAL-LESSON-ONLY / REQUIRES FUTURE
  LAB ENVIRONMENT), with what current infra supports vs. what GitOps/CI-CD/
  IaC/observability would each require.
- ROOT_PILOT_CURRICULUM.md — the authoritative pilot manifest: instructor-led
  as the first pilot's delivery mode, honest READY/PARTIAL/DEFERRED/NOT IN
  PILOT status per course and module, and what is intentionally excluded
  (ROOT 01-04 never authored, ROOT 08 non-capstone-gating and deferred, ROOT
  11 modules 2-7, three practice-bank modules instructor-led-only this pilot).
- PHASE6C_CURRICULUM_COMPLETION.md — the phase's own record of what was
  upgraded, why, the bug found and fixed, and the pilot readiness conclusion.

Updates ROOT_CURRICULUM_COVERAGE_MATRIX.md with the verified before/after
module counts (21->22 modules, 6->16 READY) and per-module upgrade rationale,
and ROOT_CAPSTONE_READINESS.md with a re-review confirming the unlock gate's
6 stages, and ROOT 08/09's non-gating status, are unchanged by this phase's
curriculum expansion.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 11:21:09 -05:00
ced4568andClaude Sonnet 5 01d3764138 feat(frontend): visibility note for standalone assessment-type activities
CourseView.jsx already special-cased 'capstone' activities with a pointer to
the Capstone tab (since only capstone-type activities existed before this
phase). Phase 6C's new rootnode-security-assessment introduces the first
non-capstone 'assessment'-type module activity — without a similar note, a
student would see it in the course tree with no way to discover it needs to
be started from the Assessments tab. Adds the same pattern for 'assessment'
type, naming the assessment by its own title.

No other frontend change was needed: CurriculumView.jsx (instructor view)
already renders activity_type labels, scenario_id/assessment_definition_id,
is_required, instructor_notes availability, and READY/PARTIAL/PLANNED status
pills generically — Phase 6C's new module/activity shapes render correctly
under Phase 6B's existing generic logic, verified by inspection.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 11:20:51 -05:00
ced4568andClaude Sonnet 5 903b0ead43 test(phase6c): acceptance suite, real-k3s rehearsal, and 6A/6B staleness fixes
Adds platform/test/e2e-phase6c.js (17 checks): upgraded-module activity
chains, documented-exception promotions, optional-lab non-blocking behavior,
no-fake-completion-from-viewing, idempotent completion, instructor-notes
exclusion and RBAC on new content, security-assessment pool/draw/cross-student
isolation/completion, the capstone gate's documented indifference to ROOT 09,
ROOT 11's honest partial/lesson-only rendering, and version-bump content
stability — plus running validate-course-content.js as part of the suite.
All 17 pass against both a warm and a freshly-reset dev stack.

Adds infra/scripts/drills/{run,test}-phase6c-security-config-rehearsal —
Section 22's real-k3s dress rehearsal: login -> program -> course -> lesson ->
demonstration -> knowledge-check -> guided-exercise -> real Lab -> real
kubectl (create Secret, apply Pod, wait for Ready) -> validation -> progress
persistence across logout/login -> instructor visibility of the resulting
learning state, walking root-07-m02-configuration-and-secrets (upgraded from
PARTIAL this phase). 10/10 pass against a real k3s Lab, no mocking.

Fixes two stale hardcoded assumptions in e2e-phase6a.js and e2e-phase6b.js
that Phase 6C's own legitimate content changes broke: the gold module
(root-10-m01) now has 7 activities (6 required + 1 new optional lab, not 6),
and root-05-m01 now has 2 required manual-marker activities the course-
completion path must also complete (its new bookending lesson/reflection).
Both suites are back to green (21/21 and 24/24) against a fresh stack.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 11:20:37 -05:00
ced4568andClaude Sonnet 5 7f6e1857c0 feat(curriculum): Phase 6C module upgrades, security assessment bank, ROOT 11 orientation
Upgrades six PARTIAL modules to the gold-module standard (lesson/demonstration/
knowledge-check/guided-exercise/lab(s)/reflection), preserving every existing lab
activity_id and scenario_id: root-06-m03 (jobs/cronjobs/daemonsets), root-07-m04
(ingress/networkpolicy), root-07-m02 (configuration/secrets, converted in place
from a bare 5-lab bank), root-09-m02 (serviceaccounts/rbac), root-09-m03
(network/supply-chain security), root-10-m03 (troubleshooting framework).

root-05-m01 (20-task kubectl-fluency bank) gets a minimal bookending lesson +
reflection rather than a full redesign, since each task already carries its own
explanation. root-12-m01, root-capstone-m01, and root-09-m04 are promoted to
READY via documented exceptions (no new activities) where adding one would
misrepresent their intentional design.

Wires a new rootnode-security-assessment (exam, 60min, hint_policy disabled)
using the existing Phase 3B assessment engine: 3 required hands-on CORE
scenarios + 4 random-draw pools covering SecurityContext, RBAC, network
policy, and the 7 previously-unwired CKS MCQs. Wires the previously-unwired
readiness-probe-task scenario as an OPTIONAL practice lab in root-10-m01,
using the existing is_required model.

Adds root-11-m01-devops-platform-thinking — an honest, lesson-only ROOT 11
orientation module naming DevOps/platform engineering practices already
exercised in ROOT 05-10/12, explicit that GitOps/CI-CD/IaC/observability need
lab infrastructure this platform doesn't yet provide. No fake labs.

Adds infra/scripts/validate-course-content.js: cross-checks the DB against
scenario/content files for duplicate ids, orphans, invalid references, cycles,
sequence collisions, instructor-notes leakage, and (new) self-paced content
deferring explanation to a live instructor. 0 errors against the resulting
22 courses/modules, 163 activities, 98 scenario files.

No application code changed — every gap was satisfiable with existing tables
(course_modules, module_activities, assessment_definitions) and the existing
content-delivery pipeline.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 11:20:17 -05:00
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
ced4568andClaude Sonnet 5 505783e5f7 test(phase6b): add ROOT curriculum acceptance coverage + real-Lab rehearsal
e2e-phase6b.js (24 checks): hierarchy for the 13 new modules across
ROOT 05-10/12/Capstone, prerequisite chains through the newly-inserted
front-door modules, lesson/knowledge-check completion in brand-new
modules, a newly-wired scenario (job-task) completing correctly, the
optional-vs-required (is_required) completion rule, persistence/
isolation/RBAC/draft-hiding proven against the new content, and the
capstone server-side unlock fix in both directions (a direct bypass
attempt rejected with blocking_stage_ids, an ordinary exam unaffected,
a legitimately unlocked attempt still accepted and its completion
reflected in the course content model).

test-phase6b-root-course-rehearsal.js + wrapper (11 checks, real k3s):
one continuous student narrative through a brand-new module (ROOT 07
Services & Service Discovery, not the Phase 6A gold module) — real Lab
launch, the Lab's own setup_commands, a real 'kubectl expose' against
the live cluster, real validate, logout/login/Resume Learning, Lab
destroy/recreate with academic progress intact — plus an instructor
narrative proving Curriculum view, Prepare Labs, and classroom/learning
tooling all still work against the expanded curriculum.

e2e-phase6a.js updated for two of this phase's own intentional,
documented behavior changes (not defects): resume now points at
root-05's new mental-model module instead of the old bare-lab bank, and
root-10's gold module now unlocks the new troubleshooting-framework
module rather than the bare-lab bank directly.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:09:20 -05:00
ced4568andClaude Sonnet 5 e0f954e714 feat(instructor): expand curriculum teaching visibility
CurriculumView.jsx's per-module activity table gains a Required column
(required/optional) so an instructor can see at a glance which of
Phase 6B's new CORE vs. GUIDED/INDEPENDENT/ADVANCED activities a
student needs to complete a module. Reuses the existing Classroom/
Prepare Labs tooling unchanged — no second classroom system.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:08:54 -05:00
ced4568andClaude Sonnet 5 54b35e8ad7 feat(student): polish structured ROOT learning flow
CourseView.jsx now shows an '(optional)' label on any activity marked
is_required=false, both in the module activity list and the activity
detail header — the only genuine UX need Phase 6B's new optional/
advanced practice content exposed. No other changes to the existing
Course/Module/Activity navigation, Launch Lab flow, or Practice tab.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:08:28 -05:00
ced4568andClaude Sonnet 5 de6c5b3286 feat(root): build Real Ops and capstone readiness content
root-12-real-ops gains a Detect -> Triage -> Diagnose -> Mitigate ->
Recover -> Verify -> Learn incident-response framing lesson at the
front of the existing 4-incident module, and a post-incident reflection
at the end — the incidents themselves are unchanged, still deliberately
un-guided ('you are responsible for this environment,' not 'complete
this exercise'). No fixes revealed; instructor notes carry the deeper
solution guidance the student-facing lesson intentionally withholds.

root-capstone-m02-capstone-readiness — a new READY orientation module:
what the Capstone measures, how the timed/randomized draw works, time
management and troubleshooting strategy under a clock, and a genuine
self-assessment checklist. Never publishes the current draw or answers.
See docs/ROOT_CAPSTONE_READINESS.md for why this module's completion is
deliberately independent of the real capstone's server-side unlock gate.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:08:01 -05:00
ced4568andClaude Sonnet 5 831486d664 feat(root): expand troubleshooting and observability curriculum
The Phase 6A gold-standard Health Probes module is preserved byte-for-
byte unchanged — it's the template, not a page to rewrite for
consistency.

root-10-m03-troubleshooting-framework — a new PARTIAL module
introducing a repeatable Observe -> Gather Evidence -> Form Hypothesis
-> Test -> Repair -> Validate -> Prevent Recurrence framework, applied
to a CrashLoopBackOff and a broken Service selector. Lesson,
demonstration (the full framework walked through a real
CrashLoopBackOff, command by command), knowledge check, and real Labs
(crashloop-fix, endpoint-fix-task). Sequenced between the gold module
and the existing bare-lab bank, which now sits behind it.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:07:34 -05:00
ced4568andClaude Sonnet 5 960a638ec9 feat(root): add Kubernetes security curriculum
Four new modules, moving ROOT 09 off PLANNED and building the
22-scenario CKS-style bank into a coherent course instead of
disconnected exam tasks — see docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md
for the CORE/GUIDED/INDEPENDENT/ADVANCED/ASSESSMENT-BANK classification
behind every placement.

root-09-m01-security-model-and-securitycontext — READY, full
gold-standard pattern: defense in depth, least privilege, hardening a
Pod with SecurityContext. Lesson, demonstration (a Pod before/after
hardening), knowledge check, guided exercise (a hardening checklist),
real Labs (CORE: non-root/drop-capabilities/read-only-fs/
pod-security-context; GUIDED: seccomp; ADVANCED: AppArmor; INDEPENDENT:
the generic pod-security-context duplicate), and a reflection.

root-09-m02-serviceaccounts-and-rbac — PARTIAL: workload identity and
least-privilege permissions. Lesson + knowledge check + real Labs.

root-09-m03-network-and-supplychain-security — PARTIAL: NetworkPolicy
as a security control (default-deny), image/registry trust, TLS
ingress. Lesson + knowledge check + real Labs.

root-09-m04-cluster-hardening-and-runtime — PARTIAL, deliberately
survey-depth: Pod Security Admission and a lighter treatment of
audit-policy/runtime-sandboxing topics that don't belong in the core
daily-driver path.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:07:07 -05:00
ced4568andClaude Sonnet 5 73cea1ba1d feat(root): add storage and scheduling curriculum
Two new PARTIAL modules, moving ROOT 08 off PLANNED for the first time:

root-08-m01-storage-fundamentals — ephemeral vs. persistent storage,
PV/PVC/StorageClass. Lesson + knowledge check + real Labs (emptydir-pod,
pv-pvc-mount, pvc-dynamic-task, storageclass-mcq).

root-08-m02-scheduling-resource-governance — how the scheduler places
Pods and how quotas/limits/priority/disruption budgets shape that
placement. Lesson + knowledge check + real Labs (node-label-selector,
node-taint-toleration, pod-affinity-mcq, priority-class-task,
pod-disruption-budget-task, resource-quota-ns, limitrange-task).

cluster-upgrade-mcq and etcd-backup-mcq deliberately left unwired —
ROOT 11/DevOps territory, out of this phase's scope, not overlooked.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:06:43 -05:00
ced4568andClaude Sonnet 5 dbcc210889 feat(root): author networking and configuration curriculum
root-07-m03-services-and-service-discovery — a new, full gold-standard-
pattern module: the Service/Endpoints/DNS request path, choosing the
right Service type. Lesson, demonstration (a Service with zero
Endpoints — the single fastest diagnostic check for this failure
class), knowledge check, guided exercise (ClusterIP vs. NodePort vs.
LoadBalancer for three real components), a real Lab
(expose-service-basics), and a reflection.

root-07-m04-ingress-networkpolicy-foundations — a new PARTIAL module:
Ingress and NetworkPolicy at the architectural level (the security-
control framing of NetworkPolicy is deliberately deferred to ROOT 09).
Lesson + knowledge check + real Labs (ingress-task, network-policy).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:06:19 -05:00
ced4568andClaude Sonnet 5 86ea035e9b feat(root): author workloads curriculum
root-06-m02-deployments-scaling-updates — a new, full gold-standard-
pattern module: why Deployments/ReplicaSets exist, how a rolling update
actually progresses, and what rollback restores. Lesson, demonstration
(a healthy rollout vs. one stalled on ImagePullBackOff), knowledge
check, guided exercise (planning a safe rollout strategy), real Labs
(rolling-update-task, deployment-rollback), and a reflection.

root-06-m03-jobs-cronjobs-daemonsets — a new PARTIAL module: Jobs,
CronJobs, and DaemonSets as distinct workload shapes from a
Deployment's always-on model. Lesson + knowledge check + real Labs
(job-task, cronjob-task).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:06:00 -05:00
ced4568andClaude Sonnet 5 25409d3bd7 feat(root): author Kubernetes foundations curriculum
root-05-m00-kubernetes-mental-model — a new, full gold-standard-pattern
front-door module for ROOT 05: what Kubernetes solves, the desired-state
model, the control-plane/worker split, and Pods/Namespaces/labels
through kubectl. Lesson, demonstration (watching a Pod get replaced
after manual deletion), knowledge check, guided exercise (planning a
Namespace layout), a real Lab (namespaces-basics), and a reflection —
sequenced ahead of the existing bare kubectl-fluency lab bank.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:05:40 -05:00
ced4568andClaude Sonnet 5 046a0fba18 fix(capstone): enforce unlock rule server-side
POST /api/assessments/:definitionId/start only ever checked that the
definition existed and was active — it never checked unlock_rule. GET
/api/capstone correctly computed and displayed lock state, and the
student UI never exposed a start action while locked, but a direct POST
to this route bypassed the check entirely (documented as a known gap in
docs/PHASE6A_ROOT_COURSE_FOUNDATION.md §10). Student UI state is not the
enforcement boundary.

Fixed by binding to the exact same computeCurriculumState() gate
/api/capstone already relies on, rather than re-parsing
definition.unlock_rule independently — one computation of 'is this
unlocked,' not two that could drift. Only a definition the curriculum
path actually names as ITS capstone is gated this way; an ordinary exam
is completely unaffected. Returns a clean 403 { error: 'locked',
blocking_stage_ids } — the same shape /api/capstone already exposes.

Found while fixing this: e2e-phase5b.js's own capstone-completion test
had been passing only because of this exact gap — it never included the
real-ops stage in its completion loop before attempting to start the
capstone, and the missing unlock check let it succeed anyway. Fixed
alongside the platform code (REAL_OPS added to ALL_NON_CAPSTONE), not
routed around.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:05:18 -05:00
ced4568andClaude Sonnet 5 bee57d89fd feat(root): wire ROOT 05-10/12/Capstone curriculum expansion
023_phase6b_curriculum.sql — additive on top of 022_course_content.sql:
13 new teaching modules (ROOT 08/09 move from PLANNED to PARTIAL; ROOT
05-07/10 gain a new front-door module sequenced ahead of the existing
bare-lab bank; ROOT 12 gains an incident-response framing lesson +
reflection; Capstone gains a readiness module). No existing row is
deleted; a small number of existing rows have their sequence/
prerequisites updated so a new teaching module supersedes the bare-lab
bank as the front door — never their scenario_id/activity_type/
completion_behavior, so no student's derived completion changes meaning.

is_required (new module_activities column, defaults true — every Phase
6A activity unaffected) lets a module distinguish CORE teaching from
GUIDED/INDEPENDENT-practice duplicates and ADVANCED/optional extras.
course-progress.js's totals() now considers a module complete once
every REQUIRED activity is done, not literally every activity — an
incomplete optional one no longer blocks completion, though it still
counts toward the displayed percentage.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:04:55 -05:00
ced4568andClaude Sonnet 5 82f17a05e8 docs(curriculum): map Phase 6B ROOT coverage
Course -> module -> objective -> lesson/demo/knowledge-check/guided-
exercise -> scenario(s) -> Real Ops connection -> status, for ROOT 05-10,
12, and Capstone, grounded in the Phase 6A inventory. Every scenario
placement has an intentional reason, not a coverage-percentage target —
includes an explicit 'duplicate concepts identified' section for the
near-duplicate scenario pairs (pod-security-context vs.
cks-pod-security-context, rbac-clusterrole vs. cks-rbac-clusterrole,
network-policy's architectural vs. security-control framing) and which
scenarios are deliberately left out of structured curriculum entirely.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:04:30 -05:00
ced4568andClaude Sonnet 5 fd38d06055 docs(phase6a): document RootNode course foundation
COURSE_AUTHORING_STANDARD.md — the standard every future lesson/module
must follow (target learner, prerequisites, measurable objectives,
concept-before-lab, instructor notes, terminology, versioning, review
requirements), grounded in the gold-standard module as the reference
implementation.

PHASE6A_ROOT_COURSE_FOUNDATION.md — the phase summary: youth-ladder
context, the Google Workspace status already recorded in Phase 5C's own
docs, architecture/build summary, honest content states, test results,
explicit non-goals, and known limitations/Phase 6B recommendations.

Updated ENGINEERING_SOP.md (new Phase 6A section + a curriculum-content
cross-reference), REMOTE_AND_SELF_PACED_ARCHITECTURE.md (a 7th
closed gap: self-paced enrollment now resolves to a real course tree,
not just a scenario list), LAB_ARCHITECTURE.md (Phase 6A reuses the
disposable Lab unmodified, verified by a real rehearsal), and
platform/README.md (course model in the api/ summary, new e2e suite
descriptions for 5A/5B/5C/6A which were missing entirely, and the
real-Lab rehearsal script).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:30:11 -05:00
ced4568andClaude Sonnet 5 8ffc923a84 test(phase6a): add course-delivery acceptance coverage + real-Lab rehearsal
e2e-phase6a.js (21 checks): hierarchy/ordering, honest READY/PARTIAL/
PLANNED states, all three completion behaviors (manual marker/
scenario-derived/assessment-derived), prerequisite locking (including
the zero-content-is-vacuously-satisfied rule), resume, persistence
across logout/login, cross-student isolation, RBAC for self-paced
no-cohort students, draft-content hiding, and content-version
stability.

test-phase6a-course-rehearsal.js + run-phase6a-course-rehearsal.sh: a
real-k3s dress rehearsal of the gold-standard module end to end — a
student reads the real lesson content, launches a real disposable Lab,
the Lab's own POST /api/scenarios/:id/setup (called through the
Gateway's existing /lab/:token/* proxy exactly as the browser UI does)
stands up the broken api-gateway deployment, a real kubectl patch fixes
the readiness probe, and the module completes and unlocks the next one.
No mocked KubeKosh anywhere in this suite.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:30:00 -05:00
ced4568andClaude Sonnet 5 db927b8081 feat(instructor): add curriculum teaching view
CurriculumView.jsx — a new 'Curriculum' tab in the admin portal:
program structure (courses -> modules -> activities), mapped scenarios/
assessments, estimated teaching time, and instructor notes rendered per
activity. A student_id lookup shows one student's real per-activity
progress alongside the same structure, for spotting where someone is
stuck. Read-only, no WYSIWYG editor — course/module authoring stays
Git/migration-based this phase per docs/COURSE_CONTENT_MODEL.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:50 -05:00
ced4568andClaude Sonnet 5 8c09ef8f3e feat(student): add structured course learning experience
CourseView.jsx — My Programs -> ROOT_ -> Course -> Module -> Activity ->
Launch Lab -> back -> continue, nested inside the existing self-paced
ProgramsTab rather than a second portal. Renders lesson/demonstration/
knowledge-check/guided-exercise/reflection content via the existing
react-markdown+remark-gfm stack (already used by ScenarioPanel.jsx — no
new dependency). Locked modules/courses are inert, not hidden — the
server is still the actual gate (course-routes.js).

ProgramsTab.jsx gains a 'View Courses' button alongside the existing
'Continue Learning' button — the original direct-to-Lab flow is
byte-for-byte unchanged; both paths call the identical launch sequence
underneath.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:41 -05:00
ced4568andClaude Sonnet 5 28c925069b feat(root): author the health-probes gold-standard module
content/root/root-10-kubernetes-troubleshooting-observability/m01-health-probes/:
lesson (probe concepts) -> demonstration (reading kubectl describe pod
Events for a probe failure) -> knowledge check -> guided exercise
(write a readiness probe on paper) -> Launch Lab intro
(rootnode-probe-port-mismatch) -> reflection (root cause + Real Ops
prevention takeaway). 5 of 6 activities carry instructor notes (demo
plan, misconceptions, timing, discussion questions, extensions).

This is the reference implementation docs/COURSE_AUTHORING_STANDARD.md
documents for all future RootNode lesson authoring.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:32 -05:00
ced4568andClaude Sonnet 5 e2298e95de feat(root): wire course/module/activity routes into the Platform API
course-routes.js — student-facing: the full course tree through an
enrollment (GET /api/student/programs/:id/courses) and the lesson
completion marker (POST /api/student/activities/:id/complete, refused
for anything but a manual_marker activity — a lab/assessment can never
be faked complete through this route).

admin-course-routes.js — instructor-facing, read-only (no WYSIWYG CMS
this phase): program structure with instructor notes
(GET /api/admin/programs/:id/courses) and per-student progress
(GET /api/admin/students/:id/courses), scoped via
requireStudentRelationshipAccess — the same self-paced-no-cohort rule
Phase 5C's notification routes already established, not
requireStudentCohortAccess (which would 403 a plain instructor out of
every self-paced student).

Dockerfile now also COPYs content/ alongside the existing scenarios/ —
same 'read-only, never executed' reasoning as that line.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:24 -05:00
ced4568andClaude Sonnet 5 fe702754cd feat(content): add course/module/activity content model
New tables (courses, course_modules, module_activities,
activity_completions) layered over the existing scenario/assessment/
achievement systems — a lab activity references an existing scenario_id,
an assessment/capstone activity references an existing
assessment_definition_id, neither duplicated. Long-form lesson prose
lives in git-tracked Markdown (content/root/), split into shared vs.
instructor-only sections by a '## Instructor Notes' heading convention
(content.js) rather than a second file or a CMS.

course-progress.js derives completion from EXISTING sources only:
auto_scenario reads the progress table, auto_assessment reads
achievements by assessment_definition_id, manual_marker is the one
genuinely new piece of state (for lesson-only activities with nothing
else to derive completion from). Prerequisite locking treats a
zero-content (PLANNED) prerequisite as vacuously satisfied, so an
honestly-unbuilt course never permanently locks everything after it.

Found by testing: computing a level's prerequisite lock and stripping
its working totals in the same map iteration made the result depend on
iteration order. Fixed with two explicit passes.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:13 -05:00
ced4568andClaude Sonnet 5 f152b9a489 docs(curriculum): define the ROOT_ program architecture
13 courses (ROOT 01-12 + Capstone) under the existing single
root-kubernetes-foundations program — root_ is one continuous ladder a
student enrolls in once, not thirteen separate purchases. Honest
READY/PARTIAL/PLANNED states grounded in the actual inventory: no course
reaches READY yet, 5 are fully PLANNED (no Linux/Git/Docker/DevOps
scenario content exists anywhere in this repo), 7 are PARTIAL (real
labs, no lessons yet). Documents the prerequisite graph and why it
deviates from a strictly linear 01->12 chain where the existing content
doesn't actually support one.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:03 -05:00
ced4568andClaude Sonnet 5 e4cbcf6c40 docs(curriculum): inventory existing RootNode learning assets
Full inventory of scenarios/data/ (98 scenarios), scenarios/bundles/,
rootnode-path.json's stage structure, assessment_definitions, and the
programs/achievements model — gathered by inspection before any Phase 6A
design work, nothing modified to produce this.

Only 3 scenarios are RootNode-authored; the other 95 (including all 44
wired into rootnode-path.json) are generic upstream Kubernetes/CKS
content. 54 scenarios exist with no rootnode-path.json stage at all —
a real, working content bank for future ROOT 07/08/09/10 modules,
inventoried and grouped by category rather than left undiscovered.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:28:55 -05:00