LMS data model
LMS data model
Section titled “LMS data model”Audience: backend
Status: specced
Owns: backend
Depends on: LMS overview, API overview, Orchestrator data model, Coding standards
Design SoT: ecosystem-root lms-schema.prisma. This page is the human outline. Not yet migrated — CHECK constraints on String status fields must be hand-added to migration SQL (same convention as CAP).
Conventions
Section titled “Conventions”| Rule | Detail |
|---|---|
| ULID PKs | @id @db.Char(26), app-generated |
| Money | BigInt minor units on Course — never Float |
| JSONB | Onboarding data, item body / quiz, completion policy, sequencing, CMI snapshot |
| Enums | Structural only (LmsPersonaType, ItemType, EntitlementSource, StaffRole, …) |
| Status fields | String + intended CHECK |
| Cross-service ids | sectorId / tradeId / unitIds / paymentId / userId / assetId are strings, not FKs |
LmsUser — identity anti-corruption layer
Section titled “LmsUser — identity anti-corruption layer”| Pattern | Rule |
|---|---|
One table holds Orchestrator userId |
LmsUser.userId unique + indexed |
All other LMS tables FK to LmsUser.id |
Not to Orchestrator ids directly |
| Provisioning | Consume user.created idempotently (dedupe on userId); lazy-create on first authenticated LMS hit is allowed |
Core models
Section titled “Core models”| Model | Notes |
|---|---|
LmsUser |
Local id + OL userId |
OnboardingRecord |
Unique (lmsUserId, persona); JSONB data + schemaVersion |
LearnerProfile, InstructorProfile, StaffMembership |
Created on onboarding submit |
Invite |
Instructor or staff; email + status |
Course |
Price, status, optional CAP linkage, completionPolicy JSON, sequencing JSON |
CourseModule, CourseItem |
Item types include SCORM_PACKAGE (packageAssetId) |
CourseInstructor |
OWNER / CO_INSTRUCTOR |
Entitlement |
Source + status; optional sponsor / paymentId / capApplicationId |
Enrollment |
Unique (courseId, learnerLmsUserId); percentComplete |
ItemProgress |
Per item status + optional CMI JSON |
AssessmentAttempt |
Native quizzes only |
ScormRuntimeSession |
LMS launch path (extracted files), not Cloudinary URL |
LmsCertificate |
1:1 enrollment when issued; OL assetId |
OutboxEvent |
Transactional outbox |
Entitlement vs enrollment
Section titled “Entitlement vs enrollment”- Entitlement = why the learner may access.
- Enrollment = progress container.
- Player requires entitlement
ACTIVEand enrollmentACTIVE. Do not puthasPaidonCourseorLmsUser.
SCORM storage
Section titled “SCORM storage”Canonical zip bytes: Orchestrator StorageAsset (packageAssetId). Extracted player tree: LMS-local (ScormRuntimeSession.launchPath or equivalent object-store prefix). Future OL package adapter does not change LMS FKs — still an assetId.
See also
Section titled “See also”- LMS API · CAP data model (same ACL pattern)
- Payment architecture