@tearleads/client-sdk 0.1.81 → 0.1.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/client/organizations/organizationReadModels.js +4 -2
  2. package/client/organizations/organizationReadModels.js.map +1 -1
  3. package/data/documents/documentSync.js.map +1 -1
  4. package/data/documents/shared/crypto.js.map +1 -1
  5. package/data/documents/shared/types.d.ts +1 -1
  6. package/data/documents/shared/types.js.map +1 -1
  7. package/data/persistence/container-contents/containerContentsPersistence.js +2 -2
  8. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  9. package/data/persistence/container-contents/containerContentsPersistenceTypes.d.ts +1 -1
  10. package/data/persistence/container-contents/containerContentsPersistenceTypes.js.map +1 -1
  11. package/data/persistence/container-contents/containerDeletionPersistence.js +1 -1
  12. package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
  13. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +3 -3
  14. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js +1 -1
  16. package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js.map +1 -1
  17. package/data/persistence/container-contents/containerMetadataRows.js +1 -1
  18. package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
  19. package/data/persistence/container-contents/containerPendingUpdatePersistence.js +2 -2
  20. package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
  21. package/data/persistence/container-contents/containerReconcilePersistence.js +1 -1
  22. package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
  23. package/data/persistence/container-contents/containerRemovalWork.js +1 -1
  24. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  25. package/data/persistence/documents/documentDiscoveryReset.d.ts +6 -0
  26. package/data/persistence/documents/documentsPersistence.js +2 -2
  27. package/data/persistence/documents/documentsPersistence.js.map +1 -1
  28. package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js +1 -1
  29. package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js.map +1 -1
  30. package/data/persistence/documents/internal/discardDocument.js +2 -2
  31. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  32. package/data/persistence/documents/internal/documentDeletionPersistence.js +2 -2
  33. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  34. package/data/persistence/documents/internal/documentMutationPersistence.js +3 -3
  35. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  36. package/data/persistence/documents/internal/documentPullContinuationPersistence.js +1 -1
  37. package/data/persistence/documents/internal/documentPullContinuationPersistence.js.map +1 -1
  38. package/data/persistence/documents/internal/documentRecordIdentity.js.map +1 -1
  39. package/data/persistence/documents/internal/documentRows.js.map +1 -1
  40. package/data/persistence/documents/internal/ensureDocumentsSchema.js +1 -1
  41. package/data/persistence/documents/internal/ensureDocumentsSchema.js.map +1 -1
  42. package/data/persistence/documents/internal/orphanSideRows.js +1 -1
  43. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  44. package/data/persistence/documents/internal/rowQueryPersistence.js +1 -1
  45. package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
  46. package/data/persistence/documents/internal/syncQueuePersistence.js +2 -2
  47. package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
  48. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentHistoryPersistence.d.ts +1 -1
  49. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentHistoryPersistence.js +5 -5
  50. package/data/persistence/documents/records/documentHistoryPersistence.js.map +1 -0
  51. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPendingUpdatePersistence.d.ts +2 -2
  52. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPendingUpdatePersistence.js +2 -2
  53. package/data/persistence/documents/records/documentPendingUpdatePersistence.js.map +1 -0
  54. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPersistenceTypes.d.ts +2 -2
  55. package/data/persistence/documents/records/documentPersistenceTypes.js.map +1 -0
  56. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentRecordPersistence.d.ts +1 -1
  57. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentRecordPersistence.js +4 -4
  58. package/data/persistence/documents/records/documentRecordPersistence.js.map +1 -0
  59. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentSyncFailurePersistence.d.ts +2 -2
  60. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentSyncFailurePersistence.js +3 -3
  61. package/data/persistence/documents/records/documentSyncFailurePersistence.js.map +1 -0
  62. package/data/{sqlite/documentPersistence → persistence/documents/records}/index.d.ts +2 -2
  63. package/data/{sqlite/documentPersistence → persistence/documents/records}/index.js +4 -4
  64. package/data/persistence/documents/records/index.js.map +1 -0
  65. package/data/persistence/documents/types.d.ts +2 -2
  66. package/data/persistence/documents/types.js.map +1 -1
  67. package/{workflows/sync/remoteResetPrincipalScope.d.ts → data/persistence/principalPolicy/principalPolicyRemoteReset.d.ts} +1 -1
  68. package/{workflows/sync/remoteResetPrincipalScope.js → data/persistence/principalPolicy/principalPolicyRemoteReset.js} +7 -7
  69. package/data/persistence/principalPolicy/principalPolicyRemoteReset.js.map +1 -0
  70. package/data/persistence/verifiedManifestBundlePersistence.d.ts +2 -0
  71. package/data/persistence/verifiedManifestBundlePersistence.js +7 -0
  72. package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -1
  73. package/data/sqlite/{documentPersistence/documentOrphanBlobReclaims.js → schema/documentOrphanBlobReclaimSchema.js} +1 -1
  74. package/data/sqlite/schema/documentOrphanBlobReclaimSchema.js.map +1 -0
  75. package/data/sqlite/schema/index.js +1 -1
  76. package/data/sqlite/schema/index.js.map +1 -1
  77. package/data/sqlite/sqliteBindBudget.js +12 -0
  78. package/data/sqlite/sqliteBindBudget.js.map +1 -1
  79. package/package.json +1 -1
  80. package/workflows/container-contents/container-state/create/createIntentSeed.js.map +1 -1
  81. package/workflows/container-contents/container-state/create/createWithMetadataPlan.js.map +1 -1
  82. package/workflows/container-contents/container-state/types.js.map +1 -1
  83. package/workflows/container-contents/metadata/index.js.map +1 -1
  84. package/workflows/container-contents/metadata/metadataEvents.d.ts +1 -1
  85. package/workflows/container-contents/metadata/metadataEvents.js.map +1 -1
  86. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js +1 -1
  87. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -1
  88. package/workflows/container-contents/metadata/metadataRemoteSync.d.ts +1 -1
  89. package/workflows/container-contents/metadata/metadataRemoteSync.js.map +1 -1
  90. package/workflows/container-contents/pendingWrites/index.js +1 -1
  91. package/workflows/container-contents/pendingWrites/index.js.map +1 -1
  92. package/{client/organizations/organizationAccessRestoration.js → workflows/container-contents/recovery/accessRestoration.js} +16 -12
  93. package/workflows/container-contents/recovery/accessRestoration.js.map +1 -0
  94. package/workflows/container-contents/remoteReset/containerRemoteReset.d.ts +185 -0
  95. package/workflows/container-contents/remoteReset/containerRemoteReset.js +174 -0
  96. package/workflows/container-contents/remoteReset/containerRemoteReset.js.map +1 -0
  97. package/workflows/container-contents/remoteReset/remoteResetCursorScope.d.ts +14 -0
  98. package/workflows/{sync → container-contents/remoteReset}/remoteResetCursorScope.js +2 -2
  99. package/workflows/container-contents/remoteReset/remoteResetCursorScope.js.map +1 -0
  100. package/workflows/documents/create/documentCreationPersistence.js.map +1 -1
  101. package/workflows/documents/create/index.d.ts +1 -1
  102. package/workflows/documents/create/index.js.map +1 -1
  103. package/workflows/documents/documentMutationCommit.d.ts +1 -1
  104. package/workflows/documents/documentMutationCommit.js.map +1 -1
  105. package/workflows/documents/index.d.ts +2 -2
  106. package/workflows/documents/index.js +2 -2
  107. package/workflows/documents/index.js.map +1 -1
  108. package/workflows/documents/remoteReset/documentRemoteReset.d.ts +56 -0
  109. package/workflows/documents/remoteReset/documentRemoteReset.js +135 -0
  110. package/workflows/documents/remoteReset/documentRemoteReset.js.map +1 -0
  111. package/workflows/{sync → documents/remoteReset}/remoteResetAttachments.js +3 -3
  112. package/workflows/documents/remoteReset/remoteResetAttachments.js.map +1 -0
  113. package/workflows/{sync → documents/remoteReset}/remoteResetPlans.d.ts +1 -1
  114. package/workflows/{sync → documents/remoteReset}/remoteResetPlans.js +7 -7
  115. package/workflows/documents/remoteReset/remoteResetPlans.js.map +1 -0
  116. package/workflows/documents/sync/index.js.map +1 -1
  117. package/workflows/documents/sync/initialSync.d.ts +1 -1
  118. package/workflows/documents/sync/initialSync.js.map +1 -1
  119. package/workflows/documents/sync/readOnlySync.d.ts +1 -1
  120. package/workflows/documents/sync/readOnlySync.js.map +1 -1
  121. package/workflows/documents/sync/syncAttemptPlanning.js.map +1 -1
  122. package/workflows/documents/sync/syncAttemptState.d.ts +1 -1
  123. package/workflows/documents/sync/syncAttemptState.js.map +1 -1
  124. package/workflows/documents/sync/syncResponseResult.js.map +1 -1
  125. package/workflows/documents/sync/syncSubmittedResult.js.map +1 -1
  126. package/workflows/documents/syncFailures/index.js.map +1 -1
  127. package/workflows/documents/syncPlan/syncContentKeys.d.ts +1 -1
  128. package/workflows/documents/syncPlan/syncContentKeys.js.map +1 -1
  129. package/workflows/documents/syncPlan/syncPlanMaterial.js.map +1 -1
  130. package/workflows/documents/syncPlan/syncPlanRequestBounds.js.map +1 -1
  131. package/workflows/documents/syncRekeys/syncContainerRekeys.js.map +1 -1
  132. package/workflows/documents/syncRekeys/syncRecoveryRekey.d.ts +1 -1
  133. package/workflows/documents/syncRekeys/syncRecoveryRekey.js +1 -1
  134. package/workflows/documents/syncRekeys/syncRecoveryRekey.js.map +1 -1
  135. package/workflows/organizations/readModel/listLocalOrganizations.js +1 -1
  136. package/workflows/organizations/readModel/listLocalOrganizations.js.map +1 -1
  137. package/workflows/organizations/readModel/organizationRemoteReset.js +25 -0
  138. package/workflows/organizations/readModel/organizationRemoteReset.js.map +1 -0
  139. package/workflows/registration/persistRegistrationBootstrap.d.ts +1 -1
  140. package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
  141. package/workflows/sync/remoteReset.js +60 -229
  142. package/workflows/sync/remoteReset.js.map +1 -1
  143. package/workflows/sync/remoteResetScope.d.ts +7 -10
  144. package/workflows/sync/remoteResetScope.js +26 -108
  145. package/workflows/sync/remoteResetScope.js.map +1 -1
  146. package/client/organizations/organizationAccessRestoration.js.map +0 -1
  147. package/data/sqlite/documentPersistence/documentHistoryPersistence.js.map +0 -1
  148. package/data/sqlite/documentPersistence/documentOrphanBlobReclaims.js.map +0 -1
  149. package/data/sqlite/documentPersistence/documentPendingUpdatePersistence.js.map +0 -1
  150. package/data/sqlite/documentPersistence/documentPersistenceTypes.js.map +0 -1
  151. package/data/sqlite/documentPersistence/documentRecordPersistence.js.map +0 -1
  152. package/data/sqlite/documentPersistence/documentSyncFailurePersistence.js.map +0 -1
  153. package/data/sqlite/documentPersistence/index.js.map +0 -1
  154. package/workflows/sync/remoteResetAttachments.js.map +0 -1
  155. package/workflows/sync/remoteResetBatches.js +0 -13
  156. package/workflows/sync/remoteResetBatches.js.map +0 -1
  157. package/workflows/sync/remoteResetCursorScope.js.map +0 -1
  158. package/workflows/sync/remoteResetPlans.js.map +0 -1
  159. package/workflows/sync/remoteResetPrincipalScope.js.map +0 -1
  160. /package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPersistenceTypes.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, sql } from \"drizzle-orm\";\nimport {\n DOCUMENT_SYNC_PULL_RECOVERY_REQUIRED,\n type DocumentSyncPullContinuation,\n serializeDocumentSyncPullContinuation,\n} from \"../../../documents/shared/sync/pullContinuation\";\nimport {\n documentProjectionTables,\n documents,\n documentTables,\n} from \"../../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../sqlite/sqlitePersistenceRuntime\";\nimport {\n type ExecSql,\n ensureSqlTables,\n runSerializedSqlMutation,\n} from \"../../../sqlite/sqlSchema\";\nimport type { DocumentRecord } from \"./documentPersistenceTypes\";\nimport { loadDocumentRecord } from \"./documentRecordPersistence\";\n\nexport function ensureDocumentTables(execSql: ExecSql): Promise<void> {\n return ensureSqlTables(execSql, documentTables);\n}\n\nexport function ensureDocumentProjectionTables(\n execSql: ExecSql,\n): Promise<void> {\n return ensureSqlTables(execSql, documentProjectionTables);\n}\n\n/** Replace only the exact rejected continuation with a durable recovery marker. */\nexport async function invalidateDocumentSyncPullContinuation(\n execSql: ExecSql,\n input: {\n accessEpoch: number;\n accessStateHash: string | null;\n appKind: string;\n continuation: DocumentSyncPullContinuation;\n contentKeyBundle: string | null;\n documentId: string;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n lastCommitLsn: string | null;\n localId: string;\n },\n): Promise<DocumentRecord | null> {\n await ensureDocumentTables(execSql);\n const expectedContinuation = serializeDocumentSyncPullContinuation(\n input.continuation,\n );\n if (expectedContinuation === null) return null;\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const { db } = getClientSQLitePersistenceRuntime(lockedExecSql);\n await db\n .update(documents)\n .set({ pullContinuation: DOCUMENT_SYNC_PULL_RECOVERY_REQUIRED })\n .where(\n and(\n eq(documents.appKind, input.appKind),\n eq(documents.localId, input.localId),\n eq(documents.documentId, input.documentId),\n eq(documents.accessEpoch, input.accessEpoch),\n sql`${documents.accessStateHash} IS ${input.accessStateHash}`,\n sql`${documents.contentKeyBundle} IS ${input.contentKeyBundle}`,\n sql`${documents.documentKekTargets} IS ${input.documentKekTargets}`,\n sql`${documents.documentManifestBundle} IS ${input.documentManifestBundle}`,\n sql`${documents.lastCommitLsn} IS ${input.lastCommitLsn}`,\n eq(documents.pullContinuation, expectedContinuation),\n ),\n )\n .run();\n return loadDocumentRecord(lockedExecSql, {\n appKind: input.appKind,\n localId: input.localId,\n });\n });\n}\n\nexport {\n enqueueDocumentPendingUpdate,\n enqueueDocumentPendingUpdateWithHistory,\n listDocumentPendingUpdates,\n MAX_PENDING_UPDATE_REKEYS,\n rekeyDocumentPendingUpdate,\n resetDocumentPendingUpdateRekeyBudget,\n settleDocumentPendingUpdate,\n unqueueDocumentPendingUpdates,\n} from \"./documentPendingUpdatePersistence\";\nexport type {\n DocumentRecord,\n DocumentScope,\n PendingUpdateFields,\n PendingUpdateRecord,\n} from \"./documentPersistenceTypes\";\nexport {\n deleteDocumentRecord,\n documentRecordSelection,\n findLocalIdByDocumentId,\n loadDocumentRecord,\n mapSelectedDocumentRecord,\n} from \"./documentRecordPersistence\";\nexport {\n clearDocumentSyncFailure,\n hasRecordedTerminalSyncFailures,\n recordDocumentSyncFailure,\n} from \"./documentSyncFailurePersistence\";\n"]}
@@ -1,10 +1,10 @@
1
1
  import type { DocumentProjectorRegistryInput, StoredDocumentKind } from "../../documents/documentKinds.js";
2
2
  import type { DiscoveredDocumentInput, DocumentSummary } from "../../documents/documentSummary.js";
3
3
  import type { DocumentSyncPullContinuation } from "../../documents/shared/sync/pullContinuation.js";
4
- import type { DocumentRecord as BaseDocumentRecord, PendingUpdateFields, PendingUpdateRecord } from "../../sqlite/documentPersistence/index.js";
5
4
  import type { ExecSql } from "../../sqlite/sqlSchema.js";
6
5
  import type { DocumentOrphanBlobPersistence } from "./orphanBlobPersistence.js";
