Skip to content

LMS lifecycle

Audience: all
Status: specced
Owns: product + backend
Depends on: Personas, Policies, API overview

flowchart LR
OL[OL register / login] --> Prov[lms_users]
Prov --> OB[Learner onboarding]
OB --> Cat[Catalogue browse]
Cat --> Enr[Enrollment pending or active]
Enr -->|priced| Pay[LMS checkout → OL pay]
Pay --> Act[Entitlement active]
Enr -->|grant / zero-price| Act
Act --> Learn[Player + assessments]
Learn --> Comp[Completion policy]
Comp --> Cert[LMS certificate]
Comp --> Evt[lms.course.completed]
Stage Gate
Account Orchestrator JWT; user.created with lms intent (or lazy provision)
Onboarding Learner draft → submit
Catalogue Authenticated; published courses only
Access Active entitlement (not merely an enrollment row)
Learn Sequencing locks (lms.sequencing.locked); progress %
Complete Completion policy (required items + min % + passed assessments)
Certificate LMS-owned; lms.certificate.issued
  1. Platform invite → email (notification.requested).
  2. OL login / register.
  3. Persona onboarding.
  4. Author (draft) → publish (owner/staff) → learners appear on assigned courses.
Status Meaning
pending Created; waiting for payment or grant
active Entitlement active; player unlocked
completed Completion policy satisfied
expired Entitlement validity ended
withdrawn Cancelled
Source How it activates
self_pay POST /enrollments/{id}/checkoutpayment.completed (zero-price skips OL)
admin_grant Staff POST /admin/entitlements
sponsor Staff grant — “someone paid”; optional sponsorUserId / note. No LMS orgs
cap_recommendation Staff/system grant tied to capApplicationId (CAP gRPC recs + this source)

Organizations later live on Orchestrator; organization_seat is not a v1 source.

LMS does not close CAP applications. It emits lms.course.completed (learnerUserId, courseId, optional capApplicationId, linkage ids). CAP decides whether GAP_TRAINING can clear.