# Runbook: Self-Paced Programs & Enrollment Covers managing programs and enrollments from `/admin` → Programs. See `docs/PHASE5B_SELF_PACED_ENROLLMENT.md` for the underlying design and `docs/WEBSITE_ENROLLMENT_INTEGRATION.md` for the separate website-driven path. **Create a program** (Programs → Create program, admin/owner only): Program ID is a slug (e.g. `root-linux-fundamentals`) and can't be changed later. Pick a family (`init_`/`compile_`/`root_`) and delivery mode. New programs default to `curriculum_path: rootnode-path` — the only curriculum content that exists today. A program for `init_`/`compile_` can be created now as a placeholder and wired to real content later without a schema change; it just won't have real lessons behind it yet. **Activate/deactivate a program** (Programs → \[program\] → Activate/Deactivate): An inactive program can't accept new enrollments (admin-manual or via the website integration endpoint) but existing enrollments in it are untouched — students already enrolled keep their access exactly as it was. **Manually enroll a student** (Programs → \[program\] → Enroll a student): Enter the student's ID (find it on the Students tab). Choose `pending` (the default — the student sees the enrollment but can't start until you Activate it) or `active` (skip that step). Optional start/end dates enforce access windows server-side — a future start date hides Lab access until then; an end date cuts off new Lab launches after it while leaving prior progress visible. As of Phase 5C, this also automatically emails the student — an activation link if they've never had credentials, or an enrollment confirmation if they already do. See `docs/RUNBOOK_STUDENT_ACTIVATION.md` for checking delivery status and resending. **Activate a pending enrollment** (Programs → \[program\] → Enrollments table → Activate): Only needed if you enrolled as `pending`. This is the moment a student actually gains entry. **Cancel an enrollment** (Programs → \[program\] → Enrollments table → Cancel, or Enrollments list on a student's own page): Immediately blocks new Lab launches. Does not touch the student's progress/achievements/attempt history — those are permanent regardless of enrollment status. Cancelling is final for that enrollment; if the student should have access again later, enroll them again (a new enrollment row) rather than trying to "reactivate" a cancelled one. **Check a student's enrollment history** (Students → \[student\] → "Enrolled programs" card): Shows every program the student has ever been enrolled in — pending, active, completed, cancelled, expired — with progress and last activity. A plain instructor sees this scoped to enrollments they created or that belong to a student sharing one of their cohorts; owner/admin see everything. **A student says "Continue Learning" isn't working / shows the wrong thing:** 1. Check their enrollment status on the Programs or Student page. `pending` → activate it. `expired`/`cancelled` → that's working as intended; enroll them again if they should continue. 2. If `active` and still stuck, check `/api/admin/students/:id/environment` for a stuck Lab — same troubleshooting as any other Lab issue (`docs/RUNBOOK_STUCK_LAB_CLEANUP.md`). Destroying the Lab never loses their program progress; a fresh launch resumes from the same place. **A student's completion didn't register:** Completion is detected the next time their program status is *read* (their dashboard, or an admin viewing their enrollment) after they finish the capstone — not pushed instantly. Refresh the page or reopen their student detail in `/admin`; if it still doesn't show `completed` after that, check `GET /api/achievements` for that student for a `capstone_completed` record matching the program's configured capstone — if that's missing, the capstone itself wasn't actually finished, not an enrollment bug.