7
- export type { PendingUpdateRecord } from "../../sqlite/documentPersistence/index.js";
6
+ import type { DocumentRecord as BaseDocumentRecord, PendingUpdateFields, PendingUpdateRecord } from "./records/index.js";
7
+ export type { PendingUpdateRecord } from "./records/index.js";
8
8
  export interface StoredDocumentRecord extends BaseDocumentRecord {
9
9
  containerId: string | null;
10
10
  documentKind?: StoredDocumentKind;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n DocumentProjectorRegistryInput,\n StoredDocumentKind,\n} from \"../../documents/documentKinds\";\nimport type {\n DiscoveredDocumentInput,\n DocumentSummary,\n} from \"../../documents/documentSummary\";\nimport type { DocumentSyncPullContinuation } from \"../../documents/shared/sync/pullContinuation\";\nimport type {\n DocumentRecord as BaseDocumentRecord,\n PendingUpdateFields,\n PendingUpdateRecord,\n} from \"../../sqlite/documentPersistence\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport type { DocumentOrphanBlobPersistence } from \"./orphanBlobPersistence\";\n\nexport type { PendingUpdateRecord } from \"../../sqlite/documentPersistence\";\n\nexport interface StoredDocumentRecord extends BaseDocumentRecord {\n containerId: string | null;\n documentKind?: StoredDocumentKind;\n text: string;\n title?: string;\n}\n\nexport type DiscardDocumentToShellResult =\n | { discarded: false }\n | {\n discarded: true;\n documentKind: StoredDocumentKind;\n };\n\nexport interface PendingUpdateInsert extends PendingUpdateFields {\n localId: string;\n}\n\n/**\n * The identity a pending attachment upload reuses across attempts so a retry\n * (next sync pass or after a restart) reproduces byte-identical encrypted bytes\n * and resumes the same multipart stage instead of orphaning it. `contentKey` and\n * the chunk `nonceSeed` are base64. `partSize`/`stageId` are filled in once the\n * multipart stage has been opened and remain null before that.\n */\nexport interface PendingAttachmentUploadIdentity {\n blobId: string;\n contentKey: string;\n contentKeyEpoch: number;\n nonceSeed: string;\n partSize: number | null;\n plaintextSha256: string;\n stageId: string | null;\n}\n\nexport interface PendingAttachmentRecord {\n byteLength: number;\n contentSha256: string;\n localId: string;\n mimeType: string | null;\n name: string;\n slotId: string;\n storageKey: string;\n upload?: PendingAttachmentUploadIdentity | null;\n}\n\nexport interface LocalAttachmentRecord {\n blobId: string | null;\n byteLength: number;\n // Plaintext digest of the bytes at `storageKey`. Compared with the digest\n // the document content records for the slot: a held copy that differs is a\n // validly signed served binding the document has not recorded (yet).\n contentSha256: string;\n // Set once the slot is unlinked from a synced document and cleared when the\n // slot is written again. The record survives the unlink so the next sync can\n // still detach the remote binding; `detachedAt` is what keeps the local read\n // models from reporting the slot as a live blob reference in the meantime.\n detachedAt: string | null;\n localId: string;\n mimeType: string | null;\n slotId: string;\n storageKey: string;\n}\n\nexport interface AttachmentStagingRows {\n localAttachments: ReadonlyArray<LocalAttachmentRecord>;\n pendingAttachments: ReadonlyArray<PendingAttachmentRecord>;\n}\n\nexport interface AttachmentRemovalRows {\n mode: \"delete\" | \"detach\";\n slotId: string;\n storageKey: string;\n}\n\nexport interface DocumentHistoryRestoreState {\n snapshot: string;\n tailUpdates: readonly {\n origin: \"local\" | \"remote\";\n updateData: string;\n }[];\n}\n\nexport interface RelinkPersistedDocumentInput {\n accessEpoch: number;\n accessStateHash?: string | null;\n containerId: string;\n documentId: string | null;\n localId: string;\n}\n\nexport interface ContainerDocumentTombstoneInput {\n containerId: string;\n documentId: string;\n /** Epoch of the verified head; apply refuses a head below local state. */\n accessEpoch: number;\n /** Verified head link set (omits `containerId`); apply needs signed evidence. */\n linkedContainerIds: ReadonlyArray<string>;\n updatedAt: string;\n}\n\nexport type DocumentSummarySortDirection = \"asc\" | \"desc\";\nexport type DocumentSummarySortKey = \"kind\" | \"title\" | \"updated\";\n\nexport interface DocumentSummarySort {\n readonly direction: DocumentSummarySortDirection;\n readonly key: DocumentSummarySortKey;\n}\n\nexport interface ListDocumentSummariesInput {\n documentKind?: StoredDocumentKind | undefined;\n limit?: number | undefined;\n offset?: number | undefined;\n sort?: DocumentSummarySort | undefined;\n}\n\nexport interface DocumentSummaryList {\n readonly rows: ReadonlyArray<DocumentSummary>;\n readonly totalCount: number;\n}\n\nexport interface DocumentsPersistence {\n readonly orphanBlobs: DocumentOrphanBlobPersistence;\n /**\n * The adapter guarantees that recovery checkpoint replacement, selection of\n * covered local history, rejection of unproven ordinary pending rows, and\n * quarantine of every queued checkpoint artifact share the guarded\n * `commitDocumentMutation` transaction, which also advances the canonical\n * recovery generation. An unrelated history tail not covered by the rebuild\n * must abort that transaction.\n */\n readonly supportsAtomicRecoveryHistoryPruning: boolean;\n /**\n * Atomically create the canonical row, standard projections, and birth\n * checkpoint. Returns null when another initializer already owns localId.\n */\n createDocumentWithHistoryCheckpoint: (\n execSql: ExecSql,\n document: StoredDocumentRecord,\n historyCheckpoint: {\n endVersionVector: string;\n snapshot: string;\n },\n options:\n | {\n pendingUpdate?: PendingUpdateFields;\n /** Recheck volatile caller ownership inside the create transaction. */\n stillCurrent?: (() => boolean) | undefined;\n updatedAt?: string;\n }\n | undefined,\n saveClientProjection: (\n transactionExecSql: ExecSql,\n updatedAt: string,\n ) => Promise<void>,\n ) => Promise<string | null>;\n /**\n * Conditionally commit one already-prepared mutation against the exact\n * durable record it was derived from. The identity/progress comparison,\n * attachment and history writes, accepted-queue settlement,\n * canonical/projection save, and client projection callback must share one\n * adapter transaction.\n */\n commitDocumentMutation: (\n execSql: ExecSql,\n input: {\n acceptedPendingUpdateIds: readonly string[];\n attachmentRemoval?: AttachmentRemovalRows | undefined;\n attachmentStaging?: AttachmentStagingRows | undefined;\n clearSyncFailure?: boolean | undefined;\n document: StoredDocumentRecord;\n expectedRecord: StoredDocumentRecord;\n historyCheckpoint?:\n | {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n pruneCoveredLocalState: boolean;\n snapshot: string;\n }\n | undefined;\n historyUpdateOrigin?: \"local\" | \"remote\" | undefined;\n historyUpdates?: readonly string[] | undefined;\n pendingUpdate?: PendingUpdateFields | undefined;\n settleAcceptedPendingOnConflict: boolean;\n /**\n * Recheck volatile caller ownership inside the adapter transaction,\n * before any durable side effect. A false result aborts the commit.\n */\n stillCurrent?: (() => boolean) | undefined;\n updatedAt?: string | undefined;\n },\n saveClientProjection: (\n transactionExecSql: ExecSql,\n updatedAt: string,\n ) => Promise<void>,\n ) => Promise<\n | { committed: true; updatedAt: string }\n | { committed: false; currentRecord: StoredDocumentRecord | null }\n >;\n /** Settle acknowledged rows only while the response's security identity survives. */\n settleAcceptedPendingUpdates: (\n execSql: ExecSql,\n input: {\n expectedRecord: StoredDocumentRecord;\n pendingUpdateIds: readonly string[];\n },\n ) => Promise<StoredDocumentRecord | null>;\n ensureSchema: (execSql: ExecSql) => Promise<void>;\n listDocuments: (execSql: ExecSql) => Promise<DocumentSummary[]>;\n listDocumentSummaries: (\n execSql: ExecSql,\n input?: ListDocumentSummariesInput,\n ) => Promise<DocumentSummaryList>;\n listDocumentsByContainerIdsOrDocumentIds: (\n execSql: ExecSql,\n input: {\n containerIds: ReadonlyArray<string>;\n documentIds: ReadonlyArray<string>;\n },\n ) => Promise<DocumentSummary[]>;\n findDocumentLocalIdsByContainerId: (\n execSql: ExecSql,\n containerId: string,\n ) => Promise<string[]>;\n /**\n * Select one local row for a remote document identity. Prefer any row with\n * queued updates or a deferred-sync frontier, then break duplicates by\n * updatedAt and localId descending.\n */\n findLocalIdByDocumentId: (\n execSql: ExecSql,\n documentId: string,\n ) => Promise<string | null>;\n /** Canonical-row probe; false authorizes destructive orphan teardown. */\n hasDocument: (execSql: ExecSql, localId: string) => Promise<boolean>;\n /** Observe whether the canonical row still names the expected remote stream. */\n documentIdentityMatches: (\n execSql: ExecSql,\n localId: string,\n expectedDocumentId: string | null,\n expectedRecoveryGeneration: number,\n ) => Promise<boolean>;\n loadDocument: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<StoredDocumentRecord | null>;\n /** Read the canonical record and its history from one database snapshot. */\n loadDocumentWithHistoryRestoreState: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{\n document: StoredDocumentRecord | null;\n historyRestoreState: DocumentHistoryRestoreState | null;\n }>;\n /** Read every document-store startup row from one database snapshot. */\n loadDocumentStoreState: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{\n document: StoredDocumentRecord | null;\n historyRestoreState: DocumentHistoryRestoreState | null;\n localAttachments: LocalAttachmentRecord[];\n pendingAttachments: PendingAttachmentRecord[];\n }>;\n /**\n * Atomically replace the exact rejected pull continuation with the durable\n * recovery marker when every supplied sync-identity field still matches.\n * Return the authoritative current record after the compare-and-set, or\n * null when the canonical row no longer exists. A CAS loss returns the\n * winning record so the live store can adopt its newer progress.\n */\n invalidatePullContinuation: (\n execSql: ExecSql,\n input: {\n accessEpoch: number;\n accessStateHash: string | null;\n continuation: DocumentSyncPullContinuation;\n contentKeyBundle: string | null;\n documentId: string;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n lastCommitLsn: string | null;\n localId: string;\n },\n ) => Promise<{\n historyRestoreState: DocumentHistoryRestoreState | null;\n record: StoredDocumentRecord;\n } | null>;\n // Read the authoritative container placement for a locally persisted document\n // straight from its projection row. Returns `undefined` when no projection row\n // exists yet (a first create/discovery persist), so a caller can distinguish\n // that from a row that legitimately carries a null container (a document\n // unlinked from every container). Container placement is owned by the\n // link/tombstone/discovery layer, so a content-metadata persist reads this to\n // avoid republishing a stale in-memory container.\n loadDocumentContainer: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{ containerId: string | null } | undefined>;\n saveDocument: (\n execSql: ExecSql,\n document: StoredDocumentRecord,\n options?: {\n updatedAt?: string;\n },\n ) => Promise<string>;\n /**\n * Durable full-history support (checkpoint + append-only tail) — the ONLY\n * persisted content source. REQUIRED: a persistence without these could\n * report successful writes whose documents reopen empty.\n */\n appendHistoryUpdates: (\n execSql: ExecSql,\n input: {\n localId: string;\n origin: \"local\" | \"remote\";\n updates: readonly string[];\n },\n ) => Promise<void>;\n loadHistoryRestoreState: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<DocumentHistoryRestoreState | null>;\n readHistoryTailSize: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{\n byteLength: number;\n hasCheckpoint: boolean;\n rowCount: number;\n }>;\n listHistoryTailEntries: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{ id: string; updateData: string }[]>;\n replaceHistoryCheckpoint: (\n execSql: ExecSql,\n input: {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n force?: boolean;\n localId: string;\n snapshot: string;\n stillCurrent?: () => boolean;\n },\n ) => Promise<void>;\n saveDocumentAndDeletePendingUpdates: (\n execSql: ExecSql,\n document: StoredDocumentRecord,\n pendingUpdateIds: readonly string[],\n options?: {\n updatedAt?: string;\n },\n ) => Promise<string>;\n deleteDocument: (execSql: ExecSql, localId: string) => Promise<void>;\n /**\n * Delete the canonical row and every side row only when its security identity\n * and container placement still match the captured record. The comparison,\n * deletes, and client\n * projection callback must share one write transaction.\n */\n deleteDocumentIfMatches: (\n execSql: ExecSql,\n expectedRecord: StoredDocumentRecord,\n deleteClientProjection: (transactionExecSql: ExecSql) => Promise<void>,\n ) => Promise<boolean>;\n /**\n * Delete orphaned side rows only if the canonical document is still absent.\n * The absence check, row cleanup, and client projection callback must share\n * one write transaction so a concurrent create is preserved.\n */\n deleteDocumentSideRowsIfAbsent: (\n execSql: ExecSql,\n localId: string,\n expectedDocumentId: string | null,\n deleteClientProjection: (transactionExecSql: ExecSql) => Promise<void>,\n ) => Promise<boolean>;\n upsertDiscoveredDocument: (\n execSql: ExecSql,\n input: DiscoveredDocumentInput,\n ) => Promise<DocumentSummary>;\n relinkPersistedDocument: (\n execSql: ExecSql,\n input: RelinkPersistedDocumentInput,\n ) => Promise<DocumentSummary | null>;\n listPendingUpdates: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<PendingUpdateRecord[]>;\n rekeyPendingUpdate: (execSql: ExecSql, id: string) => Promise<string | null>;\n listPendingAttachments: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<PendingAttachmentRecord[]>;\n listLocalAttachments: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<LocalAttachmentRecord[]>;\n /**\n * Durably append the outgoing row and matching local-history tail entry.\n * When expectations are supplied, compare the document identity and recovery\n * generation with the canonical row inside that same mutation and return\n * false on absence or mismatch. Adapters must not insert either row.\n */\n enqueuePendingUpdate: (\n execSql: ExecSql,\n pendingUpdate: PendingUpdateInsert,\n options?: {\n expectedDocumentId: string | null;\n expectedRecoveryGeneration: number;\n },\n ) => Promise<boolean>;\n /** Replace a hydrated copy only if its observed durable slot and live document still match. */\n saveHydratedAttachment: (\n execSql: ExecSql,\n input: {\n attachment: LocalAttachmentRecord;\n expectedStorageKey: string | null;\n expectedSnapshotEndVersion: string | null;\n stillCurrent: () => boolean;\n },\n ) => Promise<boolean>;\n saveLocalAttachment: (\n execSql: ExecSql,\n attachment: LocalAttachmentRecord,\n ) => Promise<void>;\n deleteLocalAttachment: (\n execSql: ExecSql,\n localId: string,\n slotId: string,\n storageKey: string,\n ) => Promise<void>;\n markLocalAttachmentDetached: (\n execSql: ExecSql,\n localId: string,\n slotId: string,\n storageKey: string,\n ) => Promise<void>;\n savePendingAttachment: (\n execSql: ExecSql,\n attachment: PendingAttachmentRecord,\n ) => Promise<void>;\n deletePendingUpdate: (execSql: ExecSql, id: string) => Promise<void>;\n deletePendingUpdates: (execSql: ExecSql, localId: string) => Promise<void>;\n deletePendingAttachment: (\n execSql: ExecSql,\n localId: string,\n slotId: string,\n storageKey: string,\n ) => Promise<void>;\n deletePendingAttachments: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<void>;\n /**\n * Atomically convert a stuck document's local state to the\n * freshly-discovered-share shell (see the SQL implementation's doc\n * comment). The projector registry clears the document-kind client\n * projection in the same transaction — those tables live with the app's\n * projector definitions, so the CALLER'S registry is required (the default\n * registry knows no app kinds, and a discard that silently kept a\n * contact's or card's projected fields would leak the discarded values).\n * The method itself is optional: implementations without the full document\n * schema (container metadata, simple doubles) simply do not offer the\n * discard escape hatch.\n */\n /**\n * `expectedDocumentId` is revalidated against the loaded record inside the\n * serialized mutation: a stale caller (or a relink that raced the request)\n * must never discard a different identity's edits.\n */\n discardDocumentToShell?: (\n execSql: ExecSql,\n localId: string,\n expectedDocumentId: string,\n documentProjectors: DocumentProjectorRegistryInput,\n ) => Promise<DiscardDocumentToShellResult>;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n DocumentProjectorRegistryInput,\n StoredDocumentKind,\n} from \"../../documents/documentKinds\";\nimport type {\n DiscoveredDocumentInput,\n DocumentSummary,\n} from \"../../documents/documentSummary\";\nimport type { DocumentSyncPullContinuation } from \"../../documents/shared/sync/pullContinuation\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport type { DocumentOrphanBlobPersistence } from \"./orphanBlobPersistence\";\nimport type {\n DocumentRecord as BaseDocumentRecord,\n PendingUpdateFields,\n PendingUpdateRecord,\n} from \"./records\";\n\nexport type { PendingUpdateRecord } from \"./records\";\n\nexport interface StoredDocumentRecord extends BaseDocumentRecord {\n containerId: string | null;\n documentKind?: StoredDocumentKind;\n text: string;\n title?: string;\n}\n\nexport type DiscardDocumentToShellResult =\n | { discarded: false }\n | {\n discarded: true;\n documentKind: StoredDocumentKind;\n };\n\nexport interface PendingUpdateInsert extends PendingUpdateFields {\n localId: string;\n}\n\n/**\n * The identity a pending attachment upload reuses across attempts so a retry\n * (next sync pass or after a restart) reproduces byte-identical encrypted bytes\n * and resumes the same multipart stage instead of orphaning it. `contentKey` and\n * the chunk `nonceSeed` are base64. `partSize`/`stageId` are filled in once the\n * multipart stage has been opened and remain null before that.\n */\nexport interface PendingAttachmentUploadIdentity {\n blobId: string;\n contentKey: string;\n contentKeyEpoch: number;\n nonceSeed: string;\n partSize: number | null;\n plaintextSha256: string;\n stageId: string | null;\n}\n\nexport interface PendingAttachmentRecord {\n byteLength: number;\n contentSha256: string;\n localId: string;\n mimeType: string | null;\n name: string;\n slotId: string;\n storageKey: string;\n upload?: PendingAttachmentUploadIdentity | null;\n}\n\nexport interface LocalAttachmentRecord {\n blobId: string | null;\n byteLength: number;\n // Plaintext digest of the bytes at `storageKey`. Compared with the digest\n // the document content records for the slot: a held copy that differs is a\n // validly signed served binding the document has not recorded (yet).\n contentSha256: string;\n // Set once the slot is unlinked from a synced document and cleared when the\n // slot is written again. The record survives the unlink so the next sync can\n // still detach the remote binding; `detachedAt` is what keeps the local read\n // models from reporting the slot as a live blob reference in the meantime.\n detachedAt: string | null;\n localId: string;\n mimeType: string | null;\n slotId: string;\n storageKey: string;\n}\n\nexport interface AttachmentStagingRows {\n localAttachments: ReadonlyArray<LocalAttachmentRecord>;\n pendingAttachments: ReadonlyArray<PendingAttachmentRecord>;\n}\n\nexport interface AttachmentRemovalRows {\n mode: \"delete\" | \"detach\";\n slotId: string;\n storageKey: string;\n}\n\nexport interface DocumentHistoryRestoreState {\n snapshot: string;\n tailUpdates: readonly {\n origin: \"local\" | \"remote\";\n updateData: string;\n }[];\n}\n\nexport interface RelinkPersistedDocumentInput {\n accessEpoch: number;\n accessStateHash?: string | null;\n containerId: string;\n documentId: string | null;\n localId: string;\n}\n\nexport interface ContainerDocumentTombstoneInput {\n containerId: string;\n documentId: string;\n /** Epoch of the verified head; apply refuses a head below local state. */\n accessEpoch: number;\n /** Verified head link set (omits `containerId`); apply needs signed evidence. */\n linkedContainerIds: ReadonlyArray<string>;\n updatedAt: string;\n}\n\nexport type DocumentSummarySortDirection = \"asc\" | \"desc\";\nexport type DocumentSummarySortKey = \"kind\" | \"title\" | \"updated\";\n\nexport interface DocumentSummarySort {\n readonly direction: DocumentSummarySortDirection;\n readonly key: DocumentSummarySortKey;\n}\n\nexport interface ListDocumentSummariesInput {\n documentKind?: StoredDocumentKind | undefined;\n limit?: number | undefined;\n offset?: number | undefined;\n sort?: DocumentSummarySort | undefined;\n}\n\nexport interface DocumentSummaryList {\n readonly rows: ReadonlyArray<DocumentSummary>;\n readonly totalCount: number;\n}\n\nexport interface DocumentsPersistence {\n readonly orphanBlobs: DocumentOrphanBlobPersistence;\n /**\n * The adapter guarantees that recovery checkpoint replacement, selection of\n * covered local history, rejection of unproven ordinary pending rows, and\n * quarantine of every queued checkpoint artifact share the guarded\n * `commitDocumentMutation` transaction, which also advances the canonical\n * recovery generation. An unrelated history tail not covered by the rebuild\n * must abort that transaction.\n */\n readonly supportsAtomicRecoveryHistoryPruning: boolean;\n /**\n * Atomically create the canonical row, standard projections, and birth\n * checkpoint. Returns null when another initializer already owns localId.\n */\n createDocumentWithHistoryCheckpoint: (\n execSql: ExecSql,\n document: StoredDocumentRecord,\n historyCheckpoint: {\n endVersionVector: string;\n snapshot: string;\n },\n options:\n | {\n pendingUpdate?: PendingUpdateFields;\n /** Recheck volatile caller ownership inside the create transaction. */\n stillCurrent?: (() => boolean) | undefined;\n updatedAt?: string;\n }\n | undefined,\n saveClientProjection: (\n transactionExecSql: ExecSql,\n updatedAt: string,\n ) => Promise<void>,\n ) => Promise<string | null>;\n /**\n * Conditionally commit one already-prepared mutation against the exact\n * durable record it was derived from. The identity/progress comparison,\n * attachment and history writes, accepted-queue settlement,\n * canonical/projection save, and client projection callback must share one\n * adapter transaction.\n */\n commitDocumentMutation: (\n execSql: ExecSql,\n input: {\n acceptedPendingUpdateIds: readonly string[];\n attachmentRemoval?: AttachmentRemovalRows | undefined;\n attachmentStaging?: AttachmentStagingRows | undefined;\n clearSyncFailure?: boolean | undefined;\n document: StoredDocumentRecord;\n expectedRecord: StoredDocumentRecord;\n historyCheckpoint?:\n | {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n pruneCoveredLocalState: boolean;\n snapshot: string;\n }\n | undefined;\n historyUpdateOrigin?: \"local\" | \"remote\" | undefined;\n historyUpdates?: readonly string[] | undefined;\n pendingUpdate?: PendingUpdateFields | undefined;\n settleAcceptedPendingOnConflict: boolean;\n /**\n * Recheck volatile caller ownership inside the adapter transaction,\n * before any durable side effect. A false result aborts the commit.\n */\n stillCurrent?: (() => boolean) | undefined;\n updatedAt?: string | undefined;\n },\n saveClientProjection: (\n transactionExecSql: ExecSql,\n updatedAt: string,\n ) => Promise<void>,\n ) => Promise<\n | { committed: true; updatedAt: string }\n | { committed: false; currentRecord: StoredDocumentRecord | null }\n >;\n /** Settle acknowledged rows only while the response's security identity survives. */\n settleAcceptedPendingUpdates: (\n execSql: ExecSql,\n input: {\n expectedRecord: StoredDocumentRecord;\n pendingUpdateIds: readonly string[];\n },\n ) => Promise<StoredDocumentRecord | null>;\n ensureSchema: (execSql: ExecSql) => Promise<void>;\n listDocuments: (execSql: ExecSql) => Promise<DocumentSummary[]>;\n listDocumentSummaries: (\n execSql: ExecSql,\n input?: ListDocumentSummariesInput,\n ) => Promise<DocumentSummaryList>;\n listDocumentsByContainerIdsOrDocumentIds: (\n execSql: ExecSql,\n input: {\n containerIds: ReadonlyArray<string>;\n documentIds: ReadonlyArray<string>;\n },\n ) => Promise<DocumentSummary[]>;\n findDocumentLocalIdsByContainerId: (\n execSql: ExecSql,\n containerId: string,\n ) => Promise<string[]>;\n /**\n * Select one local row for a remote document identity. Prefer any row with\n * queued updates or a deferred-sync frontier, then break duplicates by\n * updatedAt and localId descending.\n */\n findLocalIdByDocumentId: (\n execSql: ExecSql,\n documentId: string,\n ) => Promise<string | null>;\n /** Canonical-row probe; false authorizes destructive orphan teardown. */\n hasDocument: (execSql: ExecSql, localId: string) => Promise<boolean>;\n /** Observe whether the canonical row still names the expected remote stream. */\n documentIdentityMatches: (\n execSql: ExecSql,\n localId: string,\n expectedDocumentId: string | null,\n expectedRecoveryGeneration: number,\n ) => Promise<boolean>;\n loadDocument: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<StoredDocumentRecord | null>;\n /** Read the canonical record and its history from one database snapshot. */\n loadDocumentWithHistoryRestoreState: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{\n document: StoredDocumentRecord | null;\n historyRestoreState: DocumentHistoryRestoreState | null;\n }>;\n /** Read every document-store startup row from one database snapshot. */\n loadDocumentStoreState: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{\n document: StoredDocumentRecord | null;\n historyRestoreState: DocumentHistoryRestoreState | null;\n localAttachments: LocalAttachmentRecord[];\n pendingAttachments: PendingAttachmentRecord[];\n }>;\n /**\n * Atomically replace the exact rejected pull continuation with the durable\n * recovery marker when every supplied sync-identity field still matches.\n * Return the authoritative current record after the compare-and-set, or\n * null when the canonical row no longer exists. A CAS loss returns the\n * winning record so the live store can adopt its newer progress.\n */\n invalidatePullContinuation: (\n execSql: ExecSql,\n input: {\n accessEpoch: number;\n accessStateHash: string | null;\n continuation: DocumentSyncPullContinuation;\n contentKeyBundle: string | null;\n documentId: string;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n lastCommitLsn: string | null;\n localId: string;\n },\n ) => Promise<{\n historyRestoreState: DocumentHistoryRestoreState | null;\n record: StoredDocumentRecord;\n } | null>;\n // Read the authoritative container placement for a locally persisted document\n // straight from its projection row. Returns `undefined` when no projection row\n // exists yet (a first create/discovery persist), so a caller can distinguish\n // that from a row that legitimately carries a null container (a document\n // unlinked from every container). Container placement is owned by the\n // link/tombstone/discovery layer, so a content-metadata persist reads this to\n // avoid republishing a stale in-memory container.\n loadDocumentContainer: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{ containerId: string | null } | undefined>;\n saveDocument: (\n execSql: ExecSql,\n document: StoredDocumentRecord,\n options?: {\n updatedAt?: string;\n },\n ) => Promise<string>;\n /**\n * Durable full-history support (checkpoint + append-only tail) — the ONLY\n * persisted content source. REQUIRED: a persistence without these could\n * report successful writes whose documents reopen empty.\n */\n appendHistoryUpdates: (\n execSql: ExecSql,\n input: {\n localId: string;\n origin: \"local\" | \"remote\";\n updates: readonly string[];\n },\n ) => Promise<void>;\n loadHistoryRestoreState: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<DocumentHistoryRestoreState | null>;\n readHistoryTailSize: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{\n byteLength: number;\n hasCheckpoint: boolean;\n rowCount: number;\n }>;\n listHistoryTailEntries: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<{ id: string; updateData: string }[]>;\n replaceHistoryCheckpoint: (\n execSql: ExecSql,\n input: {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n force?: boolean;\n localId: string;\n snapshot: string;\n stillCurrent?: () => boolean;\n },\n ) => Promise<void>;\n saveDocumentAndDeletePendingUpdates: (\n execSql: ExecSql,\n document: StoredDocumentRecord,\n pendingUpdateIds: readonly string[],\n options?: {\n updatedAt?: string;\n },\n ) => Promise<string>;\n deleteDocument: (execSql: ExecSql, localId: string) => Promise<void>;\n /**\n * Delete the canonical row and every side row only when its security identity\n * and container placement still match the captured record. The comparison,\n * deletes, and client\n * projection callback must share one write transaction.\n */\n deleteDocumentIfMatches: (\n execSql: ExecSql,\n expectedRecord: StoredDocumentRecord,\n deleteClientProjection: (transactionExecSql: ExecSql) => Promise<void>,\n ) => Promise<boolean>;\n /**\n * Delete orphaned side rows only if the canonical document is still absent.\n * The absence check, row cleanup, and client projection callback must share\n * one write transaction so a concurrent create is preserved.\n */\n deleteDocumentSideRowsIfAbsent: (\n execSql: ExecSql,\n localId: string,\n expectedDocumentId: string | null,\n deleteClientProjection: (transactionExecSql: ExecSql) => Promise<void>,\n ) => Promise<boolean>;\n upsertDiscoveredDocument: (\n execSql: ExecSql,\n input: DiscoveredDocumentInput,\n ) => Promise<DocumentSummary>;\n relinkPersistedDocument: (\n execSql: ExecSql,\n input: RelinkPersistedDocumentInput,\n ) => Promise<DocumentSummary | null>;\n listPendingUpdates: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<PendingUpdateRecord[]>;\n rekeyPendingUpdate: (execSql: ExecSql, id: string) => Promise<string | null>;\n listPendingAttachments: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<PendingAttachmentRecord[]>;\n listLocalAttachments: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<LocalAttachmentRecord[]>;\n /**\n * Durably append the outgoing row and matching local-history tail entry.\n * When expectations are supplied, compare the document identity and recovery\n * generation with the canonical row inside that same mutation and return\n * false on absence or mismatch. Adapters must not insert either row.\n */\n enqueuePendingUpdate: (\n execSql: ExecSql,\n pendingUpdate: PendingUpdateInsert,\n options?: {\n expectedDocumentId: string | null;\n expectedRecoveryGeneration: number;\n },\n ) => Promise<boolean>;\n /** Replace a hydrated copy only if its observed durable slot and live document still match. */\n saveHydratedAttachment: (\n execSql: ExecSql,\n input: {\n attachment: LocalAttachmentRecord;\n expectedStorageKey: string | null;\n expectedSnapshotEndVersion: string | null;\n stillCurrent: () => boolean;\n },\n ) => Promise<boolean>;\n saveLocalAttachment: (\n execSql: ExecSql,\n attachment: LocalAttachmentRecord,\n ) => Promise<void>;\n deleteLocalAttachment: (\n execSql: ExecSql,\n localId: string,\n slotId: string,\n storageKey: string,\n ) => Promise<void>;\n markLocalAttachmentDetached: (\n execSql: ExecSql,\n localId: string,\n slotId: string,\n storageKey: string,\n ) => Promise<void>;\n savePendingAttachment: (\n execSql: ExecSql,\n attachment: PendingAttachmentRecord,\n ) => Promise<void>;\n deletePendingUpdate: (execSql: ExecSql, id: string) => Promise<void>;\n deletePendingUpdates: (execSql: ExecSql, localId: string) => Promise<void>;\n deletePendingAttachment: (\n execSql: ExecSql,\n localId: string,\n slotId: string,\n storageKey: string,\n ) => Promise<void>;\n deletePendingAttachments: (\n execSql: ExecSql,\n localId: string,\n ) => Promise<void>;\n /**\n * Atomically convert a stuck document's local state to the\n * freshly-discovered-share shell (see the SQL implementation's doc\n * comment). The projector registry clears the document-kind client\n * projection in the same transaction — those tables live with the app's\n * projector definitions, so the CALLER'S registry is required (the default\n * registry knows no app kinds, and a discard that silently kept a\n * contact's or card's projected fields would leak the discarded values).\n * The method itself is optional: implementations without the full document\n * schema (container metadata, simple doubles) simply do not offer the\n * discard escape hatch.\n */\n /**\n * `expectedDocumentId` is revalidated against the loaded record inside the\n * serialized mutation: a stale caller (or a relink that raced the request)\n * must never discard a different identity's edits.\n */\n discardDocumentToShell?: (\n execSql: ExecSql,\n localId: string,\n expectedDocumentId: string,\n documentProjectors: DocumentProjectorRegistryInput,\n ) => Promise<DiscardDocumentToShellResult>;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { ClientSQLiteTransactionScope } from "../../data/sqlite/sqlitePersistenceRuntime.js";
