# Runbook: Student Account Lifecycle Covers creating, converting, resetting, and revoking student accounts. See `docs/PHASE5A_STUDENT_IDENTITY_REMOTE_CLASSROOM.md` for the underlying design. **Create a new credentialed student** (`/admin` → Students → Add student): Fill in display name plus **either** email (older/self-paced) or login ID (younger/instructor- managed) — leave both blank for a plain pilot account instead. Submitting shows an activation link **once**: `https:///?activate=`. Copy it immediately (print it, read it aloud, hand it over) — it is never shown again and never stored in plaintext anywhere. The student opens the link and sets their own password; the instructor never sees it. **Convert an existing pilot student to a real account** (Students → \[student\] → Convert): Same as creation, but for a student who already exists with progress/attempts/achievements — none of that is touched. Give an email or login ID, get a one-time activation link the same way. **Bulk import via CSV** (Students → Bulk import): Columns: `display_name, email, login_identifier, cohort_id` (only `display_name` is required per row). The whole file is validated before anything is written — one bad row rejects the entire file with a list of row errors, rather than importing some rows and skipping others. Never include a password column; it will always be rejected if present. Activation links for every created row are shown once after a successful import. **Reset a student's password** (Students → \[student\] → Reset password): Only for already-credentialed accounts. Issues a fresh reset link (`?reset=`, valid 1 hour) and immediately revokes every existing session for that student — the instructor still never sees or sets the actual password. **Revoke a student's sessions** (Students → \[student\] → Revoke all sessions): Immediately invalidates every active login for that student without touching their password. Use this if a device is lost/shared or a session looks compromised. **Deactivate a student** (Students → \[student\] → PATCH status: inactive, via the existing students list — deactivation takes effect on their very next request, not just their next login, because `studentSession` middleware re-checks `status='active'` every time. **If a student says their activation/reset link "doesn't work":** tokens are single-use and time-limited (activation 7 days, reset 1 hour). Just issue a new one via Convert or Reset password — there's no way to "resend" the same token, and that's intentional.