# Database Schema > Generated from the Sequelize models (`backend/src/db/models/*`) — the source of truth. > Regenerate after schema changes. Last generated: 2026-06-09. ## Overview - **Engine:** PostgreSQL via **Sequelize 6** (models in `backend/src/db/models`, typed data access in `backend/src/db/api`). - **Models:** 38 tables. - **Primary keys:** every table has a `uuid` `id` (default `UUIDV4`). - **Soft delete:** all tables are `paranoid` — rows are flagged with `deletedAt` instead of being physically removed. - **Timestamps:** `createdAt` / `updatedAt` are managed automatically. - **Audit:** `createdById` / `updatedById` reference `users` (aliases `createdBy` / `updatedBy`). - **Multi-tenancy:** tenant-owned tables carry `organizationId` and are scoped to the current user's organization in `db/api` (see `full-integration-refactor-plan.md`, tenant boundary workstream). - **Import idempotency:** `importHash` (unique) deduplicates seeded/imported rows. ### Type notes Types below are the SQL column types. A few Sequelize types are returned as JS `string` at runtime to preserve precision: `DECIMAL`, `NUMERIC`, `BIGINT`, and `DATEONLY` (date-only). `DATE` maps to a JS `Date`. ## Domains - **Tenancy & Access:** `organizations`, `users`, `roles`, `permissions` - **Campuses & People:** `campuses`, `students`, `guardians`, `staff` - **Academics:** `academic_years`, `grades`, `subjects`, `classes`, `class_enrollments`, `class_subjects`, `timetables`, `timetable_periods`, `assessments`, `assessment_results` - **Attendance:** `attendance_sessions`, `attendance_records`, `campus_attendance_config`, `campus_attendance_summaries`, `staff_attendance_records` - **Finance / Billing:** `fee_plans`, `invoices`, `payments` - **Communication:** `messages`, `message_recipients`, `communication_events` - **Content & Product modules:** `content_catalog`, `documents`, `frame_entries`, `user_progress`, `safety_quiz_results`, `walkthrough_checkins`, `personality_quiz_results` - **System:** `file`, `auth_refresh_tokens` ## Relationship graph (foreign keys) Each edge is a `belongsTo` (the child holds the FK). `createdBy` / `updatedBy` edges to `users` are omitted for readability. ```mermaid erDiagram organizations ||--o{ academic_years : "organization" organizations ||--o{ assessment_results : "organization" assessments ||--o{ assessment_results : "assessment" students ||--o{ assessment_results : "student" organizations ||--o{ assessments : "organization" class_subjects ||--o{ assessments : "class_subject" organizations ||--o{ attendance_records : "organization" attendance_sessions ||--o{ attendance_records : "attendance_session" students ||--o{ attendance_records : "student" organizations ||--o{ attendance_sessions : "organization" campuses ||--o{ attendance_sessions : "campus" classes ||--o{ attendance_sessions : "class" class_subjects ||--o{ attendance_sessions : "class_subject" staff ||--o{ attendance_sessions : "taken_by" users ||--o{ auth_refresh_tokens : "user" organizations ||--o{ auth_refresh_tokens : "organization" organizations ||--o{ campus_attendance_config : "organization" campuses ||--o{ campus_attendance_config : "campus" organizations ||--o{ campus_attendance_summaries : "organization" campuses ||--o{ campus_attendance_summaries : "campus" organizations ||--o{ campuses : "organization" organizations ||--o{ class_enrollments : "organization" classes ||--o{ class_enrollments : "class" students ||--o{ class_enrollments : "student" organizations ||--o{ class_subjects : "organization" classes ||--o{ class_subjects : "class" subjects ||--o{ class_subjects : "subject" staff ||--o{ class_subjects : "teacher" organizations ||--o{ classes : "organization" campuses ||--o{ classes : "campus" academic_years ||--o{ classes : "academic_year" grades ||--o{ classes : "grade" staff ||--o{ classes : "homeroom_teacher" organizations ||--o{ communication_events : "organization" campuses ||--o{ communication_events : "campus" organizations ||--o{ documents : "organization" campuses ||--o{ documents : "campus" organizations ||--o{ fee_plans : "organization" academic_years ||--o{ fee_plans : "academic_year" grades ||--o{ fee_plans : "grade" organizations ||--o{ frame_entries : "organization" campuses ||--o{ frame_entries : "campus" organizations ||--o{ grades : "organization" organizations ||--o{ guardians : "organization" students ||--o{ guardians : "student" organizations ||--o{ invoices : "organization" campuses ||--o{ invoices : "campus" students ||--o{ invoices : "student" fee_plans ||--o{ invoices : "fee_plan" organizations ||--o{ message_recipients : "organization" messages ||--o{ message_recipients : "message" organizations ||--o{ messages : "organization" campuses ||--o{ messages : "campus" users ||--o{ messages : "sent_by" organizations ||--o{ payments : "organization" invoices ||--o{ payments : "invoice" staff ||--o{ payments : "received_by" organizations ||--o{ personality_quiz_results : "organization" campuses ||--o{ personality_quiz_results : "campus" users ||--o{ personality_quiz_results : "user" organizations ||--o{ safety_quiz_results : "organization" campuses ||--o{ safety_quiz_results : "campus" users ||--o{ safety_quiz_results : "user" organizations ||--o{ staff : "organization" campuses ||--o{ staff : "campus" users ||--o{ staff : "user" organizations ||--o{ staff_attendance_records : "organization" campuses ||--o{ staff_attendance_records : "campus" users ||--o{ staff_attendance_records : "user" organizations ||--o{ students : "organization" campuses ||--o{ students : "campus" organizations ||--o{ subjects : "organization" organizations ||--o{ timetable_periods : "organization" timetables ||--o{ timetable_periods : "timetable" class_subjects ||--o{ timetable_periods : "class_subject" organizations ||--o{ timetables : "organization" campuses ||--o{ timetables : "campus" academic_years ||--o{ timetables : "academic_year" organizations ||--o{ user_progress : "organization" campuses ||--o{ user_progress : "campus" users ||--o{ user_progress : "user" roles ||--o{ users : "app_role" organizations ||--o{ users : "organizations" organizations ||--o{ walkthrough_checkins : "organization" campuses ||--o{ walkthrough_checkins : "campus" ``` ## Table reference ### Tenancy & Access #### `organizations` Tenant root. Every tenant-owned row references an organization via `organizationId`. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `users` as `users_organizations` (FK `organizationId`) - **has many** `campuses` as `campuses_organization` (FK `organizationId`) - **has many** `academic_years` as `academic_years_organization` (FK `organizationId`) - **has many** `grades` as `grades_organization` (FK `organizationId`) - **has many** `subjects` as `subjects_organization` (FK `organizationId`) - **has many** `students` as `students_organization` (FK `organizationId`) - **has many** `guardians` as `guardians_organization` (FK `organizationId`) - **has many** `staff` as `staff_organization` (FK `organizationId`) - **has many** `classes` as `classes_organization` (FK `organizationId`) - **has many** `class_enrollments` as `class_enrollments_organization` (FK `organizationId`) - **has many** `class_subjects` as `class_subjects_organization` (FK `organizationId`) - **has many** `timetables` as `timetables_organization` (FK `organizationId`) - **has many** `timetable_periods` as `timetable_periods_organization` (FK `organizationId`) - **has many** `attendance_sessions` as `attendance_sessions_organization` (FK `organizationId`) - **has many** `attendance_records` as `attendance_records_organization` (FK `organizationId`) - **has many** `fee_plans` as `fee_plans_organization` (FK `organizationId`) - **has many** `invoices` as `invoices_organization` (FK `organizationId`) - **has many** `payments` as `payments_organization` (FK `organizationId`) - **has many** `assessments` as `assessments_organization` (FK `organizationId`) - **has many** `assessment_results` as `assessment_results_organization` (FK `organizationId`) - **has many** `messages` as `messages_organization` (FK `organizationId`) - **has many** `message_recipients` as `message_recipients_organization` (FK `organizationId`) - **has many** `documents` as `documents_organization` (FK `organizationId`) #### `users` Authentication identities. `email` is required (login + primary contact). Belongs to one organization (`organizationId`, alias `organizations`), one `app_role`, and may hold direct `custom_permissions`. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `firstName` | text | yes | — | | | `lastName` | text | yes | — | | | `phoneNumber` | text | yes | — | | | `email` | text | no | — | | | `disabled` | boolean | no | false | | | `password` | text | yes | — | | | `emailVerified` | boolean | no | false | | | `emailVerificationToken` | text | yes | — | | | `emailVerificationTokenExpiresAt` | timestamptz | yes | — | | | `passwordResetToken` | text | yes | — | | | `passwordResetTokenExpiresAt` | timestamptz | yes | — | | | `provider` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `app_roleId` | uuid | yes | — | FK | _Relations:_ - **many-to-many with** `permissions` as `custom_permissions` (FK `users_custom_permissionsId`) - **many-to-many with** `permissions` as `custom_permissions_filter` (FK `users_custom_permissionsId`) - **has many** `staff` as `staff_user` (FK `userId`) - **has many** `messages` as `messages_sent_by` (FK `sent_byId`) - **belongs to** `roles` as `app_role` (FK `app_roleId`) - **belongs to** `organizations` as `organizations` (FK `organizationId`) - **has many** `file` as `avatar` (FK `belongsToId`) #### `roles` Named permission sets (RBAC). Linked to permissions M:N; `globalAccess` grants cross-tenant access. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `globalAccess` | boolean | no | false | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **many-to-many with** `permissions` as `permissions` (FK `roles_permissionsId`) - **many-to-many with** `permissions` as `permissions_filter` (FK `roles_permissionsId`) - **has many** `users` as `users_app_role` (FK `app_roleId`) #### `permissions` Flat permission catalog. Permission names follow `${METHOD}_${ENTITY}` (e.g. `READ_CAMPUSES`). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | ### Campuses & People #### `campuses` A physical or online campus belonging to one organization. Parent of students, staff, classes, etc. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `code` | text | yes | — | | | `address` | text | yes | — | | | `phone` | text | yes | — | | | `email` | text | yes | — | | | `mascot` | text | yes | — | | | `color` | text | yes | — | | | `bgGradient` | text | yes | — | | | `borderColor` | text | yes | — | | | `textColor` | text | yes | — | | | `bgLight` | text | yes | — | | | `description` | text | yes | — | | | `isOnline` | boolean | no | false | | | `active` | boolean | no | false | | | `importHash` | varchar | yes | — | unique, audit | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | _Relations:_ - **has many** `students` as `students_campus` (FK `campusId`) - **has many** `staff` as `staff_campus` (FK `campusId`) - **has many** `classes` as `classes_campus` (FK `campusId`) - **has many** `timetables` as `timetables_campus` (FK `campusId`) - **has many** `attendance_sessions` as `attendance_sessions_campus` (FK `campusId`) - **has many** `invoices` as `invoices_campus` (FK `campusId`) - **has many** `messages` as `messages_campus` (FK `campusId`) - **has many** `documents` as `documents_campus` (FK `campusId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) #### `students` Enrolled students. Belong to a campus and organization; have guardians, enrollments, attendance, results, invoices. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `student_number` | text | yes | — | | | `first_name` | text | yes | — | | | `last_name` | text | yes | — | | | `gender` | enum | yes | — | | | `date_of_birth` | timestamptz | yes | — | | | `enrollment_date` | timestamptz | yes | — | | | `status` | enum | yes | — | | | `email` | text | yes | — | | | `phone` | text | yes | — | | | `address` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `campusId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `guardians` as `guardians_student` (FK `studentId`) - **has many** `class_enrollments` as `class_enrollments_student` (FK `studentId`) - **has many** `attendance_records` as `attendance_records_student` (FK `studentId`) - **has many** `invoices` as `invoices_student` (FK `studentId`) - **has many** `assessment_results` as `assessment_results_student` (FK `studentId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **has many** `file` as `photo` (FK `belongsToId`) #### `guardians` Guardians/contacts linked to a student. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `full_name` | text | yes | — | | | `relationship` | enum | yes | — | | | `phone` | text | yes | — | | | `email` | text | yes | — | | | `address` | text | yes | — | | | `primary_contact` | boolean | no | false | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `studentId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `students` as `student` (FK `studentId`) #### `staff` Staff members, optionally linked to a `user` account; can be homeroom teacher, subject teacher, attendance taker, payment receiver. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `employee_number` | text | yes | — | | | `job_title` | text | yes | — | | | `staff_type` | enum | yes | — | | | `hire_date` | timestamptz | yes | — | | | `status` | enum | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `campusId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `userId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `classes` as `classes_homeroom_teacher` (FK `homeroom_teacherId`) - **has many** `class_subjects` as `class_subjects_teacher` (FK `teacherId`) - **has many** `attendance_sessions` as `attendance_sessions_taken_by` (FK `taken_byId`) - **has many** `payments` as `payments_received_by` (FK `received_byId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `users` as `user` (FK `userId`) - **has many** `file` as `photo` (FK `belongsToId`) ### Academics #### `academic_years` School years (with `current` flag and effective dates) scoping classes, timetables, fee plans. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `start_date` | timestamptz | yes | — | | | `end_date` | timestamptz | yes | — | | | `current` | boolean | no | false | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `classes` as `classes_academic_year` (FK `academic_yearId`) - **has many** `timetables` as `timetables_academic_year` (FK `academic_yearId`) - **has many** `fee_plans` as `fee_plans_academic_year` (FK `academic_yearId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) #### `grades` Grade levels (with `sort_order`). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `code` | text | yes | — | | | `sort_order` | integer | yes | — | | | `description` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `classes` as `classes_grade` (FK `gradeId`) - **has many** `fee_plans` as `fee_plans_grade` (FK `gradeId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) #### `subjects` Academic subjects (Math, English, …). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `code` | text | yes | — | | | `description` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `class_subjects` as `class_subjects_subject` (FK `subjectId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) #### `classes` Class/group: belongs to campus, academic year, grade, and a homeroom teacher. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `section` | text | yes | — | | | `capacity` | integer | yes | — | | | `status` | enum | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `academic_yearId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `gradeId` | uuid | yes | — | FK | | `homeroom_teacherId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `class_enrollments` as `class_enrollments_class` (FK `classId`) - **has many** `class_subjects` as `class_subjects_class` (FK `classId`) - **has many** `attendance_sessions` as `attendance_sessions_class` (FK `classId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `academic_years` as `academic_year` (FK `academic_yearId`) - **belongs to** `grades` as `grade` (FK `gradeId`) - **belongs to** `staff` as `homeroom_teacher` (FK `homeroom_teacherId`) #### `class_enrollments` Join of student ↔ class with enrolment dates and status. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `enrolled_on` | timestamptz | yes | — | | | `ended_on` | timestamptz | yes | — | | | `status` | enum | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `classId` | uuid | yes | — | FK | | `studentId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `classes` as `class` (FK `classId`) - **belongs to** `students` as `student` (FK `studentId`) #### `class_subjects` Join of class ↔ subject ↔ teacher; the unit that schedule, attendance, and assessments hang off. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `status` | enum | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `classId` | uuid | yes | — | FK | | `subjectId` | uuid | yes | — | FK | | `teacherId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `timetable_periods` as `timetable_periods_class_subject` (FK `class_subjectId`) - **has many** `attendance_sessions` as `attendance_sessions_class_subject` (FK `class_subjectId`) - **has many** `assessments` as `assessments_class_subject` (FK `class_subjectId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `classes` as `class` (FK `classId`) - **belongs to** `subjects` as `subject` (FK `subjectId`) - **belongs to** `staff` as `teacher` (FK `teacherId`) #### `timetables` A timetable for a campus + academic year, with effective dates. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `effective_from` | timestamptz | yes | — | | | `effective_to` | timestamptz | yes | — | | | `status` | enum | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `academic_yearId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `timetable_periods` as `timetable_periods_timetable` (FK `timetableId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `academic_years` as `academic_year` (FK `academic_yearId`) #### `timetable_periods` A single period (day/time/room) linking a timetable to a class_subject. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `day_of_week` | enum | yes | — | | | `starts_at` | timestamptz | yes | — | | | `ends_at` | timestamptz | yes | — | | | `room` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `class_subjectId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `timetableId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `timetables` as `timetable` (FK `timetableId`) - **belongs to** `class_subjects` as `class_subject` (FK `class_subjectId`) #### `assessments` Assessments for a class_subject (type, dates, max score, attachments). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `assessment_type` | enum | yes | — | | | `assigned_at` | timestamptz | yes | — | | | `due_at` | timestamptz | yes | — | | | `max_score` | decimal | yes | — | | | `status` | enum | yes | — | | | `instructions` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `class_subjectId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `assessment_results` as `assessment_results_assessment` (FK `assessmentId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `class_subjects` as `class_subject` (FK `class_subjectId`) - **has many** `file` as `attachments` (FK `belongsToId`) #### `assessment_results` A student's result for an assessment (score, grade_letter). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `score` | decimal | yes | — | | | `grade_letter` | enum | yes | — | | | `remarks` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `assessmentId` | uuid | yes | — | FK | | `studentId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `assessments` as `assessment` (FK `assessmentId`) - **belongs to** `students` as `student` (FK `studentId`) ### Attendance #### `attendance_sessions` An attendance session for a class/class_subject taken by a staff member. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `session_date` | timestamptz | yes | — | | | `session_type` | enum | yes | — | | | `notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `classId` | uuid | yes | — | FK | | `class_subjectId` | uuid | yes | — | FK | | `taken_byId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `attendance_records` as `attendance_records_attendance_session` (FK `attendance_sessionId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `classes` as `class` (FK `classId`) - **belongs to** `class_subjects` as `class_subject` (FK `class_subjectId`) - **belongs to** `staff` as `taken_by` (FK `taken_byId`) #### `attendance_records` Per-student attendance within a session (status, minutes_late). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `status` | enum | yes | — | | | `minutes_late` | integer | yes | — | | | `remarks` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `attendance_sessionId` | uuid | yes | — | FK | | `studentId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `attendance_sessions` as `attendance_session` (FK `attendance_sessionId`) - **belongs to** `students` as `student` (FK `studentId`) #### `campus_attendance_config` Product-module config for campus attendance. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `campus_key` | text | no | — | | | `attendance_link` | text | yes | — | | | `updated_by_label` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) #### `campus_attendance_summaries` Product-module aggregated campus attendance. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `campus_key` | text | no | — | | | `attendance_date` | date | no | — | | | `total_enrolled` | integer | no | — | | | `total_present` | integer | no | — | | | `total_absent` | integer | no | — | | | `total_tardy` | integer | no | 0 | | | `attendance_percentage` | decimal | no | — | | | `recorded_by_label` | text | yes | — | | | `notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) #### `staff_attendance_records` Staff attendance records (present/late/absent). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `attendance_date` | date | no | — | | | `status` | enum | no | — | | | `note` | text | yes | — | | | `user_name` | text | no | — | | | `user_role` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `userId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `users` as `user` (FK `userId`) ### Finance / Billing #### `fee_plans` Fee/tuition plans (billing cycle, total amount) for a grade in an academic year. Invoices are generated from these. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `name` | text | yes | — | | | `billing_cycle` | enum | yes | — | | | `total_amount` | decimal | yes | — | | | `active` | boolean | no | false | | | `notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `academic_yearId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `gradeId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `invoices` as `invoices_fee_plan` (FK `fee_planId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `academic_years` as `academic_year` (FK `academic_yearId`) - **belongs to** `grades` as `grade` (FK `gradeId`) #### `invoices` Invoices issued to a student (amounts, status) — optionally from a fee_plan. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `invoice_number` | text | yes | — | | | `issue_date` | timestamptz | yes | — | | | `due_date` | timestamptz | yes | — | | | `subtotal` | decimal | yes | — | | | `discount_amount` | decimal | yes | — | | | `tax_amount` | decimal | yes | — | | | `total_amount` | decimal | yes | — | | | `balance_due` | decimal | yes | — | | | `status` | enum | yes | — | | | `notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `campusId` | uuid | yes | — | FK | | `fee_planId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `studentId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `payments` as `payments_invoice` (FK `invoiceId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `students` as `student` (FK `studentId`) - **belongs to** `fee_plans` as `fee_plan` (FK `fee_planId`) - **has many** `file` as `attachments` (FK `belongsToId`) #### `payments` Payments against an invoice (amount, method, proof file). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `receipt_number` | text | yes | — | | | `paid_at` | timestamptz | yes | — | | | `amount` | decimal | yes | — | | | `method` | enum | yes | — | | | `reference_code` | text | yes | — | | | `notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `invoiceId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `received_byId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `invoices` as `invoice` (FK `invoiceId`) - **belongs to** `staff` as `received_by` (FK `received_byId`) - **has many** `file` as `proof` (FK `belongsToId`) ### Communication #### `messages` In-app announcements/messages (subject/body/channel/audience) with attachments and recipients. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `subject` | text | yes | — | | | `body` | text | yes | — | | | `channel` | enum | yes | — | | | `audience` | enum | yes | — | | | `sent_at` | timestamptz | yes | — | | | `status` | enum | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `campusId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `sent_byId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **has many** `message_recipients` as `message_recipients_message` (FK `messageId`) - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `users` as `sent_by` (FK `sent_byId`) - **has many** `file` as `attachments` (FK `belongsToId`) #### `message_recipients` Per-recipient delivery/read tracking for a message (in-app). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `recipient_type` | enum | yes | — | | | `recipient_label` | text | yes | — | | | `destination` | text | yes | — | | | `delivery_status` | enum | yes | — | | | `delivered_at` | timestamptz | yes | — | | | `read_at` | timestamptz | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `messageId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `messages` as `message` (FK `messageId`) #### `communication_events` Product-module communication events (meetings, drills, events, deadlines). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `title` | text | no | — | | | `event_date` | date | no | — | | | `event_type` | text | no | — | | | `roles` | jsonb | no | Array | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) ### Content & Product modules #### `content_catalog` Product content catalog. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `content_type` | text | no | — | unique | | `payload` | jsonb | no | — | | | `active` | boolean | no | true | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | #### `documents` Polymorphic document records with a `file` attachment, scoped to organization/campus. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `entity_type` | enum | yes | — | | | `entity_reference` | text | yes | — | | | `name` | text | yes | — | | | `category` | enum | yes | — | | | `uploaded_at` | timestamptz | yes | — | | | `notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `campusId` | uuid | yes | — | FK | | `organizationId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **has many** `file` as `file` (FK `belongsToId`) #### `frame_entries` Product-module "frame" entries. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `week_of` | text | no | — | | | `posted_date` | text | no | — | | | `formal` | text | no | — | | | `recognition` | text | no | — | | | `application` | text | no | — | | | `management` | text | no | — | | | `emotional` | text | no | — | | | `author` | text | no | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) #### `user_progress` Per-user progress (sign learning, zone check-ins). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `progress_type` | text | no | — | | | `item_id` | text | no | — | | | `value` | text | yes | — | | | `score` | integer | yes | — | | | `metadata` | jsonb | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `userId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `users` as `user` (FK `userId`) #### `safety_quiz_results` Product-module safety quiz results. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `quiz_id` | text | no | — | | | `quiz_title` | text | no | — | | | `week_of` | text | no | — | | | `score` | integer | no | — | | | `total_questions` | integer | no | — | | | `answers` | jsonb | no | — | | | `user_name` | text | no | — | | | `user_role` | text | no | — | | | `completed_at` | timestamptz | no | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `userId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `users` as `user` (FK `userId`) #### `walkthrough_checkins` Product-module walkthrough check-ins. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `teacher_name` | text | no | — | | | `classroom` | text | no | — | | | `director_name` | text | no | — | | | `check_in_date` | date | no | — | | | `check_in_time` | time | no | — | | | `attitude_rating` | integer | no | — | | | `attitude_comment` | text | yes | — | | | `classroom_management_rating` | integer | no | — | | | `classroom_management_comment` | text | yes | — | | | `cleanliness_rating` | integer | no | — | | | `cleanliness_comment` | text | yes | — | | | `vibes_rating` | integer | no | — | | | `vibes_comment` | text | yes | — | | | `team_dynamics_rating` | integer | no | — | | | `team_dynamics_comment` | text | yes | — | | | `emergency_exit_rating` | integer | no | — | | | `emergency_exit_comment` | text | yes | — | | | `lesson_plan_rating` | integer | no | — | | | `lesson_plan_comment` | text | yes | — | | | `overall_notes` | text | yes | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) #### `personality_quiz_results` Product-module personality quiz results. | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `personality_type` | text | no | — | | | `quiz_answers` | jsonb | no | — | | | `completed_at` | timestamptz | no | — | | | `importHash` | varchar | yes | — | unique, audit | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `organizationId` | uuid | yes | — | FK | | `campusId` | uuid | yes | — | FK | | `userId` | uuid | yes | — | FK | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | _Relations:_ - **belongs to** `organizations` as `organization` (FK `organizationId`) - **belongs to** `campuses` as `campus` (FK `campusId`) - **belongs to** `users` as `user` (FK `userId`) ### System #### `file` Polymorphic file/attachment store (`belongsTo` + `belongsToColumn` + `belongsToId`). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `belongsTo` | varchar | yes | — | | | `belongsToId` | uuid | yes | — | FK | | `belongsToColumn` | varchar | yes | — | | | `name` | varchar | no | — | | | `sizeInBytes` | integer | yes | — | | | `privateUrl` | varchar | yes | — | | | `publicUrl` | varchar | no | — | | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | | `deletedAt` | timestamptz | yes | — | audit | | `createdById` | uuid | yes | — | FK, audit | | `updatedById` | uuid | yes | — | FK, audit | #### `auth_refresh_tokens` Refresh-token rotation records for cookie-based auth (hash, family, expiry, revocation). | Column | Type | Null | Default | Notes | |---|---|---|---|---| | `id` | uuid | no | UUIDV4 | PK | | `userId` | uuid | no | — | FK | | `organizationId` | uuid | yes | — | FK | | `tokenHash` | text | no | — | unique | | `familyId` | uuid | no | — | FK | | `previousTokenId` | uuid | yes | — | FK | | `userAgent` | text | yes | — | | | `ipAddress` | text | yes | — | | | `expiresAt` | timestamptz | no | — | | | `revokedAt` | timestamptz | yes | — | | | `replacedByTokenId` | uuid | yes | — | FK | | `createdAt` | timestamptz | yes | — | audit | | `updatedAt` | timestamptz | yes | — | audit | _Relations:_ - **belongs to** `users` as `user` (FK `userId`) - **belongs to** `organizations` as `organization` (FK `organizationId`)