1
+ import type { ClientSQLiteTransactionScope } from "../../sqlite/sqlitePersistenceRuntime.js";
2
2
  export interface RemoteResetPrincipalKey {
3
3
  readonly principalId: string;
4
4
  readonly principalType: "group" | "organization";
@@ -1,10 +1,10 @@
1
1
  import { and, eq, or } from "drizzle-orm";
2
- import { principalPolicies, principalPolicyBundleHistory, principalPolicyBundleReferences, principalPolicyCheckpoints, principalPolicyOrganizations, } from "../../data/sqlite/schema/index.js";
3
- import { principalHistoryEntries, principalHistoryNodes, principalHistoryPrefixes, } from "../../data/sqlite/schema/principalHistoryEvidenceSchema.js";
4
- import { principalHistoryNodeReferences, principalHistoryRootOwners, } from "../../data/sqlite/schema/principalHistoryNodeRetentionSchema.js";
5
- import { principalKeyEnvelopeArchive } from "../../data/sqlite/schema/principalHistoryRetentionSchema.js";
6
- import { principalHistoryStages } from "../../data/sqlite/schema/principalHistoryStageSchema.js";
7
- import { remoteResetBatches } from "./remoteResetBatches.js";
2
+ import { principalPolicies, principalPolicyBundleHistory, principalPolicyBundleReferences, principalPolicyCheckpoints, principalPolicyOrganizations, } from "../../sqlite/schema/index.js";
3
+ import { principalHistoryEntries, principalHistoryNodes, principalHistoryPrefixes, } from "../../sqlite/schema/principalHistoryEvidenceSchema.js";
4
+ import { principalHistoryNodeReferences, principalHistoryRootOwners, } from "../../sqlite/schema/principalHistoryNodeRetentionSchema.js";
5
+ import { principalKeyEnvelopeArchive } from "../../sqlite/schema/principalHistoryRetentionSchema.js";
6
+ import { principalHistoryStages } from "../../sqlite/schema/principalHistoryStageSchema.js";
7
+ import { remoteResetBatches } from "../../sqlite/sqliteBindBudget.js";
8
8
  /** Current cache writes atomically pin ownership; reset never backfills it. */
9
9
  export async function loadRemoteResetPrincipalScope(tx, organizationId) {
10
10
  const [policyRows, retainedRows, ownershipRows] = await Promise.all([
@@ -100,4 +100,4 @@ export async function clearRemoteResetPrincipalRows(input) {
100
100
  }
101
101
  }
102
102
  }
103
- //# sourceMappingURL=remoteResetPrincipalScope.js.map
103
+ //# sourceMappingURL=principalPolicyRemoteReset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalPolicyRemoteReset.js","sourceRoot":"","sources":["principalPolicyRemoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, or } from \"drizzle-orm\";\nimport {\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyCheckpoints,\n principalPolicyOrganizations,\n} from \"../../sqlite/schema\";\nimport {\n principalHistoryEntries,\n principalHistoryNodes,\n principalHistoryPrefixes,\n} from \"../../sqlite/schema/principalHistoryEvidenceSchema\";\nimport {\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n} from \"../../sqlite/schema/principalHistoryNodeRetentionSchema\";\nimport { principalKeyEnvelopeArchive } from \"../../sqlite/schema/principalHistoryRetentionSchema\";\nimport { principalHistoryStages } from \"../../sqlite/schema/principalHistoryStageSchema\";\nimport { remoteResetBatches } from \"../../sqlite/sqliteBindBudget\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\n\nexport interface RemoteResetPrincipalKey {\n readonly principalId: string;\n readonly principalType: \"group\" | \"organization\";\n}\n\ninterface PrincipalRow {\n readonly id: string;\n readonly type: string;\n}\n\n/** Current cache writes atomically pin ownership; reset never backfills it. */\nexport async function loadRemoteResetPrincipalScope(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<{\n readonly policyRows: readonly PrincipalRow[];\n readonly principalKeys: readonly RemoteResetPrincipalKey[];\n}> {\n const [policyRows, retainedRows, ownershipRows] = await Promise.all([\n tx\n .select({\n id: principalPolicies.principalId,\n type: principalPolicies.principalType,\n })\n .from(principalPolicies),\n Promise.all(\n [\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyCheckpoints,\n ].map((table) =>\n tx\n .selectDistinct({ id: table.principalId, type: table.principalType })\n .from(table),\n ),\n ),\n tx\n .select({\n organizationId: principalPolicyOrganizations.organizationId,\n principalId: principalPolicyOrganizations.principalId,\n principalType: principalPolicyOrganizations.principalType,\n })\n .from(principalPolicyOrganizations),\n ]);\n const owners = new Map(\n ownershipRows.map((row) => [\n `${row.principalType}\\0${row.principalId}`,\n row.organizationId,\n ]),\n );\n for (const row of [...policyRows, ...retainedRows.flat()]) {\n const owner = owners.get(`${row.type}\\0${row.id}`);\n if (row.type === \"group\" && !owner) {\n throw new Error(\n \"Unowned group policy cache requires a local database reset before organization purge\",\n );\n }\n if (row.type !== \"group\" && row.type !== \"organization\") {\n throw new Error(\"Principal policy cache has an invalid principal type\");\n }\n if (\n row.type === \"organization\" &&\n owner !== undefined &&\n owner !== row.id\n ) {\n throw new Error(\n \"Organization policy cache ownership does not match its identity\",\n );\n }\n }\n const keys = new Map<string, RemoteResetPrincipalKey>();\n keys.set(`organization\\0${organizationId}`, {\n principalId: organizationId,\n principalType: \"organization\",\n });\n for (const row of ownershipRows) {\n if (row.principalType !== \"group\" && row.principalType !== \"organization\") {\n throw new Error(\n \"Principal policy cache ownership has an invalid principal type\",\n );\n }\n if (!row.organizationId) {\n throw new Error(\n \"Principal policy cache ownership requires a local database reset\",\n );\n }\n if (row.organizationId !== organizationId) continue;\n keys.set(`${row.principalType}\\0${row.principalId}`, {\n principalId: row.principalId,\n principalType: row.principalType,\n });\n }\n return { policyRows, principalKeys: [...keys.values()] };\n}\n\n// Trust checkpoints and their ownership survive reset. Clearing cached bundles\n// must not turn a previously observed principal or object into first sight.\nexport async function clearRemoteResetPrincipalRows(input: {\n organizationId: string;\n snapshot: { principalKeys: readonly RemoteResetPrincipalKey[] };\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const table of [\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n principalHistoryEntries,\n principalHistoryNodes,\n principalHistoryPrefixes,\n principalKeyEnvelopeArchive,\n ])\n await input.tx\n .delete(table)\n .where(eq(table.organizationId, input.organizationId))\n .run();\n await input.tx\n .delete(principalHistoryStages)\n .where(eq(principalHistoryStages.organizationId, input.organizationId))\n .run();\n for (const principalBatch of remoteResetBatches(\n input.snapshot.principalKeys,\n )) {\n for (const table of [\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n ] as const) {\n await input.tx\n .delete(table)\n .where(\n or(\n ...principalBatch.map((principal) =>\n and(\n eq(table.principalType, principal.principalType),\n eq(table.principalId, principal.principalId),\n ),\n ),\n ),\n )\n .run();\n }\n }\n}\n"]}
@@ -43,3 +43,5 @@ export declare function writeVerifiedManifestBundlesInTransaction(tx: ClientSQLi
43
43
  export declare function loadVerifiedManifestCitations(execSql: ExecSql, target: WriterProjectionTarget, limit?: number): Promise<AccessManifestBundleWireResponse[]>;
44
44
  /** Cites from whichever database the signed-in identity currently uses. */
45
45
  export declare function createVerifiedManifestCitations(resolveExecSql: () => ExecSql | null): VerifiedManifestCitations;
46
+ /** Drops an organization's verified bundles when a remote reset forgets it. */
47
+ export declare function deleteVerifiedManifestBundlesForOrganization(tx: ClientSQLiteTransactionScope, organizationId: string): Promise<void>;
@@ -279,4 +279,11 @@ export function createVerifiedManifestCitations(resolveExecSql) {
279
279
  },
280
280
  };
281
281
  }
282
+ /** Drops an organization's verified bundles when a remote reset forgets it. */
283
+ export async function deleteVerifiedManifestBundlesForOrganization(tx, organizationId) {
284
+ await tx
285
+ .delete(bundles)
286
+ .where(eq(bundles.organizationId, organizationId))
287
+ .run();
288
+ }
282
289
  //# sourceMappingURL=verifiedManifestBundlePersistence.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verifiedManifestBundlePersistence.js","sourceRoot":"","sources":["verifiedManifestBundlePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n VerifiedManifestCitations,\n WriterProjectionTarget,\n} from \"@tearleads/api-client\";\nimport { toFingerprint } from \"@tearleads/crypto\";\nimport {\n type AccessManifestBundleWireResponse,\n isAccessManifestBundleWireResponse,\n} from \"@tearleads/validators/response\";\nimport {\n KNOWN_MANIFEST_HINT_LIMIT,\n MAX_CONTAINER_PATH_LENGTH,\n} from \"@tearleads/validators/util\";\nimport { and, asc, desc, eq, inArray, sql } from \"drizzle-orm\";\nimport {\n containerTables,\n documentContainerProjection,\n documentContainerProjectionTables,\n} from \"../sqlite/schema\";\nimport { containers } from \"../sqlite/schema/containerSchema\";\nimport {\n documentDiscoveryHeads,\n pendingDocumentDiscoveries,\n} from \"../sqlite/schema/documentDiscoveryEvidenceSchema\";\nimport {\n verifiedAccessManifestBundles as bundles,\n verifiedManifestBundleTables,\n} from \"../sqlite/schema/verifiedManifestBundleSchema\";\nimport {\n type ClientSQLiteDatabase,\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\n/**\n * Bounds local bytes (a bundle is ~10–20 KB). Evicting the least recently\n * verified rows only makes a later read carry those bundles again.\n */\nexport const MAX_VERIFIED_MANIFEST_BUNDLES = 1024;\nconst STATEMENT_BATCH = 200;\n\nexport interface VerifiedManifestBundle {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly checkpoint: {\n readonly objectKind: string;\n readonly organizationId: string;\n readonly objectId: string;\n readonly epoch: number;\n };\n}\n\nfunction sha256Hex(text: string): Promise<string> {\n return toFingerprint(new TextEncoder().encode(text));\n}\n\nfunction batches<T>(values: readonly T[]): T[][] {\n const result: T[][] = [];\n for (let index = 0; index < values.length; index += STATEMENT_BATCH)\n result.push(values.slice(index, index + STATEMENT_BATCH));\n return result;\n}\n\nasync function pruneInTransaction(\n tx: ClientSQLiteTransactionScope,\n): Promise<void> {\n const [row] = await tx.select({ count: sql<number>`count(*)` }).from(bundles);\n const excess = (row?.count ?? 0) - MAX_VERIFIED_MANIFEST_BUNDLES;\n if (excess <= 0) return;\n const evicted = await tx\n .select({ manifestHash: bundles.manifestHash })\n .from(bundles)\n .orderBy(asc(bundles.verifiedAt), asc(bundles.manifestHash))\n .limit(excess);\n for (const batch of batches(evicted.map((entry) => entry.manifestHash)))\n await tx.delete(bundles).where(inArray(bundles.manifestHash, batch)).run();\n}\n\n/** A verified bundle's exact JSON and that JSON's digest. */\nexport type VerifiedManifestBundleRow = Omit<\n typeof bundles.$inferInsert,\n \"verifiedAt\"\n>;\n\n/**\n * Prepares rows for bundles that just passed projection verification. The\n * digests are computed here, before the checkpoint transaction that writes\n * them begins.\n */\nexport function verifiedManifestBundleRows(\n entries: readonly VerifiedManifestBundle[],\n): Promise<VerifiedManifestBundleRow[]> {\n const unique = new Map(\n entries.map((entry) => [entry.bundle.manifestHash, entry]),\n );\n return Promise.all(\n [...unique.values()].map(async ({ bundle, checkpoint }) => {\n const bundleJson = JSON.stringify(bundle);\n return {\n manifestHash: bundle.manifestHash,\n organizationId: checkpoint.organizationId,\n objectKind: checkpoint.objectKind,\n objectId: checkpoint.objectId,\n epoch: checkpoint.epoch,\n bundleJson,\n bundleDigest: await sha256Hex(bundleJson),\n };\n }),\n );\n}\n\n/**\n * Records verified bundles inside the transaction that finalizes their\n * projection's checkpoints, so they commit or roll back with it and no cache\n * work outlives the verification. Freshly verified bytes replace any stored\n * copy.\n */\nexport async function writeVerifiedManifestBundlesInTransaction(\n tx: ClientSQLiteTransactionScope,\n rows: readonly VerifiedManifestBundleRow[],\n verifiedAt: string,\n): Promise<void> {\n if (rows.length === 0) return;\n const stored = await storedDigests(\n tx,\n rows.map((row) => row.manifestHash),\n );\n // An identical stored row only needs its recency refreshed.\n const unchanged = rows.filter(\n (row) => stored.get(row.manifestHash) === row.bundleDigest,\n );\n for (const batch of batches(unchanged.map((row) => row.manifestHash)))\n await tx\n .update(bundles)\n .set({ verifiedAt })\n .where(inArray(bundles.manifestHash, batch))\n .run();\n for (const row of rows) {\n if (stored.get(row.manifestHash) === row.bundleDigest) continue;\n const verified = { ...row, verifiedAt };\n await tx\n .insert(bundles)\n .values(verified)\n .onConflictDoUpdate({ target: bundles.manifestHash, set: verified })\n .run();\n }\n await pruneInTransaction(tx);\n}\n\nasync function storedDigests(\n tx: ClientSQLiteTransactionScope,\n manifestHashes: readonly string[],\n): Promise<Map<string, string>> {\n const digests = new Map<string, string>();\n for (const batch of batches(manifestHashes)) {\n const rows = await tx\n .select({\n bundleDigest: bundles.bundleDigest,\n manifestHash: bundles.manifestHash,\n })\n .from(bundles)\n .where(inArray(bundles.manifestHash, batch));\n for (const row of rows) digests.set(row.manifestHash, row.bundleDigest);\n }\n return digests;\n}\n\n/** The requested object first, then each container whose lineage it cites. */\nasync function containerLineage(\n db: ClientSQLiteDatabase,\n containerId: string,\n): Promise<string[]> {\n const lineage = [containerId];\n while (lineage.length < MAX_CONTAINER_PATH_LENGTH) {\n const [row] = await db\n .select({ parentId: containers.parentId })\n .from(containers)\n .where(eq(containers.id, lineage.at(-1) ?? \"\"))\n .limit(1);\n const parentId = row?.parentId;\n if (!parentId || lineage.includes(parentId)) break;\n lineage.push(parentId);\n }\n return lineage;\n}\n\nasync function citedObjects(\n db: ClientSQLiteDatabase,\n target: WriterProjectionTarget,\n): Promise<{ readonly kind: string; readonly id: string }[]> {\n if (target.kind === \"container\")\n return (await containerLineage(db, target.id)).map((id) => ({\n kind: \"container\",\n id,\n }));\n // Linked containers, containers listing the document before its signed\n // placement is checked, and a container whose metadata document it is.\n const placements = [\n ...(await db\n .select({ containerId: documentContainerProjection.containerId })\n .from(documentContainerProjection)\n .where(eq(documentContainerProjection.documentId, target.id))),\n ...(await db\n .select({ containerId: pendingDocumentDiscoveries.containerId })\n .from(pendingDocumentDiscoveries)\n .where(eq(pendingDocumentDiscoveries.documentId, target.id))),\n ...(await db\n .select({ containerId: containers.id })\n .from(containers)\n .where(eq(containers.metadataDocumentId, target.id))),\n ];\n const containerIds = new Set<string>();\n for (const { containerId } of placements)\n if (containerId)\n for (const id of await containerLineage(db, containerId))\n containerIds.add(id);\n return [\n { kind: \"document\", id: target.id },\n ...[...containerIds].map((id) => ({ kind: \"container\", id })),\n ];\n}\n\n/**\n * The one organization every local source places the read in. Verified\n * ownership (stored verified bundles of the target and of the containers on\n * its walk, and a document's verified discovery head) and local placement\n * (listed container rows reached through links, pending listings, metadata,\n * or parents) must all agree: any disagreement, or no source at all, yields\n * null, so the read is sent with no hints rather than another\n * organization's.\n */\nasync function targetOrganization(\n db: ClientSQLiteDatabase,\n target: WriterProjectionTarget,\n objects: readonly { readonly kind: string; readonly id: string }[],\n): Promise<string | null> {\n const containerIds = objects\n .filter((object) => object.kind === \"container\")\n .map((object) => object.id);\n const listed =\n containerIds.length === 0\n ? []\n : await db\n .select({ organizationId: containers.organizationId })\n .from(containers)\n .where(inArray(containers.id, containerIds));\n const verifiedContainers =\n containerIds.length === 0\n ? []\n : await db\n .select({ organizationId: bundles.organizationId })\n .from(bundles)\n .where(\n and(\n eq(bundles.objectKind, \"container\"),\n inArray(bundles.objectId, containerIds),\n ),\n );\n const verifiedTarget = await db\n .select({ organizationId: bundles.organizationId })\n .from(bundles)\n .where(\n and(eq(bundles.objectKind, target.kind), eq(bundles.objectId, target.id)),\n );\n const discovered =\n target.kind === \"document\"\n ? await db\n .select({ organizationId: documentDiscoveryHeads.organizationId })\n .from(documentDiscoveryHeads)\n .where(eq(documentDiscoveryHeads.documentId, target.id))\n : [];\n const sources = [listed, verifiedContainers, verifiedTarget, discovered];\n const organizations = new Set(\n sources.flat().map((row) => row.organizationId),\n );\n const [organizationId] = organizations;\n return organizations.size === 1 && organizationId ? organizationId : null;\n}\n\ninterface StoredBundleRow {\n readonly bundleDigest: string;\n readonly bundleJson: string;\n readonly manifestHash: string;\n}\n\nconst storedColumns = {\n bundleDigest: bundles.bundleDigest,\n bundleJson: bundles.bundleJson,\n manifestHash: bundles.manifestHash,\n};\n\nasync function readStoredBundle(\n row: StoredBundleRow,\n): Promise<AccessManifestBundleWireResponse | null> {\n if ((await sha256Hex(row.bundleJson)) !== row.bundleDigest) return null;\n try {\n const bundle: unknown = JSON.parse(row.bundleJson);\n return isAccessManifestBundleWireResponse(bundle) &&\n bundle.manifestHash === row.manifestHash\n ? bundle\n : null;\n } catch {\n return null;\n }\n}\n\nfunction objectRows(\n db: ClientSQLiteDatabase,\n organizationId: string,\n object: { readonly kind: string; readonly id: string },\n limit: number,\n) {\n return db\n .select(storedColumns)\n .from(bundles)\n .where(\n and(\n eq(bundles.organizationId, organizationId),\n eq(bundles.objectKind, object.kind),\n eq(bundles.objectId, object.id),\n ),\n )\n .orderBy(desc(bundles.epoch))\n .limit(limit);\n}\n\nfunction recentRows(\n db: ClientSQLiteDatabase,\n organizationId: string,\n limit: number,\n) {\n return db\n .select(storedColumns)\n .from(bundles)\n .where(eq(bundles.organizationId, organizationId))\n .orderBy(desc(bundles.verifiedAt), asc(bundles.manifestHash))\n .limit(limit);\n}\n\n/**\n * Verified bundles of the target's object and of the containers its\n * projection walks, newest epochs first; then the most recently verified rows\n * of its organization, since a just-verified parent is the likeliest part of\n * a new child's projection. Citations never leave the target's organization:\n * an object whose organization the device cannot place cites nothing.\n * Damaged rows are dropped.\n */\nexport async function loadVerifiedManifestCitations(\n execSql: ExecSql,\n target: WriterProjectionTarget,\n limit = KNOWN_MANIFEST_HINT_LIMIT,\n): Promise<AccessManifestBundleWireResponse[]> {\n await ensureSqlTables(execSql, [\n ...verifiedManifestBundleTables,\n ...containerTables,\n ...documentContainerProjectionTables,\n ]);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const cited = new Map<string, AccessManifestBundleWireResponse>();\n const damaged: string[] = [];\n const collect = async (rows: readonly StoredBundleRow[]) => {\n for (const row of rows) {\n if (cited.size >= limit || cited.has(row.manifestHash)) continue;\n const bundle = await readStoredBundle(row);\n if (bundle) cited.set(row.manifestHash, bundle);\n else damaged.push(row.manifestHash);\n }\n };\n const objects = await citedObjects(db, target);\n const organizationId = await targetOrganization(db, target, objects);\n if (organizationId === null) return [];\n for (const object of objects)\n if (cited.size < limit)\n await collect(\n await objectRows(db, organizationId, object, limit - cited.size),\n );\n if (cited.size < limit)\n await collect(await recentRows(db, organizationId, limit + cited.size));\n if (damaged.length > 0)\n await getClientSQLitePersistenceRuntime(execSql)\n .runMutation((handle) =>\n handle\n .delete(bundles)\n .where(inArray(bundles.manifestHash, damaged))\n .run(),\n )\n .catch(() => undefined);\n return [...cited.values()];\n}\n\n/** Cites from whichever database the signed-in identity currently uses. */\nexport function createVerifiedManifestCitations(\n resolveExecSql: () => ExecSql | null,\n): VerifiedManifestCitations {\n return {\n cite: async (target) => {\n const execSql = resolveExecSql();\n return execSql ? loadVerifiedManifestCitations(execSql, target) : [];\n },\n };\n}\n"]}
1
+ {"version":3,"file":"verifiedManifestBundlePersistence.js","sourceRoot":"","sources":["verifiedManifestBundlePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n VerifiedManifestCitations,\n WriterProjectionTarget,\n} from \"@tearleads/api-client\";\nimport { toFingerprint } from \"@tearleads/crypto\";\nimport {\n type AccessManifestBundleWireResponse,\n isAccessManifestBundleWireResponse,\n} from \"@tearleads/validators/response\";\nimport {\n KNOWN_MANIFEST_HINT_LIMIT,\n MAX_CONTAINER_PATH_LENGTH,\n} from \"@tearleads/validators/util\";\nimport { and, asc, desc, eq, inArray, sql } from \"drizzle-orm\";\nimport {\n containerTables,\n documentContainerProjection,\n documentContainerProjectionTables,\n} from \"../sqlite/schema\";\nimport { containers } from \"../sqlite/schema/containerSchema\";\nimport {\n documentDiscoveryHeads,\n pendingDocumentDiscoveries,\n} from \"../sqlite/schema/documentDiscoveryEvidenceSchema\";\nimport {\n verifiedAccessManifestBundles as bundles,\n verifiedManifestBundleTables,\n} from \"../sqlite/schema/verifiedManifestBundleSchema\";\nimport {\n type ClientSQLiteDatabase,\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\n/**\n * Bounds local bytes (a bundle is ~10–20 KB). Evicting the least recently\n * verified rows only makes a later read carry those bundles again.\n */\nexport const MAX_VERIFIED_MANIFEST_BUNDLES = 1024;\nconst STATEMENT_BATCH = 200;\n\nexport interface VerifiedManifestBundle {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly checkpoint: {\n readonly objectKind: string;\n readonly organizationId: string;\n readonly objectId: string;\n readonly epoch: number;\n };\n}\n\nfunction sha256Hex(text: string): Promise<string> {\n return toFingerprint(new TextEncoder().encode(text));\n}\n\nfunction batches<T>(values: readonly T[]): T[][] {\n const result: T[][] = [];\n for (let index = 0; index < values.length; index += STATEMENT_BATCH)\n result.push(values.slice(index, index + STATEMENT_BATCH));\n return result;\n}\n\nasync function pruneInTransaction(\n tx: ClientSQLiteTransactionScope,\n): Promise<void> {\n const [row] = await tx.select({ count: sql<number>`count(*)` }).from(bundles);\n const excess = (row?.count ?? 0) - MAX_VERIFIED_MANIFEST_BUNDLES;\n if (excess <= 0) return;\n const evicted = await tx\n .select({ manifestHash: bundles.manifestHash })\n .from(bundles)\n .orderBy(asc(bundles.verifiedAt), asc(bundles.manifestHash))\n .limit(excess);\n for (const batch of batches(evicted.map((entry) => entry.manifestHash)))\n await tx.delete(bundles).where(inArray(bundles.manifestHash, batch)).run();\n}\n\n/** A verified bundle's exact JSON and that JSON's digest. */\nexport type VerifiedManifestBundleRow = Omit<\n typeof bundles.$inferInsert,\n \"verifiedAt\"\n>;\n\n/**\n * Prepares rows for bundles that just passed projection verification. The\n * digests are computed here, before the checkpoint transaction that writes\n * them begins.\n */\nexport function verifiedManifestBundleRows(\n entries: readonly VerifiedManifestBundle[],\n): Promise<VerifiedManifestBundleRow[]> {\n const unique = new Map(\n entries.map((entry) => [entry.bundle.manifestHash, entry]),\n );\n return Promise.all(\n [...unique.values()].map(async ({ bundle, checkpoint }) => {\n const bundleJson = JSON.stringify(bundle);\n return {\n manifestHash: bundle.manifestHash,\n organizationId: checkpoint.organizationId,\n objectKind: checkpoint.objectKind,\n objectId: checkpoint.objectId,\n epoch: checkpoint.epoch,\n bundleJson,\n bundleDigest: await sha256Hex(bundleJson),\n };\n }),\n );\n}\n\n/**\n * Records verified bundles inside the transaction that finalizes their\n * projection's checkpoints, so they commit or roll back with it and no cache\n * work outlives the verification. Freshly verified bytes replace any stored\n * copy.\n */\nexport async function writeVerifiedManifestBundlesInTransaction(\n tx: ClientSQLiteTransactionScope,\n rows: readonly VerifiedManifestBundleRow[],\n verifiedAt: string,\n): Promise<void> {\n if (rows.length === 0) return;\n const stored = await storedDigests(\n tx,\n rows.map((row) => row.manifestHash),\n );\n // An identical stored row only needs its recency refreshed.\n const unchanged = rows.filter(\n (row) => stored.get(row.manifestHash) === row.bundleDigest,\n );\n for (const batch of batches(unchanged.map((row) => row.manifestHash)))\n await tx\n .update(bundles)\n .set({ verifiedAt })\n .where(inArray(bundles.manifestHash, batch))\n .run();\n for (const row of rows) {\n if (stored.get(row.manifestHash) === row.bundleDigest) continue;\n const verified = { ...row, verifiedAt };\n await tx\n .insert(bundles)\n .values(verified)\n .onConflictDoUpdate({ target: bundles.manifestHash, set: verified })\n .run();\n }\n await pruneInTransaction(tx);\n}\n\nasync function storedDigests(\n tx: ClientSQLiteTransactionScope,\n manifestHashes: readonly string[],\n): Promise<Map<string, string>> {\n const digests = new Map<string, string>();\n for (const batch of batches(manifestHashes)) {\n const rows = await tx\n .select({\n bundleDigest: bundles.bundleDigest,\n manifestHash: bundles.manifestHash,\n })\n .from(bundles)\n .where(inArray(bundles.manifestHash, batch));\n for (const row of rows) digests.set(row.manifestHash, row.bundleDigest);\n }\n return digests;\n}\n\n/** The requested object first, then each container whose lineage it cites. */\nasync function containerLineage(\n db: ClientSQLiteDatabase,\n containerId: string,\n): Promise<string[]> {\n const lineage = [containerId];\n while (lineage.length < MAX_CONTAINER_PATH_LENGTH) {\n const [row] = await db\n .select({ parentId: containers.parentId })\n .from(containers)\n .where(eq(containers.id, lineage.at(-1) ?? \"\"))\n .limit(1);\n const parentId = row?.parentId;\n if (!parentId || lineage.includes(parentId)) break;\n lineage.push(parentId);\n }\n return lineage;\n}\n\nasync function citedObjects(\n db: ClientSQLiteDatabase,\n target: WriterProjectionTarget,\n): Promise<{ readonly kind: string; readonly id: string }[]> {\n if (target.kind === \"container\")\n return (await containerLineage(db, target.id)).map((id) => ({\n kind: \"container\",\n id,\n }));\n // Linked containers, containers listing the document before its signed\n // placement is checked, and a container whose metadata document it is.\n const placements = [\n ...(await db\n .select({ containerId: documentContainerProjection.containerId })\n .from(documentContainerProjection)\n .where(eq(documentContainerProjection.documentId, target.id))),\n ...(await db\n .select({ containerId: pendingDocumentDiscoveries.containerId })\n .from(pendingDocumentDiscoveries)\n .where(eq(pendingDocumentDiscoveries.documentId, target.id))),\n ...(await db\n .select({ containerId: containers.id })\n .from(containers)\n .where(eq(containers.metadataDocumentId, target.id))),\n ];\n const containerIds = new Set<string>();\n for (const { containerId } of placements)\n if (containerId)\n for (const id of await containerLineage(db, containerId))\n containerIds.add(id);\n return [\n { kind: \"document\", id: target.id },\n ...[...containerIds].map((id) => ({ kind: \"container\", id })),\n ];\n}\n\n/**\n * The one organization every local source places the read in. Verified\n * ownership (stored verified bundles of the target and of the containers on\n * its walk, and a document's verified discovery head) and local placement\n * (listed container rows reached through links, pending listings, metadata,\n * or parents) must all agree: any disagreement, or no source at all, yields\n * null, so the read is sent with no hints rather than another\n * organization's.\n */\nasync function targetOrganization(\n db: ClientSQLiteDatabase,\n target: WriterProjectionTarget,\n objects: readonly { readonly kind: string; readonly id: string }[],\n): Promise<string | null> {\n const containerIds = objects\n .filter((object) => object.kind === \"container\")\n .map((object) => object.id);\n const listed =\n containerIds.length === 0\n ? []\n : await db\n .select({ organizationId: containers.organizationId })\n .from(containers)\n .where(inArray(containers.id, containerIds));\n const verifiedContainers =\n containerIds.length === 0\n ? []\n : await db\n .select({ organizationId: bundles.organizationId })\n .from(bundles)\n .where(\n and(\n eq(bundles.objectKind, \"container\"),\n inArray(bundles.objectId, containerIds),\n ),\n );\n const verifiedTarget = await db\n .select({ organizationId: bundles.organizationId })\n .from(bundles)\n .where(\n and(eq(bundles.objectKind, target.kind), eq(bundles.objectId, target.id)),\n );\n const discovered =\n target.kind === \"document\"\n ? await db\n .select({ organizationId: documentDiscoveryHeads.organizationId })\n .from(documentDiscoveryHeads)\n .where(eq(documentDiscoveryHeads.documentId, target.id))\n : [];\n const sources = [listed, verifiedContainers, verifiedTarget, discovered];\n const organizations = new Set(\n sources.flat().map((row) => row.organizationId),\n );\n const [organizationId] = organizations;\n return organizations.size === 1 && organizationId ? organizationId : null;\n}\n\ninterface StoredBundleRow {\n readonly bundleDigest: string;\n readonly bundleJson: string;\n readonly manifestHash: string;\n}\n\nconst storedColumns = {\n bundleDigest: bundles.bundleDigest,\n bundleJson: bundles.bundleJson,\n manifestHash: bundles.manifestHash,\n};\n\nasync function readStoredBundle(\n row: StoredBundleRow,\n): Promise<AccessManifestBundleWireResponse | null> {\n if ((await sha256Hex(row.bundleJson)) !== row.bundleDigest) return null;\n try {\n const bundle: unknown = JSON.parse(row.bundleJson);\n return isAccessManifestBundleWireResponse(bundle) &&\n bundle.manifestHash === row.manifestHash\n ? bundle\n : null;\n } catch {\n return null;\n }\n}\n\nfunction objectRows(\n db: ClientSQLiteDatabase,\n organizationId: string,\n object: { readonly kind: string; readonly id: string },\n limit: number,\n) {\n return db\n .select(storedColumns)\n .from(bundles)\n .where(\n and(\n eq(bundles.organizationId, organizationId),\n eq(bundles.objectKind, object.kind),\n eq(bundles.objectId, object.id),\n ),\n )\n .orderBy(desc(bundles.epoch))\n .limit(limit);\n}\n\nfunction recentRows(\n db: ClientSQLiteDatabase,\n organizationId: string,\n limit: number,\n) {\n return db\n .select(storedColumns)\n .from(bundles)\n .where(eq(bundles.organizationId, organizationId))\n .orderBy(desc(bundles.verifiedAt), asc(bundles.manifestHash))\n .limit(limit);\n}\n\n/**\n * Verified bundles of the target's object and of the containers its\n * projection walks, newest epochs first; then the most recently verified rows\n * of its organization, since a just-verified parent is the likeliest part of\n * a new child's projection. Citations never leave the target's organization:\n * an object whose organization the device cannot place cites nothing.\n * Damaged rows are dropped.\n */\nexport async function loadVerifiedManifestCitations(\n execSql: ExecSql,\n target: WriterProjectionTarget,\n limit = KNOWN_MANIFEST_HINT_LIMIT,\n): Promise<AccessManifestBundleWireResponse[]> {\n await ensureSqlTables(execSql, [\n ...verifiedManifestBundleTables,\n ...containerTables,\n ...documentContainerProjectionTables,\n ]);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const cited = new Map<string, AccessManifestBundleWireResponse>();\n const damaged: string[] = [];\n const collect = async (rows: readonly StoredBundleRow[]) => {\n for (const row of rows) {\n if (cited.size >= limit || cited.has(row.manifestHash)) continue;\n const bundle = await readStoredBundle(row);\n if (bundle) cited.set(row.manifestHash, bundle);\n else damaged.push(row.manifestHash);\n }\n };\n const objects = await citedObjects(db, target);\n const organizationId = await targetOrganization(db, target, objects);\n if (organizationId === null) return [];\n for (const object of objects)\n if (cited.size < limit)\n await collect(\n await objectRows(db, organizationId, object, limit - cited.size),\n );\n if (cited.size < limit)\n await collect(await recentRows(db, organizationId, limit + cited.size));\n if (damaged.length > 0)\n await getClientSQLitePersistenceRuntime(execSql)\n .runMutation((handle) =>\n handle\n .delete(bundles)\n .where(inArray(bundles.manifestHash, damaged))\n .run(),\n )\n .catch(() => undefined);\n return [...cited.values()];\n}\n\n/** Cites from whichever database the signed-in identity currently uses. */\nexport function createVerifiedManifestCitations(\n resolveExecSql: () => ExecSql | null,\n): VerifiedManifestCitations {\n return {\n cite: async (target) => {\n const execSql = resolveExecSql();\n return execSql ? loadVerifiedManifestCitations(execSql, target) : [];\n },\n };\n}\n\n/** Drops an organization's verified bundles when a remote reset forgets it. */\nexport async function deleteVerifiedManifestBundlesForOrganization(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<void> {\n await tx\n .delete(bundles)\n .where(eq(bundles.organizationId, organizationId))\n .run();\n}\n"]}
@@ -3,4 +3,4 @@ import { defineSqlTableSchema } from "../sqlTableSchema.js";
3
3
  /** Durable byte-reclamation queue populated before orphan attachment rows go. */
4
4
  export const documentOrphanBlobReclaims = sqliteTable("document_orphan_blob_reclaims", { storageKey: text("storage_key").primaryKey() });
5
5
  export const documentOrphanBlobReclaimTable = defineSqlTableSchema(documentOrphanBlobReclaims);
6
- //# sourceMappingURL=documentOrphanBlobReclaims.js.map
6
+ //# sourceMappingURL=documentOrphanBlobReclaimSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentOrphanBlobReclaimSchema.js","sourceRoot":"","sources":["documentOrphanBlobReclaimSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,iFAAiF;AACjF,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CACnD,+BAA+B,EAC/B,EAAE,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,UAAU,EAAE,EAAE,CACjD,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,oBAAoB,CAChE,0BAA0B,CAC3B,CAAC","sourcesContent":["import { sqliteTable, text } from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema } from \"../sqlTableSchema\";\n\n/** Durable byte-reclamation queue populated before orphan attachment rows go. */\nexport const documentOrphanBlobReclaims = sqliteTable(\n \"document_orphan_blob_reclaims\",\n { storageKey: text(\"storage_key\").primaryKey() },\n);\n\nexport const documentOrphanBlobReclaimTable = defineSqlTableSchema(\n documentOrphanBlobReclaims,\n);\n"]}
@@ -1,11 +1,11 @@
1
1
  import { sql } from "drizzle-orm";
2
2
  import { index, integer, primaryKey, sqliteTable, text, uniqueIndex, } from "drizzle-orm/sqlite-core";
3
- import { documentOrphanBlobReclaims, documentOrphanBlobReclaimTable, } from "../documentPersistence/documentOrphanBlobReclaims.js";
4
3
  import { defineSqlTableSchema } from "../sqlTableSchema.js";
5
4
  import { containerDocumentTombstoneHolds } from "./containerDocumentTombstoneHoldSchema.js";
6
5
  import { containerSQLiteSchema, containerTableSchemas, } from "./containerSchema.js";
7
6
  import { documentAttachmentBlobProjection, documentPendingAttachments, } from "./documentAttachmentSchema.js";
8
7
  import { documentDiscoveryHeads, documentDiscoverySequence, pendingDocumentDiscoveries, } from "./documentDiscoveryEvidenceSchema.js";
8
+ import { documentOrphanBlobReclaims, documentOrphanBlobReclaimTable, } from "./documentOrphanBlobReclaimSchema.js";
9
9
  import { documentIntentLinkTargets } from "./documentPlacementIntentSchema.js";
10
10
  import { localIntents } from "./localIntentSchema.js";
11
11
  import * as organizationDataUsage from "./organizationDataUsageSchema.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\nimport {\n documentOrphanBlobReclaims,\n documentOrphanBlobReclaimTable,\n} from \"../documentPersistence/documentOrphanBlobReclaims\";\nimport { defineSqlTableSchema, type SqlTableSchema } from \"../sqlTableSchema\";\nimport { containerDocumentTombstoneHolds } from \"./containerDocumentTombstoneHoldSchema\";\nimport {\n containerSQLiteSchema,\n containerTableSchemas,\n} from \"./containerSchema\";\nimport {\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n} from \"./documentAttachmentSchema\";\nimport {\n documentDiscoveryHeads,\n documentDiscoverySequence,\n pendingDocumentDiscoveries,\n} from \"./documentDiscoveryEvidenceSchema\";\nimport { documentIntentLinkTargets } from \"./documentPlacementIntentSchema\";\nimport { localIntents } from \"./localIntentSchema\";\nimport * as organizationDataUsage from \"./organizationDataUsageSchema\";\nimport { organizationFounders } from \"./organizationFounderSchema\";\nimport * as provisioningAttempt from \"./organizationProvisioningAttemptSchema\";\nimport {\n organizationReadModelSQLiteSchema,\n organizationReadModelTables,\n} from \"./organizationReadModelTableRegistry\";\nimport { principalGrantRetirements } from \"./principalGrantRetirementSchema\";\nimport {\n principalHistoryEntries,\n principalHistoryEvidenceTables,\n principalHistoryNodes,\n principalHistoryPrefixes,\n} from \"./principalHistoryEvidenceSchema\";\nimport {\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n} from \"./principalHistoryNodeRetentionSchema\";\nimport { principalKeyEnvelopeArchive } from \"./principalHistoryRetentionSchema\";\nimport {\n principalHistoryStages,\n principalHistoryStageTables,\n} from \"./principalHistoryStageSchema\";\nimport {\n principalMutationJournal,\n principalMutationJournalTables,\n} from \"./principalMutationJournalSchema\";\nimport {\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyCheckpoints,\n principalPolicyOrganizations,\n} from \"./principalPolicySchema\";\nimport {\n securityIncidents,\n securityIncidentTable,\n} from \"./securityIncidentSchema\";\nimport {\n verifiedAccessManifestBundles,\n verifiedManifestBundleTables,\n} from \"./verifiedManifestBundleSchema\";\n\nexport {\n containerHydrationTombstones,\n containers,\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n supersededContainerBindings,\n} from \"./containerSchema\";\nexport {\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n} from \"./documentAttachmentSchema\";\nexport {\n inContainerIntentLanes,\n inLocalIntentLane,\n LOCAL_INTENT_LANES,\n LOCAL_INTENT_SUBJECT,\n localIntents,\n} from \"./localIntentSchema\";\nexport {\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyCheckpoints,\n principalPolicyOrganizations,\n} from \"./principalPolicySchema\";\nexport { securityIncidents } from \"./securityIncidentSchema\";\nexport { containerDocumentTombstoneHolds, organizationReadModelTables };\n\nconst accessLevelColumn = \"effective_access_level\";\n\n/**\n * Durable Loro-backed document records shared by app features.\n *\n * This table stores encrypted document runtime state for multiple app domains.\n * `appKind` namespaces records for documents and container metadata. User-facing\n * list data is projected into feature-specific read models.\n *\n * Columns:\n * - `appKind`: Local domain namespace for the row, such as `documents` or\n * `container-metadata`.\n * - `localId`: Stable local id inside `appKind`. It may be created before a\n * server `documentId` exists.\n * - `documentId`: Server document id once the record is known remotely, or\n * `null` while the document is local-only.\n * - `accessEpoch`: Latest access epoch persisted for the document. Defaults to\n * the initial epoch.\n * - `accessStateHash`: Current document access/manifest state hash returned by\n * sync, when known.\n * - `lastCommitLsn`: Last remote commit cursor applied to this local document.\n * - `documentManifestBundle`: Serialized document manifest bundle used for\n * encrypted document sync.\n * - `contentKeyBundle`: Serialized content-key material needed to open the\n * local document.\n * - `documentKekTargets`: Serialized KEK target state for document key wraps.\n * - `pendingBaseVersion`: Encoded oplog version through which every persisted\n * op is already enqueued or synced. Persisted so a restart restores the\n * outgoing-delta marker instead of re-seeding it past a device-first\n * `deferRemoteSync` write's un-advanced op. `null` when unset.\n * - `snapshotEndVersion`: Encoded end version vector of the persisted content\n * (which lives in the durable-history tables, never on this row), written on\n * every content persist. Lets the pending-write queue's deferred-tail scan\n * compare version coverage without loading content. Empty string when the\n * document has never hydrated content, which readers treat as \"no deferred\n * tail claimable\".\n * - `recoveryGeneration`: Atomic raw-history recovery writer fence.\n * - `recoveryDocumentId`: Former server id for cross-client post-purge recreation.\n * - `pullContinuation`: Durable progress for the next bounded remote pull.\n * - `syncFailureStatus`, `syncFailureMessage`, `syncFailureAttemptedAt`: The\n * last terminal sync failure or quarantined incoming update for this scope.\n * The durable write queue (queued rows of `documentHistoryUpdates`) has no\n * status columns, so these let the write-queue view and footer explain why\n * the document is blocked. `syncFailureMessage` is non-null exactly when a\n * failure is recorded; a newer failure replaces the old, and a later fully\n * validated sync pass, a remote reset, or the scope's teardown clears all\n * three.\n * - `updatedAt`: Local timestamp for the last persisted runtime-state update.\n *\n * Indexes:\n * - `(appKind, localId)` is the primary key and scopes local document lookups.\n * - `(appKind, documentId) where documentId is not null` supports resolving a\n * server document id back to the local row during discovery and relinking.\n */\nexport const documents = sqliteTable(\n \"documents\",\n {\n appKind: text(\"app_kind\").notNull(),\n localId: text(\"local_id\").notNull(),\n documentId: text(\"document_id\"),\n accessEpoch: integer(\"access_epoch\").notNull().default(1),\n accessStateHash: text(\"access_state_hash\"),\n effectiveAccessLevel: text(accessLevelColumn).notNull().default(\"read\"),\n lastCommitLsn: text(\"last_commit_lsn\"),\n documentManifestBundle: text(\"document_manifest_bundle\"),\n contentKeyBundle: text(\"content_key_bundle\"),\n documentKekTargets: text(\"document_kek_targets\"),\n pendingBaseVersion: text(\"pending_base_version\"),\n pullContinuation: text(\"pull_continuation\"),\n recoveryGeneration: integer(\"recovery_generation\").notNull().default(0),\n recoveryDocumentId: text(\"recovery_document_id\"),\n snapshotEndVersion: text(\"snapshot_end_version\").notNull().default(\"\"),\n syncFailureStatus: integer(\"sync_failure_status\"),\n syncFailureMessage: text(\"sync_failure_message\"),\n syncFailureAttemptedAt: text(\"sync_failure_attempted_at\"),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.appKind, table.localId] }),\n index(\"documents_app_document_idx\")\n .on(table.appKind, table.documentId)\n .where(sql`${table.documentId} IS NOT NULL`),\n ],\n);\n\n/**\n * Full-history persistence for local documents (checkpoint + tail) — the ONLY\n * durable content source. Record rows in `documents` carry runtime metadata\n * and the content frontier (`snapshotEndVersion`), never content. The\n * checkpoint holds a full-history snapshot refreshed only at compaction, and\n * the tail appends every update (local deltas and decrypted remote updates)\n * written since. Restore = import checkpoint + replay tail; compaction =\n * export full history from the live doc, replace the checkpoint, clear the\n * tail — all bounded and amortized. Container metadata stores its content (an\n * exported-updates blob) as its checkpoint row, with no tail.\n */\nexport const documentHistoryCheckpoints = sqliteTable(\n \"document_history_checkpoints\",\n {\n appKind: text(\"app_kind\").notNull(),\n localId: text(\"local_id\").notNull(),\n snapshot: text(\"snapshot\").notNull(),\n endVersionVector: text(\"end_version_vector\").notNull(),\n revision: text(\"revision\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.appKind, table.localId] })],\n);\n\n/**\n * The local update log: one row per Loro update, serving as both the history\n * tail (restore = checkpoint + tail) and the outbound write queue.\n *\n * Every locally authored update is stored once. While it waits for sync it\n * carries an `updateId` (the id submitted to the server) and the version-vector\n * metadata the submission needs; settlement clears them, leaving the row as\n * ordinary tail history until compaction folds it into a checkpoint.\n *\n * Columns:\n * - `id`: Row id; tail compaction deletes by it.\n * - `appKind`, `localId`: Document scope matching `documents`.\n * - `updateData`: Serialized Loro update payload.\n * - `origin`: \"local\" (authored on this device) or \"remote\" (decrypted\n * pulled update) for tail rows. Restores use it to advance the\n * outgoing-delta marker across remote rows — their ops are already\n * server-side — while a local row left behind by a crash stays below the\n * marker so the next edit re-derives and sends it. \"outbox\" marks a queued\n * update with no tail role (container metadata, whose content is its\n * checkpoint, and full-state re-uploads after a remote reset); restores and\n * compaction never see it and settlement deletes it.\n * - `createdAt`: Insertion timestamp; with `rowid`, deterministic replay order.\n * - `updateId`: Present exactly while the row is queued for sync; rekeyed\n * after a lost acknowledgement poisons the submitted id.\n * - `partialStartVersionVector` / `partialEndVersionVector`: Version vectors\n * around a queued partial update.\n * - `sourceVersionVector`: Present on a queued rotation baseline checkpoint.\n * - `rekeyCount`: Durable bound on rekeys of a queued row.\n *\n * Invariant: compaction never deletes a queued row, so a checkpoint can cover\n * a queued update's operations without removing it from the queue.\n */\nexport const documentHistoryUpdates = sqliteTable(\n \"document_history_updates\",\n {\n id: text(\"id\"),\n appKind: text(\"app_kind\").notNull(),\n localId: text(\"local_id\").notNull(),\n updateData: text(\"update_data\").notNull(),\n origin: text(\"origin\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n updateId: text(\"update_id\"),\n partialStartVersionVector: text(\"partial_start_version_vector\"),\n partialEndVersionVector: text(\"partial_end_version_vector\"),\n sourceVersionVector: text(\"source_version_vector\"),\n rekeyCount: integer(\"rekey_count\").notNull().default(0),\n },\n (table) => [\n primaryKey({ columns: [table.id] }),\n index(\"document_history_updates_scope_created_idx\").on(\n table.appKind,\n table.localId,\n table.createdAt,\n ),\n uniqueIndex(\"document_history_updates_update_id_idx\")\n .on(table.updateId)\n .where(sql`${table.updateId} IS NOT NULL`),\n ],\n);\n\n/**\n * Anti-rollback pin for verified access manifests.\n *\n * Records the highest access-manifest epoch this client has verified for each\n * object, so a later projection that serves an older epoch (rollback) or a\n * conflicting manifest at the same epoch (equivocation) is detected before any\n * key is unwrapped. Updated monotonically after a projection verifies cleanly.\n *\n * Columns:\n * - `objectKind`: Access object kind (`container`, `document`, ...).\n * - `organizationId`: Organization boundary that owns the object.\n * - `objectId`: Stable object id.\n * - `epoch`: Highest verified manifest epoch.\n * - `manifestHash`: Manifest hash pinned at that epoch.\n * - `updatedAt`: Local timestamp for the pin.\n *\n * Indexes:\n * - `(objectKind, organizationId, objectId)` is the primary key and gives one\n * pin per object.\n */\nexport const accessManifestCheckpoints = sqliteTable(\n \"access_manifest_checkpoints\",\n {\n objectKind: text(\"object_kind\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n objectId: text(\"object_id\").notNull(),\n epoch: integer(\"epoch\").notNull(),\n manifestHash: text(\"manifest_hash\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n primaryKey({\n columns: [table.objectKind, table.organizationId, table.objectId],\n }),\n ],\n);\n\n/**\n * Durable terminal pins for documents whose signed purge proof was verified.\n * These survive remote-state resets so a dishonest API cannot later replay the\n * pre-purge writer projection and resurrect locally deleted content.\n */\nexport const documentPurgeCheckpoints = sqliteTable(\n \"document_purge_checkpoints\",\n {\n documentId: text(\"document_id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n documentManifestHash: text(\"document_manifest_hash\").notNull(),\n purgeEventHash: text(\"purge_event_hash\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n);\n\n/**\n * Durable trust-on-first-use pins for remote user identity bundles.\n *\n * The first validated identity observed for a user in a configured API trust\n * domain is inserted once. Later observations must match every suite, public\n * key, and fingerprint exactly; the persistence adapter never updates these\n * rows. `firstSeenAt` records when the local trust decision was made and is\n * likewise immutable.\n *\n * Indexes:\n * - `(identityTrustDomain, userId)` is the primary key and scopes a user pin to\n * the host-configured API authority that supplied it.\n * - `(identityTrustDomain, signingKeyFingerprint)` binds the reverse identity\n * mapping durably, including across session recreation. There is no\n * migration for a table that already violates it. Earlier builds pinned a\n * registration's user id before the server confirmed it, so a device that\n * ran one may hold two users on one key; deployments are greenfield, and\n * such a device clears its local data, which recreates this table empty. A\n * device that used an environment before a reset does the same (see\n * docs/developer/greenfield-reset.md).\n */\nexport const trustedUserIdentityPins = sqliteTable(\n \"trusted_user_identity_pins\",\n {\n identityTrustDomain: text(\"identity_trust_domain\").notNull(),\n userId: text(\"user_id\").notNull(),\n formatVersion: integer(\"format_version\").notNull(),\n signingSuite: text(\"signing_suite\").notNull(),\n signingPublicKey: text(\"signing_public_key\").notNull(),\n signingKeyFingerprint: text(\"signing_key_fingerprint\").notNull(),\n encapsulationSuite: text(\"encapsulation_suite\").notNull(),\n encapsulationPublicKey: text(\"encapsulation_public_key\").notNull(),\n encapsulationKeyFingerprint: text(\n \"encapsulation_key_fingerprint\",\n ).notNull(),\n firstSeenAt: text(\"first_seen_at\").notNull(),\n },\n (table) => [\n primaryKey({\n columns: [table.identityTrustDomain, table.userId],\n }),\n uniqueIndex(\"trusted_user_identity_pins_domain_signing_fingerprint_idx\").on(\n table.identityTrustDomain,\n table.signingKeyFingerprint,\n ),\n ],\n);\n\n/**\n * Local many-to-many projection between documents and containers.\n *\n * The document summary row stores one selected `containerId` for primary list\n * placement, while this table keeps the full set of linked containers returned\n * by container/document sync. Removing a container deletes its links and may\n * repair affected document summary rows to point at another remaining link.\n *\n * Columns:\n * - `documentId`: Server document id whose container links are projected.\n * - `containerId`: Linked container id.\n * - `updatedAt`: Local timestamp for the last replacement of the link set.\n *\n * Indexes:\n * - `(documentId, containerId)` is the primary key and prevents duplicate\n * links for the same document/container pair.\n */\nexport const documentContainerProjection = sqliteTable(\n \"document_container_projection\",\n {\n documentId: text(\"document_id\").notNull(),\n containerId: text(\"container_id\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.documentId, table.containerId] })],\n);\n\n/**\n * Queryable document summary and detail projection.\n *\n * The durable Loro state lives in `documents`. This table stores the fields the\n * app needs for document lists, summaries, and fast detail hydration without\n * opening the full Loro snapshot on every read.\n *\n * Columns:\n * - `localId`: Stable local document id. This joins to `documents.localId` for\n * rows where `documents.appKind = documents`.\n * - `documentId`: Server document id when known.\n * - `containerId`: Selected container for primary document placement, or\n * `null` if the document is not currently linked to a visible container.\n * - `organizationId`: Last-known owning organization. Stamped from the\n * container row when the document is detached because its container was\n * removed locally (e.g. access to a shared org was revoked and the container\n * tombstoned), so pending writes keep their org attribution after the\n * `containers` join source disappears. Read as a fallback only — a live\n * container join always wins.\n * - `documentKind`: Stored document kind. Defaults to `note`.\n * - `title`: Plain projected title. Defaults to the note fallback title.\n * - `updatedAt`: Timestamp used for document list ordering.\n *\n * The projected full text lives in `documentProjectionText`, keyed by the same\n * `localId`. Keeping it out of this row keeps list/window scans narrow: the\n * sidebar and summary queries read titles and placement from rows whose size\n * does not grow with document content.\n *\n * Indexes:\n * - `localId` is the primary key for document projection lookups.\n * - `(containerId) where containerId is not null` serves container-scoped\n * window/count scans without walking the whole table.\n * - `(organizationId) where containerId is null` serves the orphan-recovery\n * existence and window scans.\n * - `(documentId) where documentId is not null` serves the linked-placement\n * join from `documentContainerProjection` and server-id lookups.\n */\nexport const documentProjection = sqliteTable(\n \"document_projection\",\n {\n localId: text(\"local_id\"),\n documentId: text(\"document_id\"),\n containerId: text(\"container_id\"),\n organizationId: text(\"organization_id\"),\n documentKind: text(\"document_kind\").notNull().default(\"note\"),\n title: text(\"title\").notNull().default(\"Untitled note\"),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.localId] }),\n index(\"document_projection_container_idx\")\n .on(table.containerId)\n .where(sql`${table.containerId} IS NOT NULL`),\n index(\"document_projection_orphan_organization_idx\")\n .on(table.organizationId)\n .where(sql`${table.containerId} IS NULL`),\n index(\"document_projection_document_idx\")\n .on(table.documentId)\n .where(sql`${table.documentId} IS NOT NULL`),\n ],\n);\n\n/**\n * Projected document text, split from `documentProjection` so content size\n * never bloats the rows that list/window queries scan. Loaded only by detail\n * reads (`loadDocument`) and the save-timestamp change check.\n *\n * Columns:\n * - `localId`: Stable local document id, matching `documentProjection.localId`.\n * - `text`: Plain projected text used to rebuild summaries/details.\n */\nexport const documentProjectionText = sqliteTable(\n \"document_projection_text\",\n {\n localId: text(\"local_id\"),\n text: text(\"text\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.localId] })],\n);\n\n/**\n * Per-lane sync state for container data: the server cursor and the local\n * freshness marker share one row per lane.\n *\n * Container sync is split into lanes, such as a parent-container child lane or\n * a container-document membership lane. The cursor lets the next request\n * resume without replaying the entire tree. The freshness marker records the\n * last fully drained check independently of the cursor: empty server\n * responses do not always carry a new watermark, but startup still needs to\n * know that it recently checked the lane before polling again.\n *\n * Columns:\n * - `laneKind`: Sync lane category, such as `container_parent` or\n * `container_documents`.\n * - `laneId`: Lane identity. Root parent sync uses `root`, child sync uses a\n * parent-prefixed container id, and document lanes use the container id.\n * - `watermarkUpdatedAt`: Server `updatedAt` value for the stored watermark;\n * null until a watermark is saved.\n * - `watermarkId`: Server id tie-breaker for the stored watermark; null\n * exactly when `watermarkUpdatedAt` is.\n * - `updatedAt`: Local timestamp for when the cursor was saved.\n * - `checkedAt`: Local timestamp for the most recent fully drained lane check;\n * null until one completes.\n *\n * Indexes:\n * - `(laneKind, laneId)` is the primary key and stores one row per lane.\n */\nexport const containerSyncWatermarks = sqliteTable(\n \"container_sync_watermarks\",\n {\n laneKind: text(\"lane_kind\").notNull(),\n laneId: text(\"lane_id\").notNull(),\n watermarkUpdatedAt: text(\"watermark_updated_at\"),\n watermarkId: text(\"watermark_id\"),\n updatedAt: text(\"updated_at\"),\n checkedAt: text(\"checked_at\"),\n },\n (table) => [primaryKey({ columns: [table.laneKind, table.laneId] })],\n);\n\nexport const documentTables: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(documents),\n requiredColumns: [\n \"pull_continuation\",\n \"recovery_generation\",\n \"recovery_document_id\",\n \"sync_failure_status\",\n \"sync_failure_message\",\n \"sync_failure_attempted_at\",\n ],\n },\n defineSqlTableSchema(documentHistoryCheckpoints),\n {\n ...defineSqlTableSchema(documentHistoryUpdates),\n requiredColumns: [\"update_id\"],\n },\n];\n\nexport const principalPolicyTables: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(principalPolicies),\n requiredColumns: [\"current_grants_json\"],\n },\n {\n ...defineSqlTableSchema(principalPolicyBundleHistory),\n requiredColumns: [\"current_grants_json\"],\n },\n defineSqlTableSchema(principalPolicyBundleReferences),\n defineSqlTableSchema(principalPolicyOrganizations),\n ...principalHistoryStageTables,\n ...principalHistoryEvidenceTables,\n];\n\nexport const keyingCheckpointTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(organizationFounders),\n defineSqlTableSchema(accessManifestCheckpoints),\n defineSqlTableSchema(principalGrantRetirements),\n defineSqlTableSchema(documentPurgeCheckpoints),\n defineSqlTableSchema(principalPolicyCheckpoints),\n];\n\nexport const trustedUserIdentityPinTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(trustedUserIdentityPins),\n];\n\nconst securityIncidentTables: ReadonlyArray<SqlTableSchema> = [\n securityIncidentTable,\n];\n\nexport const containerTables = containerTableSchemas;\n\nexport const documentContainerProjectionTables: ReadonlyArray<SqlTableSchema> =\n [\n defineSqlTableSchema(documentContainerProjection),\n {\n ...defineSqlTableSchema(containerDocumentTombstoneHolds),\n requiredColumns: [\"hidden\"],\n },\n defineSqlTableSchema(pendingDocumentDiscoveries),\n {\n ...defineSqlTableSchema(documentDiscoveryHeads),\n requiredColumns: [\"organization_id\"],\n },\n defineSqlTableSchema(documentDiscoverySequence),\n ];\n\nexport const localIntentTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(localIntents),\n];\n\nexport const documentPlacementIntentTables: ReadonlyArray<SqlTableSchema> = [\n ...localIntentTables,\n defineSqlTableSchema(documentIntentLinkTargets),\n];\n\nexport const documentProjectionTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(documentProjection),\n defineSqlTableSchema(documentProjectionText),\n {\n ...defineSqlTableSchema(documentPendingAttachments),\n requiredColumns: [\"content_sha256\"],\n },\n {\n ...defineSqlTableSchema(documentAttachmentBlobProjection),\n requiredColumns: [\"content_sha256\"],\n },\n documentOrphanBlobReclaimTable,\n];\n\nexport const containerSyncWatermarkTables: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(containerSyncWatermarks),\n requiredColumns: [\"checked_at\"],\n },\n];\n\nexport const clientSqlTables: ReadonlyArray<SqlTableSchema> = [\n ...principalMutationJournalTables,\n ...documentTables,\n ...principalPolicyTables,\n ...keyingCheckpointTables,\n ...verifiedManifestBundleTables,\n ...trustedUserIdentityPinTables,\n ...securityIncidentTables,\n ...containerTables,\n ...documentContainerProjectionTables,\n ...documentPlacementIntentTables,\n ...documentProjectionTables,\n ...containerSyncWatermarkTables,\n ...organizationReadModelTables,\n ...organizationDataUsage.organizationDataUsageTables,\n ...provisioningAttempt.organizationProvisioningAttemptTables,\n];\n\nexport const clientSQLiteSchema = {\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n principalKeyEnvelopeArchive,\n principalMutationJournal,\n principalHistoryEntries,\n principalHistoryNodes,\n principalHistoryPrefixes,\n principalHistoryStages,\n organizationFounders,\n principalGrantRetirements,\n documents,\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyOrganizations,\n accessManifestCheckpoints,\n documentPurgeCheckpoints,\n principalPolicyCheckpoints,\n verifiedAccessManifestBundles,\n trustedUserIdentityPins,\n securityIncidents,\n ...containerSQLiteSchema,\n documentContainerProjection,\n localIntents,\n documentIntentLinkTargets,\n documentProjection,\n documentPendingAttachments,\n documentAttachmentBlobProjection,\n documentOrphanBlobReclaims: documentOrphanBlobReclaims,\n containerSyncWatermarks,\n ...organizationReadModelSQLiteSchema,\n ...organizationDataUsage.organizationDataUsageSQLiteSchema,\n ...provisioningAttempt.organizationProvisioningAttemptSQLiteSchema,\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema, type SqlTableSchema } from \"../sqlTableSchema\";\nimport { containerDocumentTombstoneHolds } from \"./containerDocumentTombstoneHoldSchema\";\nimport {\n containerSQLiteSchema,\n containerTableSchemas,\n} from \"./containerSchema\";\nimport {\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n} from \"./documentAttachmentSchema\";\nimport {\n documentDiscoveryHeads,\n documentDiscoverySequence,\n pendingDocumentDiscoveries,\n} from \"./documentDiscoveryEvidenceSchema\";\nimport {\n documentOrphanBlobReclaims,\n documentOrphanBlobReclaimTable,\n} from \"./documentOrphanBlobReclaimSchema\";\nimport { documentIntentLinkTargets } from \"./documentPlacementIntentSchema\";\nimport { localIntents } from \"./localIntentSchema\";\nimport * as organizationDataUsage from \"./organizationDataUsageSchema\";\nimport { organizationFounders } from \"./organizationFounderSchema\";\nimport * as provisioningAttempt from \"./organizationProvisioningAttemptSchema\";\nimport {\n organizationReadModelSQLiteSchema,\n organizationReadModelTables,\n} from \"./organizationReadModelTableRegistry\";\nimport { principalGrantRetirements } from \"./principalGrantRetirementSchema\";\nimport {\n principalHistoryEntries,\n principalHistoryEvidenceTables,\n principalHistoryNodes,\n principalHistoryPrefixes,\n} from \"./principalHistoryEvidenceSchema\";\nimport {\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n} from \"./principalHistoryNodeRetentionSchema\";\nimport { principalKeyEnvelopeArchive } from \"./principalHistoryRetentionSchema\";\nimport {\n principalHistoryStages,\n principalHistoryStageTables,\n} from \"./principalHistoryStageSchema\";\nimport {\n principalMutationJournal,\n principalMutationJournalTables,\n} from \"./principalMutationJournalSchema\";\nimport {\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyCheckpoints,\n principalPolicyOrganizations,\n} from \"./principalPolicySchema\";\nimport {\n securityIncidents,\n securityIncidentTable,\n} from \"./securityIncidentSchema\";\nimport {\n verifiedAccessManifestBundles,\n verifiedManifestBundleTables,\n} from \"./verifiedManifestBundleSchema\";\n\nexport {\n containerHydrationTombstones,\n containers,\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n supersededContainerBindings,\n} from \"./containerSchema\";\nexport {\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n} from \"./documentAttachmentSchema\";\nexport {\n inContainerIntentLanes,\n inLocalIntentLane,\n LOCAL_INTENT_LANES,\n LOCAL_INTENT_SUBJECT,\n localIntents,\n} from \"./localIntentSchema\";\nexport {\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyCheckpoints,\n principalPolicyOrganizations,\n} from \"./principalPolicySchema\";\nexport { securityIncidents } from \"./securityIncidentSchema\";\nexport { containerDocumentTombstoneHolds, organizationReadModelTables };\n\nconst accessLevelColumn = \"effective_access_level\";\n\n/**\n * Durable Loro-backed document records shared by app features.\n *\n * This table stores encrypted document runtime state for multiple app domains.\n * `appKind` namespaces records for documents and container metadata. User-facing\n * list data is projected into feature-specific read models.\n *\n * Columns:\n * - `appKind`: Local domain namespace for the row, such as `documents` or\n * `container-metadata`.\n * - `localId`: Stable local id inside `appKind`. It may be created before a\n * server `documentId` exists.\n * - `documentId`: Server document id once the record is known remotely, or\n * `null` while the document is local-only.\n * - `accessEpoch`: Latest access epoch persisted for the document. Defaults to\n * the initial epoch.\n * - `accessStateHash`: Current document access/manifest state hash returned by\n * sync, when known.\n * - `lastCommitLsn`: Last remote commit cursor applied to this local document.\n * - `documentManifestBundle`: Serialized document manifest bundle used for\n * encrypted document sync.\n * - `contentKeyBundle`: Serialized content-key material needed to open the\n * local document.\n * - `documentKekTargets`: Serialized KEK target state for document key wraps.\n * - `pendingBaseVersion`: Encoded oplog version through which every persisted\n * op is already enqueued or synced. Persisted so a restart restores the\n * outgoing-delta marker instead of re-seeding it past a device-first\n * `deferRemoteSync` write's un-advanced op. `null` when unset.\n * - `snapshotEndVersion`: Encoded end version vector of the persisted content\n * (which lives in the durable-history tables, never on this row), written on\n * every content persist. Lets the pending-write queue's deferred-tail scan\n * compare version coverage without loading content. Empty string when the\n * document has never hydrated content, which readers treat as \"no deferred\n * tail claimable\".\n * - `recoveryGeneration`: Atomic raw-history recovery writer fence.\n * - `recoveryDocumentId`: Former server id for cross-client post-purge recreation.\n * - `pullContinuation`: Durable progress for the next bounded remote pull.\n * - `syncFailureStatus`, `syncFailureMessage`, `syncFailureAttemptedAt`: The\n * last terminal sync failure or quarantined incoming update for this scope.\n * The durable write queue (queued rows of `documentHistoryUpdates`) has no\n * status columns, so these let the write-queue view and footer explain why\n * the document is blocked. `syncFailureMessage` is non-null exactly when a\n * failure is recorded; a newer failure replaces the old, and a later fully\n * validated sync pass, a remote reset, or the scope's teardown clears all\n * three.\n * - `updatedAt`: Local timestamp for the last persisted runtime-state update.\n *\n * Indexes:\n * - `(appKind, localId)` is the primary key and scopes local document lookups.\n * - `(appKind, documentId) where documentId is not null` supports resolving a\n * server document id back to the local row during discovery and relinking.\n */\nexport const documents = sqliteTable(\n \"documents\",\n {\n appKind: text(\"app_kind\").notNull(),\n localId: text(\"local_id\").notNull(),\n documentId: text(\"document_id\"),\n accessEpoch: integer(\"access_epoch\").notNull().default(1),\n accessStateHash: text(\"access_state_hash\"),\n effectiveAccessLevel: text(accessLevelColumn).notNull().default(\"read\"),\n lastCommitLsn: text(\"last_commit_lsn\"),\n documentManifestBundle: text(\"document_manifest_bundle\"),\n contentKeyBundle: text(\"content_key_bundle\"),\n documentKekTargets: text(\"document_kek_targets\"),\n pendingBaseVersion: text(\"pending_base_version\"),\n pullContinuation: text(\"pull_continuation\"),\n recoveryGeneration: integer(\"recovery_generation\").notNull().default(0),\n recoveryDocumentId: text(\"recovery_document_id\"),\n snapshotEndVersion: text(\"snapshot_end_version\").notNull().default(\"\"),\n syncFailureStatus: integer(\"sync_failure_status\"),\n syncFailureMessage: text(\"sync_failure_message\"),\n syncFailureAttemptedAt: text(\"sync_failure_attempted_at\"),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.appKind, table.localId] }),\n index(\"documents_app_document_idx\")\n .on(table.appKind, table.documentId)\n .where(sql`${table.documentId} IS NOT NULL`),\n ],\n);\n\n/**\n * Full-history persistence for local documents (checkpoint + tail) — the ONLY\n * durable content source. Record rows in `documents` carry runtime metadata\n * and the content frontier (`snapshotEndVersion`), never content. The\n * checkpoint holds a full-history snapshot refreshed only at compaction, and\n * the tail appends every update (local deltas and decrypted remote updates)\n * written since. Restore = import checkpoint + replay tail; compaction =\n * export full history from the live doc, replace the checkpoint, clear the\n * tail — all bounded and amortized. Container metadata stores its content (an\n * exported-updates blob) as its checkpoint row, with no tail.\n */\nexport const documentHistoryCheckpoints = sqliteTable(\n \"document_history_checkpoints\",\n {\n appKind: text(\"app_kind\").notNull(),\n localId: text(\"local_id\").notNull(),\n snapshot: text(\"snapshot\").notNull(),\n endVersionVector: text(\"end_version_vector\").notNull(),\n revision: text(\"revision\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.appKind, table.localId] })],\n);\n\n/**\n * The local update log: one row per Loro update, serving as both the history\n * tail (restore = checkpoint + tail) and the outbound write queue.\n *\n * Every locally authored update is stored once. While it waits for sync it\n * carries an `updateId` (the id submitted to the server) and the version-vector\n * metadata the submission needs; settlement clears them, leaving the row as\n * ordinary tail history until compaction folds it into a checkpoint.\n *\n * Columns:\n * - `id`: Row id; tail compaction deletes by it.\n * - `appKind`, `localId`: Document scope matching `documents`.\n * - `updateData`: Serialized Loro update payload.\n * - `origin`: \"local\" (authored on this device) or \"remote\" (decrypted\n * pulled update) for tail rows. Restores use it to advance the\n * outgoing-delta marker across remote rows — their ops are already\n * server-side — while a local row left behind by a crash stays below the\n * marker so the next edit re-derives and sends it. \"outbox\" marks a queued\n * update with no tail role (container metadata, whose content is its\n * checkpoint, and full-state re-uploads after a remote reset); restores and\n * compaction never see it and settlement deletes it.\n * - `createdAt`: Insertion timestamp; with `rowid`, deterministic replay order.\n * - `updateId`: Present exactly while the row is queued for sync; rekeyed\n * after a lost acknowledgement poisons the submitted id.\n * - `partialStartVersionVector` / `partialEndVersionVector`: Version vectors\n * around a queued partial update.\n * - `sourceVersionVector`: Present on a queued rotation baseline checkpoint.\n * - `rekeyCount`: Durable bound on rekeys of a queued row.\n *\n * Invariant: compaction never deletes a queued row, so a checkpoint can cover\n * a queued update's operations without removing it from the queue.\n */\nexport const documentHistoryUpdates = sqliteTable(\n \"document_history_updates\",\n {\n id: text(\"id\"),\n appKind: text(\"app_kind\").notNull(),\n localId: text(\"local_id\").notNull(),\n updateData: text(\"update_data\").notNull(),\n origin: text(\"origin\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n updateId: text(\"update_id\"),\n partialStartVersionVector: text(\"partial_start_version_vector\"),\n partialEndVersionVector: text(\"partial_end_version_vector\"),\n sourceVersionVector: text(\"source_version_vector\"),\n rekeyCount: integer(\"rekey_count\").notNull().default(0),\n },\n (table) => [\n primaryKey({ columns: [table.id] }),\n index(\"document_history_updates_scope_created_idx\").on(\n table.appKind,\n table.localId,\n table.createdAt,\n ),\n uniqueIndex(\"document_history_updates_update_id_idx\")\n .on(table.updateId)\n .where(sql`${table.updateId} IS NOT NULL`),\n ],\n);\n\n/**\n * Anti-rollback pin for verified access manifests.\n *\n * Records the highest access-manifest epoch this client has verified for each\n * object, so a later projection that serves an older epoch (rollback) or a\n * conflicting manifest at the same epoch (equivocation) is detected before any\n * key is unwrapped. Updated monotonically after a projection verifies cleanly.\n *\n * Columns:\n * - `objectKind`: Access object kind (`container`, `document`, ...).\n * - `organizationId`: Organization boundary that owns the object.\n * - `objectId`: Stable object id.\n * - `epoch`: Highest verified manifest epoch.\n * - `manifestHash`: Manifest hash pinned at that epoch.\n * - `updatedAt`: Local timestamp for the pin.\n *\n * Indexes:\n * - `(objectKind, organizationId, objectId)` is the primary key and gives one\n * pin per object.\n */\nexport const accessManifestCheckpoints = sqliteTable(\n \"access_manifest_checkpoints\",\n {\n objectKind: text(\"object_kind\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n objectId: text(\"object_id\").notNull(),\n epoch: integer(\"epoch\").notNull(),\n manifestHash: text(\"manifest_hash\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n primaryKey({\n columns: [table.objectKind, table.organizationId, table.objectId],\n }),\n ],\n);\n\n/**\n * Durable terminal pins for documents whose signed purge proof was verified.\n * These survive remote-state resets so a dishonest API cannot later replay the\n * pre-purge writer projection and resurrect locally deleted content.\n */\nexport const documentPurgeCheckpoints = sqliteTable(\n \"document_purge_checkpoints\",\n {\n documentId: text(\"document_id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n documentManifestHash: text(\"document_manifest_hash\").notNull(),\n purgeEventHash: text(\"purge_event_hash\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n);\n\n/**\n * Durable trust-on-first-use pins for remote user identity bundles.\n *\n * The first validated identity observed for a user in a configured API trust\n * domain is inserted once. Later observations must match every suite, public\n * key, and fingerprint exactly; the persistence adapter never updates these\n * rows. `firstSeenAt` records when the local trust decision was made and is\n * likewise immutable.\n *\n * Indexes:\n * - `(identityTrustDomain, userId)` is the primary key and scopes a user pin to\n * the host-configured API authority that supplied it.\n * - `(identityTrustDomain, signingKeyFingerprint)` binds the reverse identity\n * mapping durably, including across session recreation. There is no\n * migration for a table that already violates it. Earlier builds pinned a\n * registration's user id before the server confirmed it, so a device that\n * ran one may hold two users on one key; deployments are greenfield, and\n * such a device clears its local data, which recreates this table empty. A\n * device that used an environment before a reset does the same (see\n * docs/developer/greenfield-reset.md).\n */\nexport const trustedUserIdentityPins = sqliteTable(\n \"trusted_user_identity_pins\",\n {\n identityTrustDomain: text(\"identity_trust_domain\").notNull(),\n userId: text(\"user_id\").notNull(),\n formatVersion: integer(\"format_version\").notNull(),\n signingSuite: text(\"signing_suite\").notNull(),\n signingPublicKey: text(\"signing_public_key\").notNull(),\n signingKeyFingerprint: text(\"signing_key_fingerprint\").notNull(),\n encapsulationSuite: text(\"encapsulation_suite\").notNull(),\n encapsulationPublicKey: text(\"encapsulation_public_key\").notNull(),\n encapsulationKeyFingerprint: text(\n \"encapsulation_key_fingerprint\",\n ).notNull(),\n firstSeenAt: text(\"first_seen_at\").notNull(),\n },\n (table) => [\n primaryKey({\n columns: [table.identityTrustDomain, table.userId],\n }),\n uniqueIndex(\"trusted_user_identity_pins_domain_signing_fingerprint_idx\").on(\n table.identityTrustDomain,\n table.signingKeyFingerprint,\n ),\n ],\n);\n\n/**\n * Local many-to-many projection between documents and containers.\n *\n * The document summary row stores one selected `containerId` for primary list\n * placement, while this table keeps the full set of linked containers returned\n * by container/document sync. Removing a container deletes its links and may\n * repair affected document summary rows to point at another remaining link.\n *\n * Columns:\n * - `documentId`: Server document id whose container links are projected.\n * - `containerId`: Linked container id.\n * - `updatedAt`: Local timestamp for the last replacement of the link set.\n *\n * Indexes:\n * - `(documentId, containerId)` is the primary key and prevents duplicate\n * links for the same document/container pair.\n */\nexport const documentContainerProjection = sqliteTable(\n \"document_container_projection\",\n {\n documentId: text(\"document_id\").notNull(),\n containerId: text(\"container_id\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.documentId, table.containerId] })],\n);\n\n/**\n * Queryable document summary and detail projection.\n *\n * The durable Loro state lives in `documents`. This table stores the fields the\n * app needs for document lists, summaries, and fast detail hydration without\n * opening the full Loro snapshot on every read.\n *\n * Columns:\n * - `localId`: Stable local document id. This joins to `documents.localId` for\n * rows where `documents.appKind = documents`.\n * - `documentId`: Server document id when known.\n * - `containerId`: Selected container for primary document placement, or\n * `null` if the document is not currently linked to a visible container.\n * - `organizationId`: Last-known owning organization. Stamped from the\n * container row when the document is detached because its container was\n * removed locally (e.g. access to a shared org was revoked and the container\n * tombstoned), so pending writes keep their org attribution after the\n * `containers` join source disappears. Read as a fallback only — a live\n * container join always wins.\n * - `documentKind`: Stored document kind. Defaults to `note`.\n * - `title`: Plain projected title. Defaults to the note fallback title.\n * - `updatedAt`: Timestamp used for document list ordering.\n *\n * The projected full text lives in `documentProjectionText`, keyed by the same\n * `localId`. Keeping it out of this row keeps list/window scans narrow: the\n * sidebar and summary queries read titles and placement from rows whose size\n * does not grow with document content.\n *\n * Indexes:\n * - `localId` is the primary key for document projection lookups.\n * - `(containerId) where containerId is not null` serves container-scoped\n * window/count scans without walking the whole table.\n * - `(organizationId) where containerId is null` serves the orphan-recovery\n * existence and window scans.\n * - `(documentId) where documentId is not null` serves the linked-placement\n * join from `documentContainerProjection` and server-id lookups.\n */\nexport const documentProjection = sqliteTable(\n \"document_projection\",\n {\n localId: text(\"local_id\"),\n documentId: text(\"document_id\"),\n containerId: text(\"container_id\"),\n organizationId: text(\"organization_id\"),\n documentKind: text(\"document_kind\").notNull().default(\"note\"),\n title: text(\"title\").notNull().default(\"Untitled note\"),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.localId] }),\n index(\"document_projection_container_idx\")\n .on(table.containerId)\n .where(sql`${table.containerId} IS NOT NULL`),\n index(\"document_projection_orphan_organization_idx\")\n .on(table.organizationId)\n .where(sql`${table.containerId} IS NULL`),\n index(\"document_projection_document_idx\")\n .on(table.documentId)\n .where(sql`${table.documentId} IS NOT NULL`),\n ],\n);\n\n/**\n * Projected document text, split from `documentProjection` so content size\n * never bloats the rows that list/window queries scan. Loaded only by detail\n * reads (`loadDocument`) and the save-timestamp change check.\n *\n * Columns:\n * - `localId`: Stable local document id, matching `documentProjection.localId`.\n * - `text`: Plain projected text used to rebuild summaries/details.\n */\nexport const documentProjectionText = sqliteTable(\n \"document_projection_text\",\n {\n localId: text(\"local_id\"),\n text: text(\"text\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.localId] })],\n);\n\n/**\n * Per-lane sync state for container data: the server cursor and the local\n * freshness marker share one row per lane.\n *\n * Container sync is split into lanes, such as a parent-container child lane or\n * a container-document membership lane. The cursor lets the next request\n * resume without replaying the entire tree. The freshness marker records the\n * last fully drained check independently of the cursor: empty server\n * responses do not always carry a new watermark, but startup still needs to\n * know that it recently checked the lane before polling again.\n *\n * Columns:\n * - `laneKind`: Sync lane category, such as `container_parent` or\n * `container_documents`.\n * - `laneId`: Lane identity. Root parent sync uses `root`, child sync uses a\n * parent-prefixed container id, and document lanes use the container id.\n * - `watermarkUpdatedAt`: Server `updatedAt` value for the stored watermark;\n * null until a watermark is saved.\n * - `watermarkId`: Server id tie-breaker for the stored watermark; null\n * exactly when `watermarkUpdatedAt` is.\n * - `updatedAt`: Local timestamp for when the cursor was saved.\n * - `checkedAt`: Local timestamp for the most recent fully drained lane check;\n * null until one completes.\n *\n * Indexes:\n * - `(laneKind, laneId)` is the primary key and stores one row per lane.\n */\nexport const containerSyncWatermarks = sqliteTable(\n \"container_sync_watermarks\",\n {\n laneKind: text(\"lane_kind\").notNull(),\n laneId: text(\"lane_id\").notNull(),\n watermarkUpdatedAt: text(\"watermark_updated_at\"),\n watermarkId: text(\"watermark_id\"),\n updatedAt: text(\"updated_at\"),\n checkedAt: text(\"checked_at\"),\n },\n (table) => [primaryKey({ columns: [table.laneKind, table.laneId] })],\n);\n\nexport const documentTables: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(documents),\n requiredColumns: [\n \"pull_continuation\",\n \"recovery_generation\",\n \"recovery_document_id\",\n \"sync_failure_status\",\n \"sync_failure_message\",\n \"sync_failure_attempted_at\",\n ],\n },\n defineSqlTableSchema(documentHistoryCheckpoints),\n {\n ...defineSqlTableSchema(documentHistoryUpdates),\n requiredColumns: [\"update_id\"],\n },\n];\n\nexport const principalPolicyTables: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(principalPolicies),\n requiredColumns: [\"current_grants_json\"],\n },\n {\n ...defineSqlTableSchema(principalPolicyBundleHistory),\n requiredColumns: [\"current_grants_json\"],\n },\n defineSqlTableSchema(principalPolicyBundleReferences),\n defineSqlTableSchema(principalPolicyOrganizations),\n ...principalHistoryStageTables,\n ...principalHistoryEvidenceTables,\n];\n\nexport const keyingCheckpointTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(organizationFounders),\n defineSqlTableSchema(accessManifestCheckpoints),\n defineSqlTableSchema(principalGrantRetirements),\n defineSqlTableSchema(documentPurgeCheckpoints),\n defineSqlTableSchema(principalPolicyCheckpoints),\n];\n\nexport const trustedUserIdentityPinTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(trustedUserIdentityPins),\n];\n\nconst securityIncidentTables: ReadonlyArray<SqlTableSchema> = [\n securityIncidentTable,\n];\n\nexport const containerTables = containerTableSchemas;\n\nexport const documentContainerProjectionTables: ReadonlyArray<SqlTableSchema> =\n [\n defineSqlTableSchema(documentContainerProjection),\n {\n ...defineSqlTableSchema(containerDocumentTombstoneHolds),\n requiredColumns: [\"hidden\"],\n },\n defineSqlTableSchema(pendingDocumentDiscoveries),\n {\n ...defineSqlTableSchema(documentDiscoveryHeads),\n requiredColumns: [\"organization_id\"],\n },\n defineSqlTableSchema(documentDiscoverySequence),\n ];\n\nexport const localIntentTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(localIntents),\n];\n\nexport const documentPlacementIntentTables: ReadonlyArray<SqlTableSchema> = [\n ...localIntentTables,\n defineSqlTableSchema(documentIntentLinkTargets),\n];\n\nexport const documentProjectionTables: ReadonlyArray<SqlTableSchema> = [\n defineSqlTableSchema(documentProjection),\n defineSqlTableSchema(documentProjectionText),\n {\n ...defineSqlTableSchema(documentPendingAttachments),\n requiredColumns: [\"content_sha256\"],\n },\n {\n ...defineSqlTableSchema(documentAttachmentBlobProjection),\n requiredColumns: [\"content_sha256\"],\n },\n documentOrphanBlobReclaimTable,\n];\n\nexport const containerSyncWatermarkTables: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(containerSyncWatermarks),\n requiredColumns: [\"checked_at\"],\n },\n];\n\nexport const clientSqlTables: ReadonlyArray<SqlTableSchema> = [\n ...principalMutationJournalTables,\n ...documentTables,\n ...principalPolicyTables,\n ...keyingCheckpointTables,\n ...verifiedManifestBundleTables,\n ...trustedUserIdentityPinTables,\n ...securityIncidentTables,\n ...containerTables,\n ...documentContainerProjectionTables,\n ...documentPlacementIntentTables,\n ...documentProjectionTables,\n ...containerSyncWatermarkTables,\n ...organizationReadModelTables,\n ...organizationDataUsage.organizationDataUsageTables,\n ...provisioningAttempt.organizationProvisioningAttemptTables,\n];\n\nexport const clientSQLiteSchema = {\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n principalKeyEnvelopeArchive,\n principalMutationJournal,\n principalHistoryEntries,\n principalHistoryNodes,\n principalHistoryPrefixes,\n principalHistoryStages,\n organizationFounders,\n principalGrantRetirements,\n documents,\n principalPolicies,\n principalPolicyBundleHistory,\n principalPolicyBundleReferences,\n principalPolicyOrganizations,\n accessManifestCheckpoints,\n documentPurgeCheckpoints,\n principalPolicyCheckpoints,\n verifiedAccessManifestBundles,\n trustedUserIdentityPins,\n securityIncidents,\n ...containerSQLiteSchema,\n documentContainerProjection,\n localIntents,\n documentIntentLinkTargets,\n documentProjection,\n documentPendingAttachments,\n documentAttachmentBlobProjection,\n documentOrphanBlobReclaims: documentOrphanBlobReclaims,\n containerSyncWatermarks,\n ...organizationReadModelSQLiteSchema,\n ...organizationDataUsage.organizationDataUsageSQLiteSchema,\n ...provisioningAttempt.organizationProvisioningAttemptSQLiteSchema,\n};\n"]}
