Course Administration¶
Audience:
course_admin(per-course) andtenant_admin(tenant-wide) operators.Scope: Day-to-day admin tasks on a single course — roster management, analytics, course-admin assignments, audit visibility. Detailed RBAC and the impersonation contract live in
reference/user-management.mdanddevelopment/auth.md.
The LMS does not edit course content. Authoring lives in apps/cms. This guide covers the operational surfaces that ship today.
Roles¶
| Role | Scope |
|---|---|
course_admin |
Per-course; can view dashboard for assigned courses only (per course_admin_assignments). |
tenant_admin |
Full management within their own tenant — users, courses, enrolments, course-admin assignments. |
super_admin |
Global; can act across tenants via withTenantOverride(); can impersonate within a tenant. |
Course Dashboard¶
/admin/courses/\[slug\]/dashboard:
- Roster — enrolled learners with status (
active/completed/pending/cancelled). - Per-entry analytics — completion rate, average quiz score, attempt counts.
- Recent activity — last quiz attempts, completions.
Course admins see only their assigned courses. Tenant admins see all courses in their tenant. Super admins see across tenants when they explicitly use withTenantOverride().
Query shapes and caching live in reference/analytics.md.
Course-Admin Assignments¶
tenant_admin and super_admin manage assignments at /admin/courses/\[slug\]/admins:
- Search for a target user (must already exist in the tenant).
- Assign — writes a
course_admin_assignmentsrow. - The user is signed out everywhere on next request (token-version bump). On re-sign-in their JWT carries the new assignment.
To revoke, remove the row from the same surface. Revocation also bumps token_version so the JWT claim is refreshed.
Course admins themselves cannot assign other course admins — only tenant_admin and above can.
Roster Operations¶
From the course dashboard:
- View any learner's progress (entries completed, quiz attempts).
- Reset a quiz attempt only via a tenant-admin escalation; course admins file a request, tenant admins act.
- Send a password-reset email to a learner who is locked out (uses the consumed-token credentials path).
All mutating actions write audit_log rows.
Auditing¶
/admin/audit is tenant-scoped for tenant_admin and global for super_admin. Common filters:
- By actor (e.g. all impersonations triggered by a given super-admin).
- By action prefix (
auth.impersonate.*,enrollment.*,users.role_changed). - By target user or course slug.
course_admin does not have audit access in V1. Concerns about a specific learner action should be escalated to tenant_admin.
For super_admin support sessions, see Impersonation before filtering the related auth.impersonate.* events.
Common Workflows¶
Investigate an enrolment that "didn't take"¶
- Open
/admin/auditand filter byenrollment.*for the learner. - Verify the upsert ran and the row was scoped to the right tenant.
- Check the learner's session in
/admin/users/\[id\]. If theirtenant_iddiffers from the course tenant, they enrolled on the wrong subdomain.
Reset a learner's quiz progress (tenant_admin)¶
- Identify the entry slug and learner.
- Use the admin action on
/admin/courses/\[slug\]/dashboard(when present) or escalate to engineering. Direct DB edits must writeaudit_logentries withactor_user_id = <admin>.
Onboard a course admin¶
- Confirm the user has a tenant account.
- Promote to
course_adminvia/admin/users/\[id\]. - Assign the specific course at
/admin/courses/\[slug\]/admins. - Ask the user to refresh — their next request picks up the new claim.