Files
rootnode-academy/platform/api
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
..

RootNode Academy — Platform API (Phase 3B)

Lightweight service: no k3s, no --privileged, no Lab terminal runtime. See docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md for the original split/migration design, docs/PHASE3A_IDENTITY_AND_INSTRUCTOR_ACCESS.md for persistent sessions, per-instructor accounts, RBAC, and audit logging, and docs/PHASE3B_LEARNING_AND_ASSESSMENT.md for attempt telemetry, progressive hints, curriculum rules, and the exam/capstone engine — this file is the operational reference.

Configuration reference

Variable Required Meaning
PLATFORM_DB_URL no (defaults to local dev Postgres) Postgres connection string
PROVISIONER_URL no Provisioner base URL
PROVISIONER_SHARED_SECRET yes Internal Provisioner auth — process refuses to start without it
PLATFORM_API_PORT no Listen port, default 4300
FRONTEND_DIST_DIR no Where the built frontend lives — set by the Dockerfile, override for local non-Docker dev
SCENARIOS_DIR / BUNDLES_DIR / CURRICULUM_PATH_FILE no Override the default scenarios/ locations, mainly for local dev outside Docker
STUDENT_SESSION_TTL_HOURS / STUDENT_SESSION_IDLE_HOURS no Default 8h / 2h
INSTRUCTOR_SESSION_TTL_HOURS / INSTRUCTOR_SESSION_IDLE_HOURS no Default 12h / 2h
COOKIE_SECURE no Set to 1 once served over real HTTPS — adds Secure to every session/CSRF cookie
TRUST_PROXY no Set to 1 once fronted by a trusted reverse proxy — honors X-Forwarded-For for req.ip (audit source_ip, login rate limiting)

There is no ADMIN_PASSWORD anymore — instructor accounts live in Postgres (instructors table), created via bootstrap-owner.js for the first one and the admin portal after that.

Local dev

cd platform
echo "PROVISIONER_SHARED_SECRET=$(openssl rand -hex 32)" > .env
docker compose -f docker-compose.dev.yml build
docker compose -f docker-compose.dev.yml up -d

cd api
PLATFORM_DB_URL=postgres://postgres:postgres@localhost:5433/rootnode_platform \
  node bootstrap-owner.js [email protected] "Your Name" "a-real-password-12-chars-plus"

Everything is reachable through the Gateway at http://localhost:4200 — students at /, instructors at /admin (sign in with the bootstrapped owner). Platform API itself isn't meant to be hit directly by a browser (same boundary as the Provisioner relative to Platform API), though nothing stops you from curling it directly at :4300 for local debugging.

Owner bootstrap

node bootstrap-owner.js <email> <display_name> [password]

Prefer BOOTSTRAP_OWNER_PASSWORD over the positional argument outside a throwaway local test — CLI args can leak into shell history and ps. Refuses to run if an active owner already exists unless the target email belongs to an existing instructor (the intended recovery path if a platform is ever locked out with zero owners: point this at a known instructor account to promote them).

SQLite migration

One-time cutover, run against the real data volume:

docker run --rm -v <identity-data-volume>:/data \
  -e SQLITE_PATH=/data/progress.db -e PLATFORM_DB_URL=postgres://postgres:postgres@<host>:5433/rootnode_platform \
  <platform-api-image> node migrate-sqlite.js

Always backs up the SQLite file first, is safe to re-run, and writes a JSON report — see docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md §2/§3 for the full guarantees and rollback procedure. This step is about academic data (students/cohorts/progress) — it has nothing to do with instructor accounts, which are Phase 3A-native and start empty until you bootstrap one.

Tests

platform/test/e2e-phase2a.js (student-flow regression), platform/test/e2e-phase2b.js (the classroom acceptance workflow), platform/test/e2e-phase3a.js (persistent sessions including a real restart, instructor auth, RBAC, cohort scoping, CSRF, audit log), and platform/test/e2e-phase3b.js (attempt telemetry, progressive hints, curriculum/Capstone unlock rules, the exam engine including a real restart, two-student assessment isolation, instructor analytics). All four need the full stack up and OWNER_EMAIL / OWNER_PASSWORD set to a bootstrapped account — see platform/README.md.

Known limitations

See docs/PHASE3A_IDENTITY_AND_INSTRUCTOR_ACCESS.md "Known limitations" (sessions are Postgres-backed and survive a restart, but there's no distributed revocation channel to the Gateway's short-lived whoami cache; OIDC/SSO is a documented adapter interface, not a working integration yet) and docs/PHASE3B_LEARNING_AND_ASSESSMENT.md §20 (no automatic abandoned-attempt detection, needs-attention thresholds are fixed constants, pool_spec authoring is raw JSON in the admin UI).