@@ -27,4 +27,16 @@ export function sqliteRowsPerStatement(variablesPerRow, fixedVariables = 0) {
27
27
  export function sqliteInsertBatchSize(table) {
28
28
  return sqliteRowsPerStatement(Object.keys(getTableColumns(table)).length);
29
29
  }
30
+ // Keep bulk inserts, IN predicates, and expanded pair predicates comfortably
31
+ // below SQLite's common 999-bind and expression-depth limits. Some queued rows
32
+ // consume more than ten binds each, so one conservative size covers every
33
+ // reset statement.
34
+ export const REMOTE_RESET_SQL_BATCH_SIZE = 50;
35
+ export function remoteResetBatches(values) {
36
+ const batches = [];
37
+ for (let offset = 0; offset < values.length; offset += REMOTE_RESET_SQL_BATCH_SIZE) {
38
+ batches.push(values.slice(offset, offset + REMOTE_RESET_SQL_BATCH_SIZE));
39
+ }
40
+ return batches;
41
+ }
30
42
  //# sourceMappingURL=sqliteBindBudget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqliteBindBudget.js","sourceRoot":"","sources":["sqliteBindBudget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,eAAuB,EACvB,cAAc,GAAG,CAAC;IAElB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,CAAC,4BAA4B,GAAG,cAAc,CAAC,GAAG,eAAe,CAClE,CAAC;IACF,IACE,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC;QAClC,eAAe,GAAG,CAAC;QACnB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;QACjC,cAAc,GAAG,CAAC;QAClB,IAAI,GAAG,CAAC,EACR,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["import { getTableColumns } from \"drizzle-orm\";\nimport type { SQLiteTable } from \"drizzle-orm/sqlite-core\";\n\n/**\n * SQLite's historical default `SQLITE_MAX_VARIABLE_NUMBER`. Some hosts raise\n * it, but the SDK runs on several SQLite builds, so every statement it batches\n * stays within this budget.\n */\nexport const SQLITE_BOUND_VARIABLE_BUDGET = 999;\n\n/**\n * Rows (or list entries) one statement may carry when each binds\n * `variablesPerRow` values on top of `fixedVariables` shared ones.\n */\nexport function sqliteRowsPerStatement(\n variablesPerRow: number,\n fixedVariables = 0,\n): number {\n const rows = Math.floor(\n (SQLITE_BOUND_VARIABLE_BUDGET - fixedVariables) / variablesPerRow,\n );\n if (\n !Number.isInteger(variablesPerRow) ||\n variablesPerRow < 1 ||\n !Number.isInteger(fixedVariables) ||\n fixedVariables < 0 ||\n rows < 1\n ) {\n throw new Error(\"SQLite statement cannot fit its bound variables\");\n }\n return rows;\n}\n\n/**\n * Rows per multi-row INSERT into `table`. Every column may bind one value,\n * including explicit nulls, so the column count is the per-row ceiling.\n */\nexport function sqliteInsertBatchSize(table: SQLiteTable): number {\n return sqliteRowsPerStatement(Object.keys(getTableColumns(table)).length);\n}\n"]}
1
+ {"version":3,"file":"sqliteBindBudget.js","sourceRoot":"","sources":["sqliteBindBudget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,eAAuB,EACvB,cAAc,GAAG,CAAC;IAElB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,CAAC,4BAA4B,GAAG,cAAc,CAAC,GAAG,eAAe,CAClE,CAAC;IACF,IACE,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC;QAClC,eAAe,GAAG,CAAC;QACnB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;QACjC,cAAc,GAAG,CAAC;QAClB,IAAI,GAAG,CAAC,EACR,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5E,CAAC;AAED,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,mBAAmB;AACnB,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,MAAM,UAAU,kBAAkB,CAChC,MAAoB;IAEpB,MAAM,OAAO,GAAU,EAAE,CAAC;IAC1B,KACE,IAAI,MAAM,GAAG,CAAC,EACd,MAAM,GAAG,MAAM,CAAC,MAAM,EACtB,MAAM,IAAI,2BAA2B,EACrC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,2BAA2B,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { getTableColumns } from \"drizzle-orm\";\nimport type { SQLiteTable } from \"drizzle-orm/sqlite-core\";\n\n/**\n * SQLite's historical default `SQLITE_MAX_VARIABLE_NUMBER`. Some hosts raise\n * it, but the SDK runs on several SQLite builds, so every statement it batches\n * stays within this budget.\n */\nexport const SQLITE_BOUND_VARIABLE_BUDGET = 999;\n\n/**\n * Rows (or list entries) one statement may carry when each binds\n * `variablesPerRow` values on top of `fixedVariables` shared ones.\n */\nexport function sqliteRowsPerStatement(\n variablesPerRow: number,\n fixedVariables = 0,\n): number {\n const rows = Math.floor(\n (SQLITE_BOUND_VARIABLE_BUDGET - fixedVariables) / variablesPerRow,\n );\n if (\n !Number.isInteger(variablesPerRow) ||\n variablesPerRow < 1 ||\n !Number.isInteger(fixedVariables) ||\n fixedVariables < 0 ||\n rows < 1\n ) {\n throw new Error(\"SQLite statement cannot fit its bound variables\");\n }\n return rows;\n}\n\n/**\n * Rows per multi-row INSERT into `table`. Every column may bind one value,\n * including explicit nulls, so the column count is the per-row ceiling.\n */\nexport function sqliteInsertBatchSize(table: SQLiteTable): number {\n return sqliteRowsPerStatement(Object.keys(getTableColumns(table)).length);\n}\n\n// Keep bulk inserts, IN predicates, and expanded pair predicates comfortably\n// below SQLite's common 999-bind and expression-depth limits. Some queued rows\n// consume more than ten binds each, so one conservative size covers every\n// reset statement.\nexport const REMOTE_RESET_SQL_BATCH_SIZE = 50;\n\nexport function remoteResetBatches<T>(\n values: readonly T[],\n): readonly (readonly T[])[] {\n const batches: T[][] = [];\n for (\n let offset = 0;\n offset < values.length;\n offset += REMOTE_RESET_SQL_BATCH_SIZE\n ) {\n batches.push(values.slice(offset, offset + REMOTE_RESET_SQL_BATCH_SIZE));\n }\n return batches;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tearleads/client-sdk",
3
- "version": "0.1.81",
3
+ "version": "0.1.84",
4
4
  "description": "React-free Tearleads client runtime: local SQLite persistence, keys, sync, encrypted blobs, and domain workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {