4.2 KiB
Document Data Model
This note describes the core persistence model for documents: the metadata held in
documents, how versions are tracked, and the way auxiliary assets are stored.
documents
Each row represents the logical document a user interacts with in the UI. Key fields:
id (uuid)– Stable identifier used in API paths.tenant_id (uuid)– Multi-tenancy boundary; all joins filter by this.title (varchar)– Display name editable via PATCH.filename / original_name (varchar)– Current storage filename vs. the name captured during upload.folder_id (uuid, nullable)– Parent folder,NULLmeans root.metadata (jsonb)– Arbitrary structured metadata (source import details, custom fields, etc.).issued_at (timestamptz, nullable)– User-provided timestamp for when the document was issued (invoice date, etc.).current_version_id (uuid)– FK pointing at the activedocument_versionsrow; updated whenever a new version is promoted.deleted_at (timestamptz, nullable)– Soft-delete marker; non-NULL rows are treated as living in the trash.created_at / updated_at (timestamptz)– Audit stamps;updated_atreflects metadata or version changes.
Other indexes enforce per-tenant uniqueness for (folder, filename) and support
common queries (folder listing, trash filtering).
document_versions
Every binary revision lives here. Fields of interest:
document_id (uuid)– Back-reference to the logical document.version_number (int)– Monotonic per document (1, 2, …); enforced viaUNIQUE(document_id, version_number).s3_key (varchar)– Object storage path for the binary (used for download).size_bytes,checksum– Stored metadata about the binary; checksum is a hex-encoded SHA-256 hash used for dedupe/conflicts.metadata (jsonb)– Small metadata blob specific to the version (extracted text summary, processing hints, etc.).tenant_id (uuid)– Mirrors the owning document’s tenant.
The row referenced by documents.current_version_id is treated as the latest
revision. Older versions remain queryable for download or audit.
Assets
A document version can have zero or more derived artifacts (thumbnails, OCR output, previews). These are modelled via:
-
document_assetsdocument_version_id– FK to the owning version.asset_type (text)– Logical type identifier (e.g.thumbnail,ocr_text).mime_type (text)– Media type for consumers.metadata (jsonb)– Asset-specific metadata (dimensions, page count, etc.).cardinality (int, nullable)– Optional hint for multi-object assets.tenant_id (uuid)– Tenant scoping.- Uniqueness on
(document_version_id, asset_type)ensures one logical asset per type; multi-object cases are stored indocument_asset_objects.
-
document_asset_objectsasset_id– FK todocument_assets.ordinal (int)– 1-based position for multi-part assets.s3_key (text)– Object storage key for the binary blob.metadata (jsonb)– Per-object metadata if needed (e.g. page number).
Simple assets (single thumbnail) live solely in document_assets. Complex ones
(e.g. per-page previews) use document_asset_objects to point at multiple S3
objects under a single logical asset.
Related tables
document_tagsanddocument_correspondentsprovide many-to-many relationships for categorisation.jobsrecords background work (OCR, thumbnails, indexing) keyed by tenant.webdav_tokens,refresh_tokens, anduser_passkeyslive alongside but do not alter the document schema directly.
Lifecycle summary
- Upload creates a
documentsrow and an initialdocument_versionsentry. - Workers generate derived assets, inserting rows into
document_assets(and possiblydocument_asset_objects). - When a new version is promoted, a fresh
document_versionsrow is written anddocuments.current_version_idis updated atomically. - Soft-deleting the document sets
deleted_at; restore clears it and the document reappears in listings.
This schema allows arbitrary metadata expansion while maintaining a clear separation between logical documents, their version history, and derived assets.