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]>
This commit is contained in:
2026-08-26 12:59:00 -05:00
co-authored by Claude Sonnet 5
parent bd0a10fbfb
commit 3c815cfeea
2 changed files with 247 additions and 0 deletions
+130
View File
@@ -0,0 +1,130 @@
# ROOT Foundations Architecture — ROOT 01-04
Phase 6D §1 — the curriculum architecture for the foundational half of ROOT_, built entirely on
the existing course/module/activity model (`docs/COURSE_CONTENT_MODEL.md`) and the existing
scenario/assessment engines. See `docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md` for why no new
activity type or content model was needed. Every course below is a row that already exists in
`courses` (`status='planned'`, seeded by Phase 6A's `022_course_content.sql`) — this phase adds
their modules and activities, and updates their `status`/`objectives`/`prerequisites`.
## Course sequence and prerequisite chain
```
01 Computing & Linux Foundations
↓
02 Linux Administration & Networking
↓
03 Git & Collaborative Development
↓
04 Containers & Docker
↓
05 Kubernetes Foundations (existing)
```
Enforced server-side via `courses.prerequisites` (the same mechanism already gating
05→06→07/09/10→12→Capstone) — not UI-hidden alone. `root-05-kubernetes-foundations.prerequisites`
is updated this phase to add `root-04-containers-and-docker`, so a student cannot reach ROOT 05
without the foundations chain complete. This does not touch the capstone assessment engine's own
`unlock_rule` (still the original 6 `rootnode-path.json` stages) — course-level prerequisite
gating and the capstone's own gate remain the two independent systems `docs/COURSE_CONTENT_MODEL.md`
§5 and `docs/ROOT_CAPSTONE_READINESS.md` §3 already establish.
## Extension point for future placement/override (Step 20)
Not built this phase. The extension point already exists structurally: `courses.prerequisites`
is a plain array a future placement-assessment feature could programmatically satisfy (e.g. by
recording a passing placement score as an `activity_completions`-equivalent fact), or an
instructor override could satisfy by directly marking an enrollment's course complete through
the existing admin layer — neither requires a schema change to unlock. No bypass button is
implemented; this paragraph exists so a future phase doesn't need to reopen the prerequisite
model to add one.
---
## ROOT 01 — Computing & Linux Foundations
Target learner: a technically curious beginner with no assumed prior Linux/CLI experience.
Estimated duration: ~5.5 hours self-paced / ~4 hours instructor-led (see
`docs/ROOT_PROGRAM_DURATION_MODEL.md` for the derived total).
| # | Module | Outcome (verb-first) | Activities | Real Ops connection |
|---|---|---|---|---|
| 1 | How Computers Run Software | Explain what the OS/kernel manages (CPU, RAM, storage, processes) vs. what an application does | lesson, guided_exercise (inspect `/proc/cpuinfo`, `free -h`, `lsblk`, `ps aux` on paper first), lab (`linux-inspect-hardware` — real inspection commands), reflection | This is literally what a container later virtualizes — a Pod's resource requests/limits are promises about exactly these same resources. |
| 2 | Linux & The Shell | Use a shell confidently: run commands, read exit codes, use history/tab-completion/man pages | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-shell-basics`), reflection | Every `kubectl exec` session later drops a student into this exact shell experience. |
| 3 | Navigating the Filesystem | Navigate absolute/relative paths; explain what `/etc`, `/var`, `/home`, `/tmp`, `/usr`, `/proc` are for at a conceptual level | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-filesystem-navigation`), reflection | Container images later have this exact same tree — `/etc/nginx/nginx.conf` isn't a new idea, it's the same filesystem convention. |
| 4 | Files & Text | Manipulate files and text streams; use pipes/redirection to compose commands | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-files-and-text`), reflection | `kubectl logs \| grep` later is the exact same composition skill applied to a different data source. |
| 5 | Processes | Explain the process concept (PID, foreground/background, signals); inspect and terminate a real process | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-process-management`), reflection | A container IS (mostly) one isolated process tree — this module is the direct prerequisite for understanding what a container "contains." |
| 6 | Users & Permissions Foundations | Explain ownership and rwx permissions; use `chmod`/`sudo` correctly; state the least-privilege principle | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-permissions-foundations`), reflection | Direct root of ROOT 09's SecurityContext/RBAC — "least privilege" is introduced here first, in a context students can literally see and touch. |
Assessment: `rootnode-linux-foundations-assessment` (knowledge + state-validation, see §"Assessments" below).
## ROOT 02 — Linux Administration & Networking
Prerequisite: ROOT 01 complete. Target learner: comfortable with the ROOT 01 shell/filesystem/
process/permissions basics, ready to reason about services and networks.
| # | Module | Outcome | Activities | Real Ops connection |
|---|---|---|---|---|
| 1 | Linux System Administration | Explain packages/services/systemd conceptually; read logs; use environment variables and config files | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-admin-services-logs`), reflection | A Kubernetes controller IS a systemd-like supervisor pattern generalized across a cluster — "restart on failure" isn't new in ROOT 06, it's a concept students meet here first. |
| 2 | Storage & Filesystems | Explain block devices/partitions/mounts conceptually; distinguish persistent vs. temporary data; inspect real disk usage | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-storage-inspection`), reflection | Direct root of ROOT 08's PV/PVC model and ROOT 04's bind-mount/volume distinction. |
| 3 | Networking Mental Model | Explain hosts/interfaces/IP/subnet/gateway/DNS/ports/TCP-vs-UDP/client-server at a conceptual level | lesson, demonstration, knowledge_check, guided_exercise, reflection (conceptual module — no lab; see note below) | **Critical module** — the direct prerequisite for reasoning about Pod IPs, Services, Ingress, NetworkPolicy, and DNS later. |
| 4 | Linux Network Inspection | Use `ip addr`/`ip route`/`ss`/`ping`/`curl`/`dig` to answer a specific diagnostic question, not just run syntax | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-network-inspection`), reflection | Exactly the toolkit ROOT 10's troubleshooting framework assumes a student already has. |
| 5 | DNS & HTTP | Trace a request: browser → DNS → IP → TCP → HTTP → server → response | lesson, demonstration, knowledge_check, guided_exercise, lab (`linux-dns-http-trace`), reflection | The exact conceptual bridge `docs/ROOT_PROGRAM_ARCHITECTURE.md` names for later Kubernetes Services/Ingress/DNS. |
| 6 | Troubleshooting Linux Systems | Apply Observe→Evidence→Hypothesize→Test→Repair→Validate→Prevent to a Linux-level failure | lesson, demonstration, guided_exercise, lab (`linux-troubleshooting-framework`), reflection | Literally the same framework `root-10-m03-troubleshooting-framework` already teaches — introduced here first, at the Linux level, so it "already feels natural" by ROOT 10 (Step 15's explicit goal). |
Module 3 note: per the readiness standard's "sequence should match the subject," a purely
conceptual mental-model module earns READY through demonstrated reasoning (its knowledge check
and guided exercise), not a forced lab — mirroring `root-05-m00`'s own precedent. Module 4
immediately after it is where the same concepts become hands-on.
Assessment: `rootnode-linux-networking-assessment`.
## ROOT 03 — Git & Collaborative Development
Prerequisite: ROOT 02 complete. Uses only local repositories (a working tree + a local bare
"remote") inside the student's own Lab — no Gitea account, no network credential, no
RootNode-canonical-repo access ever reaches a student Lab (`docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md`
§4).
| # | Module | Outcome | Activities | Real Ops connection |
|---|---|---|---|---|
| 1 | Why Version Control Exists | Explain what problem version control solves (history, collaboration, reproducibility, source of truth) | lesson, knowledge_check, reflection | Sets up "Git as source of truth" — the exact idea GitOps (ROOT 11) generalizes. |
| 2 | Git Mental Model | Explain working tree / staging area / repository / commit / branch / remote as a model, before commands | lesson, demonstration, knowledge_check, guided_exercise, reflection | Same "model before commands" pedagogy as ROOT 05's mental-model module. |
| 3 | Everyday Git | Use `status`/`add`/`commit`/`log`/`diff` to make and inspect real changes | lesson, demonstration, knowledge_check, guided_exercise, lab (`git-everyday-basics`), reflection | Every future IaC/GitOps workflow assumes this fluency as a given. |
| 4 | Branching | Create branches, switch between them, merge, resolve a simple conflict | lesson, demonstration, knowledge_check, guided_exercise, lab (`git-branching-and-merge`), reflection | Direct root of CI/CD's branch-triggered pipelines (future ROOT 11 content). |
| 5 | Remote Repositories | Clone/fetch/pull/push against a real local-bare remote; explain `origin` | lesson, demonstration, knowledge_check, guided_exercise, lab (`git-remote-clone-push`), reflection | Direct root of GitOps's "push triggers deployment" model. |
| 6 | Engineering Workflow | Write meaningful commits; explain why `main` is protected and why rollback via history matters | lesson, demonstration, knowledge_check, reflection | Explicit bridge to ROOT 11's "Git as source of truth for infrastructure" framing. |
Assessment: `rootnode-git-fundamentals-assessment`.
## ROOT 04 — Containers & Docker
Prerequisite: ROOT 03 complete. Uses the nested Docker Engine
(`docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md` §3) — the direct bridge into Kubernetes.
| # | Module | Outcome | Activities | Real Ops connection |
|---|---|---|---|---|
| 1 | Why Containers Exist | Explain the packaging/dependency-isolation/repeatability problem containers solve; contrast VM vs. container | lesson, demonstration, knowledge_check, reflection | Sets up "Kubernetes orchestrates what Docker already isolates" — Module 8's thesis. |
| 2 | Images & Containers | Explain image/layer/container/registry/tag as a model | lesson, demonstration, knowledge_check, guided_exercise, reflection | A Kubernetes Pod's `image:` field is this exact concept, unchanged. |
| 3 | Docker CLI | Pull/run/inspect/log/exec/stop/remove a real container | lesson, demonstration, knowledge_check, guided_exercise, lab (`docker-cli-basics`), reflection | `kubectl exec`/`kubectl logs` are the same actions against a different orchestrator. |
| 4 | Container Networking | Explain host-vs-container port, publish a port, reach one container from another | lesson, demonstration, knowledge_check, guided_exercise, lab (`docker-container-networking`), reflection | Direct root of Pod IPs/Services — builds explicitly on ROOT 02 M3/M4. |
| 5 | Container Storage | Explain ephemeral container filesystem vs. bind mounts vs. volumes | lesson, demonstration, knowledge_check, guided_exercise, lab (`docker-container-storage`), reflection | Direct root of Kubernetes PVC — builds explicitly on ROOT 02 M2. |
| 6 | Dockerfile & Image Build | Write a Dockerfile (`FROM`/`RUN`/`COPY`/`WORKDIR`/`CMD`) and build a real image | lesson, demonstration, knowledge_check, guided_exercise, lab (`docker-build-image`), reflection | Direct root of CI/CD's build step (future ROOT 11 content). |
| 7 | Docker Compose | Define and run a real multi-service app (two services, one network, one volume) | lesson, demonstration, knowledge_check, guided_exercise, lab (`docker-compose-multiservice`), reflection | Direct conceptual root of a Kubernetes multi-Pod application. |
| 8 | Containers → Kubernetes | Explain what Kubernetes adds on top of what Docker already does (scheduling, desired state, controllers, service discovery, health management, scaling, rollout) | lesson, knowledge_check, reflection | The explicit bridge module — a student should be able to answer "why Kubernetes" in their own words entering ROOT 05. |
Assessment: `rootnode-containers-assessment`.
## Assessments (Step 18)
Four new `assessment_definitions` rows, one per course, using the existing Phase 3B engine
exactly as `rootnode-security-assessment` (Phase 6C) does — mixing knowledge-recall scenarios
(`type: mcq`) with real state-validation scenarios (`type: task`, the same `runCommand`-backed
mechanism every lab already uses). No KubeKosh/Kubernetes scenario is force-fit into a
non-Kubernetes assessment. See `docs/PHASE6D_ROOT_FOUNDATIONS.md` for which are actually wired
this phase vs. deferred.
## Duration model
See `docs/ROOT_PROGRAM_DURATION_MODEL.md` for the derived instructional-hour estimate — computed
from actual `estimated_duration_minutes` values on real activities, not invented.
+117
View File
@@ -0,0 +1,117 @@
# ROOT Foundations Lab Strategy
Phase 6D §7/§10 — what the existing disposable Lab can safely teach for ROOT 01-04, evaluated
by actually reading `backend/server.js` and testing inside a real container, not assumed.
## 1. The scenario engine is already generic — no new activity type needed
`POST /api/scenarios/:id/setup` and `POST /api/scenarios/:id/validate` (`backend/server.js`)
run `setup_commands[].command` / `validation.commands[].command` through `runCommand()`, which
is a bare `child_process.exec(cmd)` — an arbitrary shell command string, checked against
`expected_output` by `checkMatch()` (exact/contains/not_contains/regex). **Nothing about this
is Kubernetes-specific.** Every existing scenario just happens to write `kubectl ...` as its
command string. `isolation_type` (`shared_namespace` etc.) is pure descriptive metadata — grepped
across the entire backend and frontend, it gates no actual behavior.
This means the existing `lab` activity type (`module_activities.activity_type = 'lab'`,
`completion_behavior = 'auto_scenario'`) and the existing `scenarios/data/*.json` format already
fully support Linux, networking-inspection, and Git exercises with real, deterministic
validation — a scenario file with `"command": "test -f /root/lab/notes.txt && echo exists"` is
exactly as valid as one with `"command": "kubectl get pod ..."`. **No `shell_lab`/`git_lab`/
`container_lab` activity type is built or needed.** The speculative multi-type model the
authorization raised as a possibility is unnecessary — it would duplicate a generic mechanism
that already exists.
The only wrinkle: `runCommand` does not pass a `cwd`, so every command runs wherever the backend
process's cwd is; multi-step Linux/Git scenarios must `cd /root/lab-<id> && ...` inside each
command string (exactly how a real student would chain commands), not rely on shell state
persisting between `setup` and `validate` calls beyond what the filesystem/git/process state
itself carries.
## 2. What the Lab image already contains (verified from the real `Dockerfile`)
Ubuntu 22.04 base with `curl wget git vim nano jq bash-completion iproute2 iptables
iputils-ping procps htop mount kmod python3 nginx` already installed, plus k3s (bundling
`kubectl`/`crictl`/containerd) started by `scripts/entrypoint.sh`. The student terminal execs
into this same container via node-pty — there is no separate "Linux sandbox," it's the same
shell k3s runs in.
**Already usable with zero image changes:** shell navigation, file manipulation (`cp`/`mv`/`rm`/
`cat`/`grep`/pipes/redirection), process inspection (`ps`/`top`/`kill`), permissions
(`chmod`/`chown`/`sudo` — the container runs as root, so a permission-teaching scenario should
`useradd` a second user in its `setup_commands` to demonstrate a real permission denial), and
network inspection (`ip addr`/`ip route`/`ss`/`ping`/`curl`).
**Missing, needed for ROOT 02 Module 5 (DNS & HTTP):** `dig`/`nslookup` are NOT installed
(`dnsutils`/`bind9-dnsutils` is absent from the current package list). This is a genuinely small,
justified Dockerfile addition (one more `apt-get install` package, same risk class as everything
else already there) — not a new mechanism. `curl` alone already covers the HTTP half.
## 3. Container runtime decision — tested, not assumed
**Decision: install real Docker Engine (`docker.io`) inside the same already-privileged Lab
container, alongside k3s, as a second independent container runtime with its own nested
`/var/run/docker.sock`.** Podman was not chosen — Docker Engine matches the actual ROOT 04
curriculum content (Docker CLI, Dockerfile, Compose terminology) and required no new privilege.
**Why this doesn't weaken the security boundary:** the student Lab container is already
launched with `Privileged: true` (`platform/provisioner/src/lifecycle.js` — required for k3s,
already the accepted threat model per `docs/LAB_ARCHITECTURE.md` §7: the Lab Host VM, not the
container boundary, is what actually contains a student). A second container runtime running
*inside* an already-fully-privileged guest adds no new host capability. **The Lab Host's own
Docker socket is never touched or exposed** — the nested `dockerd` started inside the guest
listens on its own `/var/run/docker.sock` *inside that guest's filesystem namespace*, entirely
separate from the Lab Host's real Docker daemon that the Provisioner itself talks to.
**Tested empirically** (not assumed) against the exact production resource caps
(`resource-policy.yaml`: 2 vCPU, 4096MB memory, 512 PIDs, `Privileged: true`): built
`rootnode-academy:test` fresh from the real `Dockerfile`, layered `docker.io` on top, launched
it under those exact `docker run` constraints, and ran real workloads inside:
| Step | Result | Memory | PIDs |
|---|---|---|---|
| k3s alone, ready | ✓ | 357MB | 36 |
| + `dockerd --storage-driver=vfs` started | ✓ | — | — |
| `docker run --rm hello-world` | ✓ passed | — | — |
| `docker run -d -p 8080:80 nginx:alpine`, `curl localhost:8080` | ✓ 200, real HTML returned | 866MB | 159 |
| `docker build` a real 2-line Dockerfile, `docker run` the result | ✓ passed | 884MB | 160 |
Comfortable headroom remained in all three dimensions (884MB/4096MB, 160/512 PIDs, CPU settled
after the image pull). `--storage-driver=vfs` was used deliberately — overlay2-on-overlay2
(the Lab Host's own overlay filesystem, nested inside another overlay driver) is a known source
of instability in Docker-in-Docker setups; vfs is slower per-layer but has no such nesting
hazard, and ROOT 04's exercises are small single-purpose images, not build-heavy CI workloads.
**`docker compose` is NOT included by `docker.io`** — Ubuntu's packaged Docker CLI does not ship
the Compose v2 plugin. Fixed the same way the Dockerfile already fetches k3s: download the
static `docker-compose` v2 binary directly (matching the existing "curl a static binary rather
than add a whole package repository" pattern already used for k3s) into
`/usr/local/lib/docker/cli-plugins/docker-compose` so `docker compose` works as a CLI subcommand.
**What was NOT done:** no change to the Provisioner, Lab Router, or Gateway. No change to
`HostConfig` (still `Privileged: true`, same CPU/memory/PIDs caps as every other Lab). No mount
of the Lab Host's `/var/run/docker.sock` into any container — verified this was never written
anywhere in this phase's changes.
## 4. Git strategy
`git` is already installed. All ROOT 03 exercises use **local repositories created inside the
student's own Lab** (`git init` in a scenario's `setup_commands`) — no Gitea account, no network
credentials, no dependency on RootNode's own canonical repository ever touching a student Lab.
A later module ("Remote Repositories") teaches `clone`/`fetch`/`pull`/`push`/`origin` conceptually
and against a **second local bare repository** created in the same Lab (`git init --bare`,
`git remote add origin /root/lab-remote.git`) to give students a genuine push/pull/clone
round-trip without needing any real network service, credential, or RootNode-adjacent
infrastructure — Step 9's explicit constraint.
## 5. Classification summary
| Capability | Classification |
|---|---|
| Shell/filesystem/process/permissions exercises | **SUPPORTED NOW** — zero image or code change |
| Network inspection (`ip`, `ss`, `ping`, `curl`) | **SUPPORTED NOW** |
| DNS tooling (`dig`/`nslookup`) | **REQUIRES SMALL PLATFORM EXTENSION** — one apt package added to the Lab Dockerfile |
| Git exercises (local + local-bare-remote) | **SUPPORTED NOW** — zero image or code change |
| Docker CLI / image build / single containers | **REQUIRES SMALL PLATFORM EXTENSION** — `docker.io` + entrypoint change to start `dockerd`, tested and proven safe/performant above |
| Docker Compose | **REQUIRES SMALL PLATFORM EXTENSION** — static `docker-compose` v2 binary, same pattern as k3s's own binary fetch |
| A distinct `shell_lab`/`git_lab`/`container_lab` activity type | **NOT NEEDED** — the existing generic `lab` + scenario-JSON model already covers all of the above |