# Phase 6D — ROOT_ Systems Foundations Phase 6D's mission: build the foundational half of ROOT_ (ROOT 01-04) so a student reaches ROOT 05 already fluent in Linux/networking/Git and understanding why Kubernetes exists, using the existing course/module/activity model throughout. ## Baseline verification Confirmed at start: branch `main`, clean tree, HEAD = `origin/main` = `bd0a10fbfb31b05a6264d083f27d85a6f7d5d50c` (the Phase 6C milestone). ## The central architectural finding (Section 6/7) `backend/server.js`'s scenario engine (`runCommand()`) executes an arbitrary shell command string from a scenario's `setup_commands`/`validation.commands` and checks its output — nothing about it is Kubernetes-specific. This means the existing `lab` activity type and `scenarios/data/*.json` format already fully support Linux and Git exercises with real, deterministic validation. **No `shell_lab`/`git_lab`/`container_lab` activity type was built — the speculative multi-type model the authorization raised as a possibility was unnecessary.** See `docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md`. ## Container runtime decision, tested not assumed (Section 10) Installed Docker Engine (`docker.io` + a static `docker-compose` v2 binary) inside the same already-`Privileged: true` Lab container, alongside k3s. This does not weaken the security boundary — the Lab Host's own Docker socket is never touched; the nested daemon has its own socket inside the guest. Verified empirically against the real production resource caps (2 vCPU, 4096MB, 512 PIDs): k3s + dockerd + a running `nginx:alpine` container + a real image build together used 884MB/4096MB and 160/512 PIDs, comfortable headroom in all dimensions. `Dockerfile` and `scripts/entrypoint.sh` updated accordingly (dockerd starts non-blockingly alongside k3s; a Docker daemon failure never breaks Kubernetes-only Labs). ## ROOT 01 — Computing & Linux Foundations: fully authored, READY 6 modules, 35 activities, 29 new content files, 6 new hands-on scenario files (`linux-inspect-hardware`, `linux-shell-basics`, `linux-filesystem-navigation`, `linux-files-and-text`, `linux-process-management`, `linux-permissions-foundations`) plus 2 MCQ scenarios, all using the existing generic scenario/validation engine — no new mechanism. Every lab was tested end-to-end via the real scenario API (setup → solve → validate), including negative tests confirming they correctly FAIL when not actually solved. A new `rootnode-linux-foundations-assessment` (2 required + 4 random-draw scenarios) uses the existing Phase 3B engine. ## ROOT 02-04: architecture designed, content deferred `docs/ROOT_FOUNDATIONS_ARCHITECTURE.md` designs all remaining 20 modules (6+6+8) in full — outcomes, activities, and Real Ops connections for each. Given realistic effort constraints, authoring, testing, and verifying ROOT 01 to genuine READY depth was prioritized over shallow architecture-only coverage across all four courses (see `docs/ROOT_FOUNDATIONS_PILOT_READINESS.md` for the full reasoning). ROOT 02-04 remain honestly `status = 'planned'` with zero modules — not padded to look further along than they are. ## Course prerequisite chain (Section 19) `courses.prerequisites` now encodes ROOT 01→02→03→04→05 server-side, verified live: a fresh student sees ROOT 02 correctly LOCKED (ROOT 01 is real, non-empty content) while ROOT 03/04/05 stay unlocked (vacuously satisfied — their own prerequisite courses are still empty). Completing ROOT 01 unlocks ROOT 02 for that student. ROOT 06+ and the Capstone are completely unaffected (re-confirmed via regression). No UI-only hiding — this is a real `courses` table constraint the existing `prerequisitesSatisfied()` engine already enforced correctly before this phase; Phase 6D only populated real data into it. ## Extension point for placement/override (Section 20) Documented, not built: `courses.prerequisites` is a plain array a future placement assessment or instructor override could satisfy without a schema change. No bypass button implemented. ## Frontend (Sections 21-23) No frontend change was needed or made. `CourseView.jsx` and `CurriculumView.jsx` already generalized correctly to ROOT 01's activity/status shapes (lesson/demonstration/knowledge_check/ guided_exercise/lab/reflection/assessment, `ready`/`planned` status, `is_required`, `instructor_notes`) — the same generic rendering already proven for ROOT 05-12 in Phase 6C. Verified by inspection and by the real API responses `e2e-phase6d.js` and the rehearsal exercise. ## New application/platform code and why necessary - `Dockerfile` + `scripts/entrypoint.sh`: the nested Docker Engine described above — a genuine platform gap (ROOT 04's course design needs it) that the existing content model couldn't satisfy on its own, tested and justified in `docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md`. - No other application code. Every ROOT 01 requirement was satisfiable with the existing `course_modules`/`module_activities`/`assessment_definitions`/scenario-engine model. ## Bugs found and fixed - An early draft of the real-Lab rehearsal's hardware-report step used a triple-nested JS-template/shell/heredoc string that silently produced a malformed file. Caught by actually running the rehearsal against a real Lab (not assumed to work); fixed by writing the script to a file and `docker cp`-ing it in rather than an inline heredoc. - Phase 6D's own content changes made two hardcoded assumptions in `e2e-phase6a.js`/ `e2e-phase6b.js` stale: both suites asserted `resume` pointed at ROOT 05's gold module as "the first real content," which was true before this phase and is now ROOT 01. Both suites fixed and re-verified green against a fresh stack. ## Testing (Section 26) `platform/test/e2e-phase6d.js` — 20/20 passing (fresh stack): ROOT 01 hierarchy, ROOT 02-04 honestly empty, activity ordering, lab-cannot-be-manually-completed, full course completion via lesson/lab/assessment, prerequisite chain (both the locked and unlocked directions, on two separate students), existing ROOT 05+ and Capstone state unaffected, is_required rule unaffected, self-paced no-instructor-deferral check, instructor-notes exclusion, RBAC, logout/ login persistence, cross-student isolation, version-bump stability, and content validation. ## Real-Lab rehearsal (Section 27) `infra/scripts/drills/test-phase6d-foundations-rehearsal.js` — 11/11 passing against a real disposable Lab container (no mocking): login → enroll → resume → lesson/guided-exercise → real Lab launch → real bash hardware inspection (`nproc`/`free`/`df`, written to a real file) → real validation → real permission-denial-then-fix (`su - labuser`, genuinely denied, then genuinely allowed after `chmod 644`) → remaining modules → assessment → course completion → ROOT 02 unlock → logout/login persistence → instructor visibility of the resulting state. ## Regression (Section 30) Re-ran 6A (21/21), 6B (24/24), 6C (17/17) fresh, each against its own freshly-reset stack per the established isolation convention — all green after the two resume-point staleness fixes above. 2A/2B/3A/3B/5A/5B/5C were not re-run: `git diff` for this phase shows no changes to `platform/api/src/`, gateway, or provisioner code (only the Lab image/entrypoint, migrations, content, scenarios, tests, and docs), so their surface area was untouched. Frontend build: clean (`vite build`, unchanged this phase). Lab image: rebuilt and standalone-smoke-tested directly (see the container runtime section above) in addition to the full-stack rehearsal. ## Content validation `infra/scripts/validate-course-content.js` — 0 errors against 17 courses/modules with real content, 201 activities, 106 scenario files (98 + 8 new this phase). ## Known limitations / intentionally deferred - ROOT 02, 03, 04 course content — architecture designed, not authored. - ROOT 04's Docker/Compose hands-on labs specifically — platform extension done and verified, course content not yet written against it. - Instructor-led vs. self-paced timing is not a separate database field (see `docs/ROOT_PROGRAM_DURATION_MODEL.md`). - No placement testing or instructor-override UI (explicitly out of scope this phase). ## Recommended Phase 6E scope Author ROOT 02 (prioritize the "critical" Networking Mental Model module), then ROOT 03 (Git, using the already-verified local-repo strategy), then ROOT 04 (content only — the runtime is already built and tested).