Naming: snake_case tables, UUID primary keys, timestamptz for audit fields, soft-delete via deleted_at where needed.

auth_db (auth-service)

users
  id, email, phone, password_hash, full_name, is_active
  last_login_at, created_at, updated_at

roles
  id, code (SYSTEM_ADMIN, BURSAR, PARENT, ...), name

user_roles
  user_id, role_id, organization_id, campus_id (nullable)

parent_profiles
  user_id PK, organization_id, preferred_language

refresh_tokens
  id, user_id, token_hash, expires_at, revoked_at

org_db (organization-service)

organizations
  id, name, tin, logo_file_id, settings JSONB

campuses
  id, organization_id, name, code, address, phone

academic_years
  id, organization_id, label, start_date, end_date, is_current

terms
  id, academic_year_id, name (Term 1/2/3), start_date, end_date

classes
  id, campus_id, academic_year_id, name, level, stream, capacity

student_db (student-service)

students
  id, organization_id, campus_id, admission_number
  first_name, last_name, date_of_birth, gender
  photo_file_id, boarding_type (DAY|BOARDING)
  status (ACTIVE|GRADUATED|TRANSFERRED|WITHDRAWN)
  created_at, updated_at, deleted_at

guardians
  id, organization_id, user_id (auth), full_name, phone, email, relationship

student_guardians
  student_id, guardian_id, is_primary, can_pickup

enrollments
  id, student_id, class_id, academic_year_id, enrolled_at, status

requirement_templates
  id, campus_id, class_level, item_name, is_mandatory

student_requirements
  id, student_id, template_id, status (PENDING|SUBMITTED|VERIFIED), verified_by

fee_db (fee-service) — payment claims

fee_structures
  id, organization_id, campus_id, name, academic_year_id
  class_level, boarding_type, amount, term_id

fee_accounts
  id, student_id, organization_id, campus_id
  balance DECIMAL(14,2), credit_balance DECIMAL(14,2)

fee_invoices
  id, fee_account_id, student_id, term_id, invoice_number
  total_amount, amount_paid, status (OPEN|PARTIAL|PAID|VOID)
  due_date, issued_at

fee_invoice_lines
  id, invoice_id, description, amount

payment_claims                    -- Option B parent submissions
  id, organization_id, campus_id, student_id, guardian_id
  invoice_id, amount_claimed, amount_approved
  currency, payment_method, transaction_id, payer_phone
  agent_number, bank_name, payment_date, notes
  proof_file_id, status, duplicate_of_claim_id
  reviewed_by, reviewed_at, rejection_reason
  version, created_at, updated_at

payment_claim_status_history
  id, claim_id, from_status, to_status, actor_id, note, created_at

payments
  id, organization_id, campus_id, student_id, claim_id
  source (PARENT_CLAIM|BURSAR_DIRECT), amount, payment_method
  transaction_id, receipt_number, status, void_reason
  created_by, created_at

payment_allocations
  payment_id, invoice_id, amount_applied

defaulter_snapshots
  id, campus_id, term_id, student_id, amount_outstanding, as_of_date

Indexes: payment_claims(status, campus_id), payment_claims(transaction_id) partial unique, payments(receipt_number) unique, fee_invoices(student_id, status).

finance_db (finance-service)

chart_of_accounts
  id, organization_id, code, name, account_type

journal_entries
  id, organization_id, campus_id, entry_date, reference, source_event_id

journal_lines
  id, journal_entry_id, account_id, debit, credit, description

academic_db (academic-service)

grading_schemes
  id, organization_id, name (CBC_AE, LEGACY), config JSONB

subjects
  id, organization_id, code, name

mark_entries
  id, student_id, subject_id, term_id, score, grade, entered_by

report_cards
  id, student_id, term_id, file_id, published_at, status

homework_assignments
  id, class_id, subject_id, title, due_date, file_id, created_by

notice_db (notice-service)

notices
  id, campus_id, title, body, published_at, audience_type, audience_ref JSONB

distributed_documents
  id, campus_id, title, document_type, file_id
  audience_type, audience_ref JSONB, published_at

document_recipients
  document_id, guardian_id, student_id, downloaded_at

file_db (file-service)

files
  id, organization_id, bucket, object_key, mime_type, size_bytes
  uploaded_by, created_at, virus_scan_status

notification_db (notification-service)

notification_templates
  id, organization_id, code, channel, body_template

notification_log
  id, recipient, channel, template_code, payload JSONB
  provider_ref, status, sent_at, delivered_at

health_db (health-service)

student_health_records
  id, organization_id, campus_id, student_id, status, version
  allergies JSONB, chronic_conditions JSONB, medications JSONB
  blood_group, disability_notes, immunisation_notes
  family_doctor_name, family_doctor_phone, hospital_preference
  emergency_action_plan_file_id
  parent_confirmed_at, parent_confirmed_by, parent_declaration_text
  nurse_reviewed_at, nurse_reviewed_by
  created_at, updated_at

health_documents
  id, health_record_id, document_type, file_id
  uploaded_by, uploaded_at, expires_at

health_nurse_notes
  id, health_record_id, note, author_id, created_at

health_access_audit
  id, health_record_id, student_id, actor_id, action
  ip_address, created_at

health_record_status_history
  id, health_record_id, from_status, to_status, actor_id, note, created_at

Full spec: Student health records

attendance_db · inventory_db · report_db

See module specs for attendance_records, stock_items, uniform_issues, and materialized views in report_db.

Outbox pattern (all write services)

outbox_events
  id, aggregate_type, aggregate_id, event_type, payload JSONB
  created_at, published_at NULL

Poller publishes to RabbitMQ; consumers acknowledge idempotently via processed_events table.