Engineering handbook · PostgreSQL 18
Know the data.
Understand the relationships.
A browsable schema map and complete field reference, generated from migrations in an empty disposable database. No customer records are included.
Includes application, Goose and River tables. Keycloak’s internal identity database, OpenBao storage and object contents are outside this schema. A stored table does not establish a completed product feature. JSONB contracts and associations without foreign keys require the owning Go service and API documentation.
Explore the relationships
Choose a domain to keep the graph readable. Cross-domain tables appear as context. Key fields are shown here; every field and SQL definition is available below.
Catalogue & publishing
21 owned tables, with their outgoing foreign keys and immediate referenced tables.
How to read this diagram & source references
- Only declared foreign keys form relationships. Missing lines do not prove that no application-level relationship exists.
- PK/FK/UK mark participation in primary, foreign and unique constraints; composite keys apply to the whole column set. Full definitions are in the dictionary.
- Crow’s feet show zero-or-many; a circle with a bar shows zero-or-one. Nullable child keys permit an absent parent. Solid lines identify keys contained in the child primary key; dashed lines are non-identifying.
- Diagrams show key columns and a compact selection of fields. External tables are included for context; the dictionary contains every column.
Source references in the repository:
migrations/00009_drafts.sqlmigrations/00010_course_versions.sqlmigrations/00011_enrolments.sqlmigrations/00012_quarantine.sqlmigrations/00017_media_renditions.sqlmigrations/00020_refresher_schedule.sqlmigrations/00027_scorm_packages.sqlmigrations/00030_dispatch_destinations.sqlmigrations/00035_native_workspace.sqlmigrations/00043_course_bookmarks.sqlmigrations/00053_collections_pathways.sqlmigrations/00046_course_builder.sqlmigrations/00014_quiz_attempts.sqlmigrations/00045_experience.sqlmigrations/00049_learning_packages.sqlmigrations/00028_scorm_launch_registrations.sqlmigrations/00031_dispatch_registrations.sqlmigrations/00036_workspace_command_results.sqlmigrations/00054_people_directory.sql
The downloadable Mermaid file provides a text representation of every node and connection.
Data dictionary
Search table names, purposes or column names. Select a table to inspect its exact structure. Table links are shareable.
120 of 120 tables
Catalogue & publishing
courses
Mutable course drafts and authoring metadata.
| Column / keys | SQL type | Nullable | Default |
|---|---|---|---|
organisation_idPK · FK | uuid | No | — |
idPK | uuid | No | — |
title | text | No | — |
revision | bigint | No | 1 |
metadata | jsonb | No | '{}'::jsonb |
Relationships · 1 outgoing · 12 incoming
organisation_id → organisations (id)
Referenced by collection_courses: organisation_id + course_id
Referenced by course_bookmarks: organisation_id + course_id
Referenced by course_draft_assets: organisation_id + course_id
Referenced by course_draft_renditions: organisation_id + course_id
Referenced by course_versions: organisation_id + course_id
Referenced by dispatch_deployments: organisation_id + course_id
Referenced by enrolments: organisation_id + course_id
Referenced by modules: organisation_id + course_id
Referenced by pathway_course_links: organisation_id + course_id
Referenced by pathway_version_courses: organisation_id + course_id
Referenced by refresher_rules: organisation_id + course_id
Referenced by scorm_packages: organisation_id + course_id
Constraints & indexes
Composite uniqueness applies to the entire key. Partial indexes apply only when their predicate holds. NOT NULL appears in the column table above.
FOREIGN KEY (organisation_id) REFERENCES organisations(id)
PRIMARY KEY (organisation_id, id)
CHECK ((revision > 0))
CHECK (((title = btrim(title)) AND (title <> ''::text)))
CREATE UNIQUE INDEX courses_pkey ON public.courses USING btree (organisation_id, id)
Row security & triggers
ALL · PERMISSIVE · roles: public
USING (organisation_id = (NULLIF(current_setting('app.organisation_id'::text, true), ''::text))::uuid)
WITH CHECK (organisation_id = (NULLIF(current_setting('app.organisation_id'::text, true), ''::text))::uuid)No user-defined triggers.
Migration references
Files mentioning this table, including later alterations; these are provenance pointers, not a replacement for the migration ledger.
migrations/00009_drafts.sqlmigrations/00010_course_versions.sqlmigrations/00011_enrolments.sqlmigrations/00012_quarantine.sqlmigrations/00017_media_renditions.sqlmigrations/00020_refresher_schedule.sqlmigrations/00027_scorm_packages.sqlmigrations/00030_dispatch_destinations.sqlmigrations/00035_native_workspace.sqlmigrations/00043_course_bookmarks.sqlmigrations/00053_collections_pathways.sql
All domain ER diagrams
- Tenancy & company (SVG) · Mermaid
- Identity & access (SVG) · Mermaid
- Federation & provisioning (SVG) · Mermaid
- Catalogue & publishing (SVG) · Mermaid
- Learning & assessment (SVG) · Mermaid
- Evidence & reporting (SVG) · Mermaid
- Resources & AI (SVG) · Mermaid
- Messaging (SVG) · Mermaid
- Activity & analytics (SVG) · Mermaid
- Media (SVG) · Mermaid
- Learning packages (SVG) · Mermaid
- Hosted distribution (SVG) · Mermaid
- Integrations & extensions (SVG) · Mermaid
- Platform & recovery (SVG) · Mermaid
- River job engine (SVG) · Mermaid
Enums and views
river_job_state
available · cancelled · completed · discarded · pending · retryable · running · scheduled
0 SQL views in this schema snapshot.
Reading the model correctly
- Tenant boundary: many keys pair organisation_id with an entity ID. Follow the full composite foreign key. Row-security policy details show how tenant context is enforced.
- Stable learning: editable courses/modules/activities and immutable course_version_* snapshots have different lifecycles. Enrolments reference a published version.
- Packages: learning_packages and related tables back the integrated library/player. Older scorm_* tables and dispatch_* foundations remain separately documented; they do not imply SCORM 2004 or complete hosted distribution.
- Objects and jobs: PostgreSQL stores metadata and delivery state, not all file bytes. River coordinates jobs; queue tables are not tenant content APIs.
- Security metadata: hashes, encrypted fields and key references are schema attributes. This page contains no actual tokens, secrets, passwords or user records.
Reproduce and keep it current
From the repository root, run the schema exporter only with a local Docker engine. It creates and removes its own temporary PostgreSQL container, refuses remote Docker contexts and never accepts an existing database URL.
python3 scripts/docs/generate-schema.py npm run docs:diagrams --prefix web npm run docs:check --prefix web
The final command checks migration/dependency fingerprints and generated asset hashes without Docker. Regeneration needs the pinned Mermaid development dependency and a Playwright browser. See docs/technical-diagrams.md for the maintenance contract.