Skip to Content
ArchitectureData Model

Data Model

Core Principle

Courses are platform assets owned by GritCert. Tenants receive entitlements via the organization_courses join table. A student enrolled at two different tenants in the same course produces two distinct enrollment rows, two distinct certificates, and two distinct compliance records.

Tables

courses

Platform-owned course catalog. GritCert is the author-of-record for all content.

ColumnTypeNotes
idint PK
slugtexte.g. “cdl-basic”, “dot-hazmat”
titletext
verticalenumCDL, HAZMAT, EPA_608, OSHA_10, OSHA_30, FORKLIFT…
regulatory_moduletext49_CFR_172_704, 40_CFR_82…
base_price_centsint

course_versions

Published versions of each course. Enrollments pin to a specific version row.

ColumnTypeNotes
iduuid PK
course_idFK → courses
version_semvertexte.g. “1.0.0”
statusenumdraft, published, archived
published_attimestamptz
content_payloadjsonbversioned body

organizations

Every tenant. Each row is one tenant.

ColumnTypeNotes
idint PK
slugtexte.g. “freightpath”
nametextdisplay name
primary_hostnametext{slug}.gritcert.com
custom_domaintextnullable, unique
billing_contact_emailtextnullable
is_activebool

organization_courses (entitlement join)

Grants a tenant the right to offer a course. Holds per-tenant pricing overrides.

ColumnTypeNotes
iduuid PK
organization_idFK → organizations
course_idFK → courses
retail_price_centsintnullable — tenant sets retail
wholesale_price_centsintGritCert charges tenant
visibilityenumpublished, draft
expires_attimestamptznullable
UNIQUE(organization_id, course_id)

organization_memberships

User × tenant join. Authoritative membership record.

ColumnTypeNotes
iduuid PK
user_idFK → users
organization_idFK → organizations
roleenumstudent, admin, owner, support
is_primaryboolone per user
UNIQUE(user_id, organization_id)

course_enrollments

A student in a course at a tenant. Version-pinned.

ColumnTypeNotes
idint PK
user_idFK → users
organization_idFK → organizations
course_idFK → courses
course_version_idFK → course_versionspinned at enrollment
statusenumactive, completed…
UNIQUE(user_id, course_id, organization_id)

certificates

Issued per enrollment, branded per tenant.

ColumnTypeNotes
idint PK
user_idFK → users
course_idFK → courses
organization_idFK → organizationsNOT NULL
course_version_idFK → course_versionsNOT NULL
statusenumactive, expired, revoked
formatenumELDT_TPR, HM_126F, EPA_608
UNIQUE(user_id, course_id, organization_id, course_version_id)

platform_audit_log

Immutable log of every platform admin action. No delete policy.

ColumnTypeNotes
iduuid PK
organization_idFK → organizationsnullable
actor_user_idFK → usersplatform admin who acted
actiontext”admin_added”, “entitlement_granted”…
entity_typetext”organization”, “user”…
metadatajsonbbefore/after values
created_attimestamptzimmutable

Invariants

  • No tenant-specific course content in V1. Tenant overrides are pricing, visibility, and certificate header only.
  • All tenant-scoped queries enforce WHERE organization_id = req.user.organizationId.
  • Enrollments are version-pinned. New course versions never mutate in-flight enrollments.
  • BYPASS_AUTH stays false in every environment.
Last updated on
© 2026 GritCert. Internal platform documentation.