Skip to main content

Public Schema

Purpose

The public schema mixes three kinds of tables:

  • platform-owned control-plane tables such as tenants and tenant_settings
  • tenant-scoped product tables such as users, staff, classes, and exams
  • operational support tables such as event_publication, shedlock, and idempotency_keys

This page is a reference document for the boundary between those families. It keeps the ERD focused on durable ownership and RLS semantics instead of trying to dump every table in the schema.

Source Paths

PathRole
lumie-backend/app/src/main/resources/db/migration/public/V1__create_platform_tables.sqltenants and tenant_settings
lumie-backend/app/src/main/resources/db/migration/public/V18__rls_baseline.sqlBaseline tenant-scoped domain tables and FK relations
lumie-backend/app/src/main/resources/db/migration/public/V26__rename_admin_tables_to_staff.sqlRenames admins to staff and admin_permissions to staff_permissions
lumie-backend/app/src/main/resources/db/migration/public/V13__create_event_publication.sqlSpring Modulith event publication table
lumie-backend/app/src/main/resources/db/migration/public/V14__create_shedlock.sqlScheduled job lock table
lumie-backend/app/src/main/resources/db/migration/public/V16__create_idempotency_keys.sqlIdempotency table
lumie-backend/libs/common/src/main/java/com/lumie/common/domain/TenantScopedEntity.javaJPA base class that supplies tenant-scoped rows with tenant_id

Boundary ERD

The diagram intentionally does not draw a hard tenants -> tenant table edge. The baseline migrations rely on tenant_id plus RLS for tenant ownership, not on a foreign key from every tenant-scoped table back to tenants(id).

Operational Support Tables

event_publication, shedlock, and idempotency_keys live in the same schema but are not part of the tenant-domain ERD:

  • event_publication stores Spring Modulith publication state and does not carry a tenant-domain relationship.
  • shedlock coordinates scheduled job locks.
  • idempotency_keys stores request replay protection keyed by tenant_slug, endpoint_path, and idempotency_key.

RLS Boundary

The runtime contract is that tenant-scoped access happens only after backend code establishes app.tenant_id. A missing tenant context should not silently fall back to cross-tenant data access.

The JPA base class that backs tenant-scoped entities keeps that contract visible in code:

@MappedSuperclass
public abstract class TenantScopedEntity extends BaseEntity {
@Column(name = "tenant_id", nullable = false, updatable = false)
private Long tenantId;
}

Verification

cd /path/to/Lumie
rg -n "CREATE TABLE (admins|users|students|classes|exams)|CREATE TABLE IF NOT EXISTS event_publication|CREATE TABLE IF NOT EXISTS shedlock|CREATE TABLE idempotency_keys" \
lumie-backend/app/src/main/resources/db/migration/public/V18__rls_baseline.sql \
lumie-backend/app/src/main/resources/db/migration/public/V13__create_event_publication.sql \
lumie-backend/app/src/main/resources/db/migration/public/V14__create_shedlock.sql \
lumie-backend/app/src/main/resources/db/migration/public/V16__create_idempotency_keys.sql

Expected success signal: hits for the baseline tenant tables plus separate hits for event_publication, shedlock, and idempotency_keys.

cd /path/to/Lumie
rg -n "ALTER TABLE admins RENAME TO staff|ALTER TABLE admin_permissions RENAME TO staff_permissions" \
lumie-backend/app/src/main/resources/db/migration/public/V26__rename_admin_tables_to_staff.sql

Expected success signal: both rename operations appear in V26, confirming the public-schema ERD should use staff and staff_permissions.

Notes

  • V18__rls_baseline.sql still contains the original admins and admin_permissions table names because V26 performs the rename later in the migration chain.
  • Newer join tables such as announcement and lecture targeting still follow the same boundary: tenant-scoped rows in public, guarded by RLS.