// Realtime Y.js document persistence (Phase 05 Task #59 — Hocuspocus + Y.js). // // `CollabDoc` is one row per (tenant, resourceType, resourceId) triple — the // Hocuspocus database extension fetches `ydocState` on connect, persists it // back on debounced flush, and bumps `version` + `lastUpdatedAt`. Documents // are tenant-scoped so the existing tenant-isolation tooling applies as-is. // // Refs: docs/improvement-plan/05-business-features/realtime-collab.md model CollabDoc { id String @id @default(cuid()) tenantId String /// Logical resource family the doc belongs to. Examples today: /// "kb-article" | "crm-note" | "workflow" — extensible without schema-changes. resourceType String /// Resource primary-key inside `resourceType`. Free-form; consumers /// embed CUIDs / UUIDs / slugs depending on the upstream entity. resourceId String /// Encoded Y.js update payload — `Y.encodeStateAsUpdate(doc)`. /// Persisted as `bytea`; capped at HOCUSPOCUS_MAX_PAYLOAD_BYTES on store. ydocState Bytes /// Monotonic update counter, incremented per store-call. Surfaces in /// admin dashboards for "is this doc still being edited" queries. version Int @default(0) /// Touched on every store-call. `lastSnapshotAt` lags behind for the /// snapshot/compaction cadence (separate task #59 step 5). lastUpdatedAt DateTime @default(now()) lastSnapshotAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([tenantId, resourceType, resourceId]) @@index([tenantId, resourceType, lastUpdatedAt(sort: Desc)]) @@index([lastUpdatedAt]) }