@startuml db-relationships
' Schema source: Flyway V1–V69 (excl. V37, V43 — intentionally removed)
' Schema as of:  V69 (2026-05-27)
' ⚠ This is a versioned snapshot. Update when the schema changes significantly.
' Note: V69 adds columns only (persons.source_ref, tag.source_ref, document
' precision/attribution fields); no new FK relationships, so this diagram is unchanged.

hide circle
skinparam linetype ortho

left to right direction

' ── Auth ──
package "Auth" {
  entity app_users
  entity user_groups
  entity app_users_groups
  entity group_permissions
  entity password_reset_tokens
  entity invite_tokens
  entity invite_token_group_ids
}

' ── Documents ──
package "Documents" {
  entity documents
  entity document_receivers
  entity document_tags
  entity document_versions
  entity document_annotations
  entity document_comments
  entity document_training_labels
  entity comment_mentions
}

' ── Persons ──
package "Persons" {
  entity persons
  entity person_name_aliases
  entity person_relationships
}

' ── Tags ──
package "Tags" {
  entity tag
}

' ── Transcription ──
package "Transcription" {
  entity transcription_blocks
  entity transcription_block_versions
  entity transcription_block_mentioned_persons
}

' ── OCR ──
package "OCR" {
  entity ocr_jobs
  entity ocr_job_documents
  entity ocr_training_runs
  entity sender_models
}

' ── Supporting ──
package "Supporting" {
  entity notifications
  entity audit_log
  entity geschichten
  entity geschichten_persons
  entity geschichten_documents
}

' Auth relationships
app_users_groups }o--|| app_users : app_user_id
app_users_groups }o--|| user_groups : group_id
group_permissions }o--|| user_groups : group_id
password_reset_tokens }o--|| app_users : app_user_id
invite_tokens }o--|| app_users : created_by
invite_token_group_ids }o--|| invite_tokens : invite_token_id
invite_token_group_ids }o--|| user_groups : group_id

' Document relationships
documents }o--o| persons : sender_id (ON DELETE SET NULL)
document_receivers }o--|| documents : document_id
document_receivers }o--|| persons : person_id (ON DELETE CASCADE)
document_tags }o--|| documents : document_id
document_tags }o--|| tag : tag_id
document_versions }o--|| documents : document_id
document_versions }o--o| app_users : editor_id
document_annotations }o--|| documents : document_id
document_annotations }o--o| app_users : created_by
document_comments }o--|| documents : document_id
document_comments }o--o| document_annotations : annotation_id
document_comments }o--o| transcription_blocks : block_id
document_comments }o--o| app_users : author_id
document_comments }o--o| document_comments : parent_id
document_training_labels }o--|| documents : document_id
comment_mentions }o--|| document_comments : comment_id
comment_mentions }o--|| app_users : app_user_id

' Person relationships
person_name_aliases }o--|| persons : person_id
person_relationships }o--|| persons : person_id
person_relationships }o--|| persons : related_person_id

' Tag self-reference
tag }o--o| tag : parent_id

' Transcription relationships
transcription_blocks }o--|| document_annotations : annotation_id
transcription_blocks }o--|| documents : document_id
transcription_blocks }o--o| app_users : created_by
transcription_blocks }o--o| app_users : updated_by
transcription_block_versions }o--|| transcription_blocks : block_id
transcription_block_versions }o--o| app_users : changed_by
transcription_block_mentioned_persons }o--|| transcription_blocks : block_id
transcription_block_mentioned_persons }o--|| persons : person_id (ON DELETE CASCADE)

' OCR relationships
ocr_job_documents }o--|| ocr_jobs : job_id
ocr_job_documents }o--|| documents : document_id
ocr_training_runs }o--o| app_users : triggered_by
ocr_training_runs }o--o| persons : person_id
sender_models ||--|| persons : person_id

' Supporting relationships
notifications }o--|| app_users : recipient_id
audit_log }o--o| app_users : actor_id
audit_log }o--o| documents : document_id
geschichten }o--o| app_users : author_id
geschichten_persons }o--|| geschichten : geschichte_id
geschichten_persons }o--|| persons : person_id
geschichten_documents }o--|| geschichten : geschichte_id
geschichten_documents }o--|| documents : document_id

@enduml
