@tearleads/client-sdk 0.1.42 → 0.1.43

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 (161) hide show
  1. package/data/blobs/transferPool.js +35 -8
  2. package/data/blobs/transferPool.js.map +1 -1
  3. package/data/containers/shared/projection.js +12 -0
  4. package/data/containers/shared/projection.js.map +1 -1
  5. package/data/documents/blob/shared/types.d.ts +2 -3
  6. package/data/documents/blob/shared/types.js.map +1 -1
  7. package/data/documents/shared/events.js +0 -1
  8. package/data/documents/shared/events.js.map +1 -1
  9. package/data/persistence/container-contents/containerContentsPersistence.js +6 -22
  10. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  11. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +5 -15
  12. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  13. package/data/persistence/container-contents/containerPendingUpdatePersistence.js +6 -15
  14. package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerRecoveryPersistence.js +3 -4
  16. package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
  17. package/data/persistence/container-contents/containerRemovalWork.js +3 -5
  18. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  19. package/data/persistence/container-contents/dormantContainerMetadata.js +1 -5
  20. package/data/persistence/container-contents/dormantContainerMetadata.js.map +1 -1
  21. package/data/persistence/documents/documentsPersistence.js +4 -9
  22. package/data/persistence/documents/documentsPersistence.js.map +1 -1
  23. package/data/persistence/documents/internal/discardDocument.js +1 -2
  24. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  25. package/data/persistence/documents/internal/documentDeletionPersistence.js +1 -2
  26. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  27. package/data/persistence/documents/internal/documentMutationPersistence.js +17 -25
  28. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  29. package/data/persistence/documents/internal/orphanSideRows.js +2 -14
  30. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  31. package/data/persistence/documents/internal/syncQueuePersistence.js +3 -3
  32. package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
  33. package/data/sqlite/documentHistoryPersistence.d.ts +9 -3
  34. package/data/sqlite/documentHistoryPersistence.js +31 -8
  35. package/data/sqlite/documentHistoryPersistence.js.map +1 -1
  36. package/data/sqlite/documentPendingUpdatePersistence.d.ts +58 -11
  37. package/data/sqlite/documentPendingUpdatePersistence.js +137 -63
  38. package/data/sqlite/documentPendingUpdatePersistence.js.map +1 -1
  39. package/data/sqlite/documentPersistence.d.ts +1 -1
  40. package/data/sqlite/documentPersistence.js +1 -1
  41. package/data/sqlite/documentPersistence.js.map +1 -1
  42. package/data/sqlite/documentPersistenceTypes.d.ts +2 -2
  43. package/data/sqlite/documentPersistenceTypes.js.map +1 -1
  44. package/data/sqlite/documentRecordPersistence.js +5 -4
  45. package/data/sqlite/documentRecordPersistence.js.map +1 -1
  46. package/data/sqlite/schema.d.ts +127 -377
  47. package/data/sqlite/schema.js +46 -47
  48. package/data/sqlite/schema.js.map +1 -1
  49. package/internal/api-client/ApiClient.d.ts +13 -8
  50. package/internal/api-client/ApiClient.js +2 -5
  51. package/internal/api-client/ApiClient.js.map +1 -1
  52. package/internal/api-client/binaryRequestOperationTransport.d.ts +18 -0
  53. package/internal/api-client/index.d.ts +1 -0
  54. package/internal/api-client/index.js +1 -0
  55. package/internal/api-client/index.js.map +1 -1
  56. package/internal/api-client/operationTransportFactory.d.ts +6 -0
  57. package/internal/api-client/routes/blobs/get.d.ts +7 -0
  58. package/internal/api-client/routes/blobs/get.js.map +1 -1
  59. package/internal/api-client/routes/blobs/multipart.js +1 -11
  60. package/internal/api-client/routes/blobs/multipart.js.map +1 -1
  61. package/internal/api-client/routes/blobs/multipartUpload.d.ts +14 -0
  62. package/internal/api-client/routes/blobs/multipartUpload.js +94 -43
  63. package/internal/api-client/routes/blobs/multipartUpload.js.map +1 -1
  64. package/internal/validators/operation/attachments.d.ts +80 -160
  65. package/internal/validators/operation/auth.d.ts +760 -1664
  66. package/internal/validators/operation/blobDownloads.js +1 -1
  67. package/internal/validators/operation/blobDownloads.js.map +1 -1
  68. package/internal/validators/operation/containerMutations.d.ts +416 -856
  69. package/internal/validators/operation/documentMutations.d.ts +120 -264
  70. package/internal/validators/operation/documentSync.d.ts +40 -80
  71. package/internal/validators/operation/index.d.ts +1 -1
  72. package/internal/validators/operation/index.js +1 -1
  73. package/internal/validators/operation/index.js.map +1 -1
  74. package/internal/validators/operation/multipartBlobs.d.ts +70 -190
  75. package/internal/validators/operation/multipartBlobs.js +2 -24
  76. package/internal/validators/operation/multipartBlobs.js.map +1 -1
  77. package/internal/validators/operation/multipartPartUploads.d.ts +5 -5
  78. package/internal/validators/operation/multipartPartUploads.js +6 -20
  79. package/internal/validators/operation/multipartPartUploads.js.map +1 -1
  80. package/internal/validators/operation/organizations.d.ts +882 -1906
  81. package/internal/validators/operation/principals.d.ts +120 -240
  82. package/internal/validators/operation/registry.d.ts +1 -2
  83. package/internal/validators/operation/registry.js +1 -2
  84. package/internal/validators/operation/registry.js.map +1 -1
  85. package/internal/validators/request/blob.d.ts +100 -201
  86. package/internal/validators/request/blob.js +6 -13
  87. package/internal/validators/request/blob.js.map +1 -1
  88. package/internal/validators/request/container.d.ts +136 -272
  89. package/internal/validators/request/container.js +16 -10
  90. package/internal/validators/request/container.js.map +1 -1
  91. package/internal/validators/request/containerManifestRef.d.ts +54 -0
  92. package/internal/validators/request/containerManifestRef.js +28 -0
  93. package/internal/validators/request/containerManifestRef.js.map +1 -0
  94. package/internal/validators/request/containerMetadata.d.ts +160 -368
  95. package/internal/validators/request/document.d.ts +100 -245
  96. package/internal/validators/request/document.js +1 -2
  97. package/internal/validators/request/document.js.map +1 -1
  98. package/internal/validators/request/documentSyncSchema.d.ts +42 -109
  99. package/internal/validators/request/documentSyncSchema.js +8 -25
  100. package/internal/validators/request/documentSyncSchema.js.map +1 -1
  101. package/internal/validators/request/index.d.ts +1 -1
  102. package/internal/validators/request/index.js +1 -1
  103. package/internal/validators/request/index.js.map +1 -1
  104. package/internal/validators/request/organization.d.ts +160 -320
  105. package/internal/validators/request/organizationProvisioning.d.ts +2424 -5312
  106. package/internal/validators/request/principal.d.ts +160 -320
  107. package/internal/validators/request/registration.d.ts +760 -1664
  108. package/internal/validators/response/blob.d.ts +48 -27
  109. package/internal/validators/response/blob.js +3 -10
  110. package/internal/validators/response/blob.js.map +1 -1
  111. package/internal/validators/response/index.d.ts +1 -1
  112. package/internal/validators/response/index.js +1 -1
  113. package/internal/validators/response/index.js.map +1 -1
  114. package/internal/validators/util/blob.d.ts +7 -0
  115. package/internal/validators/util/blob.js +7 -0
  116. package/internal/validators/util/blob.js.map +1 -1
  117. package/internal/validators/util/blobTransferSchemas.d.ts +41 -0
  118. package/internal/validators/util/blobTransferSchemas.js +39 -0
  119. package/internal/validators/util/blobTransferSchemas.js.map +1 -0
  120. package/internal/validators/util/containerLimits.d.ts +7 -0
  121. package/internal/validators/util/containerLimits.js +7 -0
  122. package/internal/validators/util/containerLimits.js.map +1 -1
  123. package/internal/validators/util/index.d.ts +2 -1
  124. package/internal/validators/util/index.js +2 -1
  125. package/internal/validators/util/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/workflows/blobs/multipartFirstParts.js +82 -0
  128. package/workflows/blobs/multipartFirstParts.js.map +1 -0
  129. package/workflows/blobs/multipartStageResolution.js +83 -0
  130. package/workflows/blobs/multipartStageResolution.js.map +1 -0
  131. package/workflows/blobs/multipartUpload.js +45 -89
  132. package/workflows/blobs/multipartUpload.js.map +1 -1
  133. package/workflows/container-contents/documentPriming.js +2 -1
  134. package/workflows/container-contents/documentPriming.js.map +1 -1
  135. package/workflows/container-contents/documentQueries/sql.js +4 -4
  136. package/workflows/container-contents/documentQueries/sql.js.map +1 -1
  137. package/workflows/container-contents/pendingWrites/deferredTails.js +6 -3
  138. package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
  139. package/workflows/container-contents/pendingWrites/sources.js +2 -1
  140. package/workflows/container-contents/pendingWrites/sources.js.map +1 -1
  141. package/workflows/container-contents/pendingWrites.js +2 -1
  142. package/workflows/container-contents/pendingWrites.js.map +1 -1
  143. package/workflows/containers/child/create.js +3 -3
  144. package/workflows/containers/child/create.js.map +1 -1
  145. package/workflows/containers/child/move.js +2 -2
  146. package/workflows/containers/child/move.js.map +1 -1
  147. package/workflows/containers/child/mutationRequestCore.js +5 -4
  148. package/workflows/containers/child/mutationRequestCore.js.map +1 -1
  149. package/workflows/containers/child/recitePlan.js +3 -2
  150. package/workflows/containers/child/recitePlan.js.map +1 -1
  151. package/workflows/containers/child/sharePlanCore.js +2 -2
  152. package/workflows/containers/child/sharePlanCore.js.map +1 -1
  153. package/workflows/containers/root/create.js +2 -2
  154. package/workflows/containers/root/create.js.map +1 -1
  155. package/workflows/registration/provisioningBootstrapBuilders.d.ts +20 -46
  156. package/workflows/sync/remoteReset.js +9 -9
  157. package/workflows/sync/remoteReset.js.map +1 -1
  158. package/workflows/sync/remoteResetPlans.js +6 -3
  159. package/workflows/sync/remoteResetPlans.js.map +1 -1
  160. package/internal/validators/operation/blobTransferSchemas.js +0 -11
  161. package/internal/validators/operation/blobTransferSchemas.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"documentPriming.js","sourceRoot":"","sources":["documentPriming.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n documentContainerProjectionTables,\n documentMoveIntentTables,\n documentProjectionTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerDocumentPrimeHost,\n ContainerDocumentQueriesRuntime,\n} from \"./documentQueries/types\";\nimport { requestDocumentRuntimeTargetSync } from \"./documentRuntimeTargetSync\";\nimport { listDocumentRuntimeTargetsForContainerSubtreeFromRuntime } from \"./documentSubtreeQueries\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\n\ninterface PrimeRequiredDocumentCandidate {\n readonly localId: string;\n}\n\ninterface LoadedRootDocumentPrimeResult {\n readonly candidateCount: number;\n readonly orphanPrimedCount: number;\n readonly primedCount: number;\n readonly rootCount: number;\n readonly unroutableCount: number;\n}\n\n// Documents that still NEED a store opened at prime time: local-only creates,\n// queued outbound updates/attachments, an outgoing-delta marker behind the\n// stored content frontier (a deferred tail; encoding inequality\n// over-approximates, which only re-primes a store the old behavior always\n// primed), a never-hydrated document (a freshly discovered share whose\n// content pull the primed lane performs), or a document with a recorded sync\n// failure (a refused revalidation leaves no queued work, so the failure row\n// is the only ticket that re-drives the store — the retry that clears on the\n// next clean pass). Fully-synced hydrated documents are\n// deliberately absent: priming exists to re-drive durable work, and opening a\n// store per settled document is what made a 1000-document boot a storm.\nconst PENDING_PRIME_LOCAL_ID_SQL = `\n SELECT stored.local_id AS local_id\n FROM documents stored\n WHERE stored.app_kind = 'documents'\n AND (\n stored.document_id IS NULL\n OR stored.snapshot_end_version = ''\n OR stored.pull_continuation IS NOT NULL\n OR COALESCE(stored.pending_base_version, '') <> stored.snapshot_end_version\n OR EXISTS (\n SELECT 1\n FROM document_pending_updates pending\n WHERE pending.app_kind = 'documents'\n AND pending.local_id = stored.local_id\n )\n OR EXISTS (\n SELECT 1\n FROM document_sync_failures failure\n WHERE failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n )\n OR EXISTS (\n SELECT 1\n FROM document_pending_attachments attachment\n WHERE attachment.local_id = stored.local_id\n )\n )\n`;\n\nconst PENDING_PRIME_DOCUMENT_CANDIDATE_SQL = `\n SELECT pending.local_id AS local_id\n FROM (${PENDING_PRIME_LOCAL_ID_SQL}) pending\n ORDER BY pending.local_id ASC\n`;\n\n// The structural startup probe and the priming worker share the same durable\n// predicate so they cannot disagree about what counts as document work.\nconst STARTUP_DOCUMENT_SYNC_WORK_SQL = `\n SELECT 1 AS present\n WHERE EXISTS (${PENDING_PRIME_LOCAL_ID_SQL})\n OR EXISTS (\n SELECT 1\n FROM document_move_intents intent\n -- Blocked and parked denied moves count: blocked intents replay on\n -- every scan (the blocking condition can heal after hydration), and\n -- the once-per-launch replay makes denied moves retriable — so a\n -- relaunch whose only durable work is either kind must still schedule\n -- the structural pass that re-attempts it (row 7). Unavailable moves\n -- are excluded: no pass ever replays them (#2278 #4).\n WHERE intent.sync_status IN ('pending', 'blocked', 'denied')\n )\n LIMIT 1\n`;\n\nexport async function hasStartupDocumentSyncWork(\n runtimeOrExecSql:\n | ContainerDocumentQueriesRuntime\n | ContainerDocumentQueriesRuntime[\"infra\"][\"execSql\"],\n): Promise<boolean> {\n const execSql =\n typeof runtimeOrExecSql === \"function\"\n ? runtimeOrExecSql\n : runtimeOrExecSql.infra.execSql;\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(STARTUP_DOCUMENT_SYNC_WORK_SQL);\n return rows.length > 0;\n}\n\nasync function listPrimeRequiredDocumentCandidatesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<PrimeRequiredDocumentCandidate[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n PENDING_PRIME_DOCUMENT_CANDIDATE_SQL,\n );\n\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n return [{ localId }];\n });\n}\n\n// A row with content but a NULL outgoing-delta marker is deliberately treated\n// as unsettled: the store persist path always sets the marker, so over-priming\n// is the safe direction.\nasync function listPrimeRequiredLocalIdsFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<ReadonlySet<string>> {\n const candidates =\n await listPrimeRequiredDocumentCandidatesFromRuntime(runtime);\n return new Set(candidates.map((candidate) => candidate.localId));\n}\n\n/**\n * Last-link orphans (docs/sync-edge-cases.md row 3): the container cascade\n * nulled their projection container and dropped their link rows, so no\n * subtree listing can route them. Placements held for unsigned tombstones\n * also qualify when every link is hidden; their link rows remain intact.\n * These documents are primed with a null container\n * scope instead — the documents runtime accepts one, and the document's own\n * sync pass then resolves its fate against the server: 403 parks it (row 8),\n * a coded 404 destroys it (row 1), and a local-only orphan's create attempt\n * records a terminal failure row. Hidden document kinds stay excluded, and\n * dangling non-null projections (a container row merely missing locally)\n * stay with stale-root recovery, exactly as before.\n *\n * Organization neutrality: the null scope changes only the runtime's\n * containerId — auth, crypto, and organization plumbing are identical to\n * every container-scoped runtime this store already primes with, the sync\n * pass derives billing and keying organizations from the document's own\n * plan and manifest, and a cross-organization author fails closed at the\n * sync layer's identity guard before anything is signed.\n */\nconst ORPHANED_PRIME_TARGET_SQL = `\n SELECT stored.local_id AS local_id, stored.document_id AS document_id\n FROM documents stored\n INNER JOIN document_projection projection\n ON projection.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"stored.document_id\",\n projectionAlias: \"projection\",\n })}\n ORDER BY stored.local_id ASC\n`;\n\n/**\n * Unattributed rows (empty/NULL organization) are always included: they are\n * device-first documents created before authentication, which belong to this\n * device's sole user and adopt the active organization when they create.\n */\nasync function listOrphanedDocumentPrimeTargets(\n runtime: ContainerDocumentQueriesRuntime,\n organizationId: string,\n): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentContainerProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n ORPHANED_PRIME_TARGET_SQL,\n getOrphanedDocumentQueryBind(organizationId),\n );\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n const documentId = Reflect.get(row, \"document_id\");\n return [\n {\n documentId: typeof documentId === \"string\" ? documentId : null,\n localId,\n runtimeContainerId: null,\n },\n ];\n });\n}\n\nexport async function primeDocumentsForContainerSubtree<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n primeRequiredLocalIds?: ReadonlySet<string>;\n rootContainerId: string;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<number> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) return 0;\n const [targets, primeRequiredLocalIds] = await Promise.all([\n listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId: input.rootContainerId,\n runtime: input.runtime,\n }),\n input.primeRequiredLocalIds ??\n listPrimeRequiredLocalIdsFromRuntime(input.runtime),\n ]);\n if (!isCurrent()) return 0;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter((target) =>\n primeRequiredLocalIds.has(target.localId),\n ),\n });\n return primed.size;\n}\n\nexport async function primeDocumentsForLoadedRoots<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n /**\n * The store scope's organization. Orphan priming is bounded to it: each\n * organization-scoped store resolves only its own orphans, matching the\n * per-organization invariant subtree routing provides implicitly (a pass\n * signed under another organization would fail the sync identity guard\n * instead of resolving). Absent — unauthenticated or scope-less callers —\n * orphan priming is skipped entirely.\n */\n organizationId?: string | null;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<LoadedRootDocumentPrimeResult> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) {\n return {\n candidateCount: 0,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: 0,\n };\n }\n const candidates = await listPrimeRequiredDocumentCandidatesFromRuntime(\n input.runtime,\n );\n if (!isCurrent()) {\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: candidates.length,\n };\n }\n const rootContainerIds = Array.from(input.containersById.values()).flatMap(\n (containerState) =>\n containerState.container.parentId === null\n ? [containerState.container.id]\n : [],\n );\n const requiredLocalIds = new Set(\n candidates.map((candidate) => candidate.localId),\n );\n const primedLocalIds = new Set<string>();\n\n for (const rootContainerId of rootContainerIds) {\n if (!isCurrent()) break;\n const targets =\n await listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId,\n runtime: input.runtime,\n });\n if (!isCurrent()) break;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n ),\n });\n for (const localId of primed) {\n primedLocalIds.add(localId);\n }\n }\n\n const orphanTargets = (\n isCurrent() && input.organizationId\n ? await listOrphanedDocumentPrimeTargets(\n input.runtime,\n input.organizationId,\n )\n : []\n ).filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n );\n const orphanPrimed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: isCurrent() ? orphanTargets : [],\n });\n for (const localId of orphanPrimed) {\n primedLocalIds.add(localId);\n }\n\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: orphanPrimed.size,\n primedCount: primedLocalIds.size,\n rootCount: rootContainerIds.length,\n unroutableCount: candidates.filter(\n (candidate) => !primedLocalIds.has(candidate.localId),\n ).length,\n };\n}\n"]}
1
+ {"version":3,"file":"documentPriming.js","sourceRoot":"","sources":["documentPriming.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n documentContainerProjectionTables,\n documentMoveIntentTables,\n documentProjectionTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerDocumentPrimeHost,\n ContainerDocumentQueriesRuntime,\n} from \"./documentQueries/types\";\nimport { requestDocumentRuntimeTargetSync } from \"./documentRuntimeTargetSync\";\nimport { listDocumentRuntimeTargetsForContainerSubtreeFromRuntime } from \"./documentSubtreeQueries\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\n\ninterface PrimeRequiredDocumentCandidate {\n readonly localId: string;\n}\n\ninterface LoadedRootDocumentPrimeResult {\n readonly candidateCount: number;\n readonly orphanPrimedCount: number;\n readonly primedCount: number;\n readonly rootCount: number;\n readonly unroutableCount: number;\n}\n\n// Documents that still NEED a store opened at prime time: local-only creates,\n// queued outbound updates/attachments, an outgoing-delta marker behind the\n// stored content frontier (a deferred tail; encoding inequality\n// over-approximates, which only re-primes a store the old behavior always\n// primed), a never-hydrated document (a freshly discovered share whose\n// content pull the primed lane performs), or a document with a recorded sync\n// failure (a refused revalidation leaves no queued work, so the failure row\n// is the only ticket that re-drives the store — the retry that clears on the\n// next clean pass). Fully-synced hydrated documents are\n// deliberately absent: priming exists to re-drive durable work, and opening a\n// store per settled document is what made a 1000-document boot a storm.\nconst PENDING_PRIME_LOCAL_ID_SQL = `\n SELECT stored.local_id AS local_id\n FROM documents stored\n WHERE stored.app_kind = 'documents'\n AND (\n stored.document_id IS NULL\n OR stored.snapshot_end_version = ''\n OR stored.pull_continuation IS NOT NULL\n OR COALESCE(stored.pending_base_version, '') <> stored.snapshot_end_version\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = 'documents'\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1\n FROM document_sync_failures failure\n WHERE failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n )\n OR EXISTS (\n SELECT 1\n FROM document_pending_attachments attachment\n WHERE attachment.local_id = stored.local_id\n )\n )\n`;\n\nconst PENDING_PRIME_DOCUMENT_CANDIDATE_SQL = `\n SELECT pending.local_id AS local_id\n FROM (${PENDING_PRIME_LOCAL_ID_SQL}) pending\n ORDER BY pending.local_id ASC\n`;\n\n// The structural startup probe and the priming worker share the same durable\n// predicate so they cannot disagree about what counts as document work.\nconst STARTUP_DOCUMENT_SYNC_WORK_SQL = `\n SELECT 1 AS present\n WHERE EXISTS (${PENDING_PRIME_LOCAL_ID_SQL})\n OR EXISTS (\n SELECT 1\n FROM document_move_intents intent\n -- Blocked and parked denied moves count: blocked intents replay on\n -- every scan (the blocking condition can heal after hydration), and\n -- the once-per-launch replay makes denied moves retriable — so a\n -- relaunch whose only durable work is either kind must still schedule\n -- the structural pass that re-attempts it (row 7). Unavailable moves\n -- are excluded: no pass ever replays them (#2278 #4).\n WHERE intent.sync_status IN ('pending', 'blocked', 'denied')\n )\n LIMIT 1\n`;\n\nexport async function hasStartupDocumentSyncWork(\n runtimeOrExecSql:\n | ContainerDocumentQueriesRuntime\n | ContainerDocumentQueriesRuntime[\"infra\"][\"execSql\"],\n): Promise<boolean> {\n const execSql =\n typeof runtimeOrExecSql === \"function\"\n ? runtimeOrExecSql\n : runtimeOrExecSql.infra.execSql;\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(STARTUP_DOCUMENT_SYNC_WORK_SQL);\n return rows.length > 0;\n}\n\nasync function listPrimeRequiredDocumentCandidatesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<PrimeRequiredDocumentCandidate[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n PENDING_PRIME_DOCUMENT_CANDIDATE_SQL,\n );\n\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n return [{ localId }];\n });\n}\n\n// A row with content but a NULL outgoing-delta marker is deliberately treated\n// as unsettled: the store persist path always sets the marker, so over-priming\n// is the safe direction.\nasync function listPrimeRequiredLocalIdsFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<ReadonlySet<string>> {\n const candidates =\n await listPrimeRequiredDocumentCandidatesFromRuntime(runtime);\n return new Set(candidates.map((candidate) => candidate.localId));\n}\n\n/**\n * Last-link orphans (docs/sync-edge-cases.md row 3): the container cascade\n * nulled their projection container and dropped their link rows, so no\n * subtree listing can route them. Placements held for unsigned tombstones\n * also qualify when every link is hidden; their link rows remain intact.\n * These documents are primed with a null container\n * scope instead — the documents runtime accepts one, and the document's own\n * sync pass then resolves its fate against the server: 403 parks it (row 8),\n * a coded 404 destroys it (row 1), and a local-only orphan's create attempt\n * records a terminal failure row. Hidden document kinds stay excluded, and\n * dangling non-null projections (a container row merely missing locally)\n * stay with stale-root recovery, exactly as before.\n *\n * Organization neutrality: the null scope changes only the runtime's\n * containerId — auth, crypto, and organization plumbing are identical to\n * every container-scoped runtime this store already primes with, the sync\n * pass derives billing and keying organizations from the document's own\n * plan and manifest, and a cross-organization author fails closed at the\n * sync layer's identity guard before anything is signed.\n */\nconst ORPHANED_PRIME_TARGET_SQL = `\n SELECT stored.local_id AS local_id, stored.document_id AS document_id\n FROM documents stored\n INNER JOIN document_projection projection\n ON projection.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"stored.document_id\",\n projectionAlias: \"projection\",\n })}\n ORDER BY stored.local_id ASC\n`;\n\n/**\n * Unattributed rows (empty/NULL organization) are always included: they are\n * device-first documents created before authentication, which belong to this\n * device's sole user and adopt the active organization when they create.\n */\nasync function listOrphanedDocumentPrimeTargets(\n runtime: ContainerDocumentQueriesRuntime,\n organizationId: string,\n): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentContainerProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n ORPHANED_PRIME_TARGET_SQL,\n getOrphanedDocumentQueryBind(organizationId),\n );\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n const documentId = Reflect.get(row, \"document_id\");\n return [\n {\n documentId: typeof documentId === \"string\" ? documentId : null,\n localId,\n runtimeContainerId: null,\n },\n ];\n });\n}\n\nexport async function primeDocumentsForContainerSubtree<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n primeRequiredLocalIds?: ReadonlySet<string>;\n rootContainerId: string;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<number> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) return 0;\n const [targets, primeRequiredLocalIds] = await Promise.all([\n listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId: input.rootContainerId,\n runtime: input.runtime,\n }),\n input.primeRequiredLocalIds ??\n listPrimeRequiredLocalIdsFromRuntime(input.runtime),\n ]);\n if (!isCurrent()) return 0;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter((target) =>\n primeRequiredLocalIds.has(target.localId),\n ),\n });\n return primed.size;\n}\n\nexport async function primeDocumentsForLoadedRoots<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n /**\n * The store scope's organization. Orphan priming is bounded to it: each\n * organization-scoped store resolves only its own orphans, matching the\n * per-organization invariant subtree routing provides implicitly (a pass\n * signed under another organization would fail the sync identity guard\n * instead of resolving). Absent — unauthenticated or scope-less callers —\n * orphan priming is skipped entirely.\n */\n organizationId?: string | null;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<LoadedRootDocumentPrimeResult> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) {\n return {\n candidateCount: 0,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: 0,\n };\n }\n const candidates = await listPrimeRequiredDocumentCandidatesFromRuntime(\n input.runtime,\n );\n if (!isCurrent()) {\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: candidates.length,\n };\n }\n const rootContainerIds = Array.from(input.containersById.values()).flatMap(\n (containerState) =>\n containerState.container.parentId === null\n ? [containerState.container.id]\n : [],\n );\n const requiredLocalIds = new Set(\n candidates.map((candidate) => candidate.localId),\n );\n const primedLocalIds = new Set<string>();\n\n for (const rootContainerId of rootContainerIds) {\n if (!isCurrent()) break;\n const targets =\n await listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId,\n runtime: input.runtime,\n });\n if (!isCurrent()) break;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n ),\n });\n for (const localId of primed) {\n primedLocalIds.add(localId);\n }\n }\n\n const orphanTargets = (\n isCurrent() && input.organizationId\n ? await listOrphanedDocumentPrimeTargets(\n input.runtime,\n input.organizationId,\n )\n : []\n ).filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n );\n const orphanPrimed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: isCurrent() ? orphanTargets : [],\n });\n for (const localId of orphanPrimed) {\n primedLocalIds.add(localId);\n }\n\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: orphanPrimed.size,\n primedCount: primedLocalIds.size,\n rootCount: rootContainerIds.length,\n unroutableCount: candidates.filter(\n (candidate) => !primedLocalIds.has(candidate.localId),\n ).length,\n };\n}\n"]}
@@ -42,8 +42,8 @@ export function getContainerContentsDocumentPendingStateCtes() {
42
42
  SELECT
43
43
  local_id,
44
44
  COUNT(*) AS pending_update_count
45
- FROM document_pending_updates
46
- WHERE app_kind = 'documents'
45
+ FROM document_history_updates
46
+ WHERE app_kind = 'documents' AND update_id IS NOT NULL
47
47
  GROUP BY local_id
48
48
  ),
49
49
  document_pending_attachment_counts AS (
@@ -101,8 +101,8 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
101
101
  SELECT
102
102
  local_id,
103
103
  COUNT(*) AS pending_update_count
104
- FROM document_pending_updates
105
- WHERE app_kind = 'container-metadata'
104
+ FROM document_history_updates
105
+ WHERE app_kind = 'container-metadata' AND update_id IS NOT NULL
106
106
  GROUP BY local_id
107
107
  ),
108
108
  pending_container_create_intents AS (
@@ -1 +1 @@
1
- {"version":3,"file":"sql.js","sourceRoot":"","sources":["sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,0EAA0E;AAC1E,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACjD,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAC5C,MAAM,2CAA2C,GAAG,GAAG,CAAC;AAExD,MAAM,UAAU,iCAAiC,CAC/C,MAA6B;IAE7B,MAAM,OAAO,GAAe,EAAE,CAAC;IAE/B,KACE,IAAI,KAAK,GAAG,CAAC,EACb,KAAK,GAAG,MAAM,CAAC,MAAM,EACrB,KAAK,IAAI,oCAAoC,EAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,oCAAoC,CAAC,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAAa;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,OAAO,IAAI,CAAC,GAAG,CACb,+BAA+B,EAC/B,6BAA6B,CAAC,KAAK,CAAC,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAC,KAAa;IAClE,OAAO,IAAI,CAAC,GAAG,CACb,2CAA2C,EAC3C,6BAA6B,CAAC,KAAK,CAAC,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wCAAwC,CACtD,IAAuB;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAE7D,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,4BAA4B,SAAS,4DAA4D,CAAC;IAC3G,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,sCAAsC,SAAS,wCAAwC,CAAC;IACjG,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,sCAAsC,SAAS,wCAAwC,CAAC;IACjG,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,2CAA2C,SAAS,6CAA6C,CAAC;IAC3G,CAAC;IAED,OAAO,wFAAwF,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,4CAA4C;IAC1D,OAAO;;;;;;;;;;;;;;;;;GAiBN,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,0BAA0B,CAAC,OAG1C;IACC,OAAO,YAAY,OAAO,CAAC,eAAe,4BAA4B,OAAO,CAAC,cAAc,kDAAkD,CAAC;AACjJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sCAAsC,CAAC,OAGtD;IACC,OAAO,mBAAmB,OAAO,CAAC,cAAc,iCAAiC,OAAO,CAAC,eAAe,wBAAwB,CAAC;AACnI,CAAC;AAED,SAAS,6CAA6C,CACpD,MAAmC;IAEnC,MAAM,OAAO,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,sBAAsB,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,4BAA4B,GAAG,KAAK,CAAC,IAAI,CAC7C,EAAE,MAAM,EAAE,MAAM,CAAC,sBAAsB,EAAE,EACzC,GAAG,EAAE,CAAC,GAAG,CACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,qBAAqB,4BAA4B,GAAG,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,MAAM,CAAC,sCAAsC,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,4BAA4B,GAAG,KAAK,CAAC,IAAI,CAC7C,EAAE,MAAM,EAAE,MAAM,CAAC,sCAAsC,EAAE,EACzD,GAAG,EAAE,CAAC,GAAG,CACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,CAAC,IAAI,CACV,2DAA2D,0BAA0B,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,QAAQ,4BAA4B,IAAI,CAC9K,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,SAAS,4BAA4B,CACnC,aAAqB,EACrB,cAAsB;IAEtB,OAAO;;;;qCAI4B,aAAa;sCACZ,cAAc;;UAE1C,CAAC;AACX,CAAC;AAED,MAAM,UAAU,yCAAyC,CACvD,sBAAsB,GAAG,CAAC,EAC1B,sCAAsC,GAAG,CAAC;IAE1C,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAkC/C,0BAA0B,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;;;;;;;;;;;cAWtE,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,CAAC;cACnD,6CAA6C,CAAC;QAClD,sCAAsC;QACtC,sBAAsB;KACvB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4BI,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;gCAC9B,4BAA4B,CAAC,eAAe,EAAE,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6BjF,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;;;;;WAKnD,4BAA4B,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;;;;GAIjF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uCAAuC;IACrD,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;;cAiB3C,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;gCAC9B,4BAA4B,CAAC,eAAe,EAAE,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;cAoBjF,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;;;;;WAKnD,4BAA4B,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;;;;GAIjF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B;IAC7C,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;cA0B3C,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;YAClD,2BAA2B,CAAC;QAChC,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,GAAG;KACrB,CAAC;;;;GAIL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;YAgB7C,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;YAChD,2BAA2B,CAAC;QAChC,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,GAAG;KACrB,CAAC;GACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO;;;YAGG,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC;YAChD,2BAA2B,CAAC;QAChC,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,GAAG;KACrB,CAAC;;GAEL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mDAAmD;IACjE,OAAO,iFAAiF,CAAC;AAC3F,CAAC","sourcesContent":["import { getOrphanedDocumentWhereSql } from \"../orphanedDocumentSql\";\nimport { hydratedProjectionSql } from \"./hydrationSql\";\nimport type { ContainerItemSort } from \"./types\";\n\n// Keep each IN clause below SQLite's historical 999 bind-parameter limit.\nconst CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE = 500;\nconst MAX_CONTAINER_ITEM_WINDOW_LIMIT = 200;\nconst MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT = 200;\n\nexport function listContainerContentsSqlIdBatches(\n values: ReadonlyArray<string>,\n): ReadonlyArray<ReadonlyArray<string>> {\n const batches: string[][] = [];\n\n for (\n let index = 0;\n index < values.length;\n index += CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE\n ) {\n batches.push(\n values.slice(index, index + CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE),\n );\n }\n\n return batches;\n}\n\nexport function clampContainerItemWindowValue(value: number): number {\n return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n}\n\nexport function getContainerItemWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_ITEM_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerDocumentSidebarWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerContentsContainerItemOrderBy(\n sort: ContainerItemSort,\n): string {\n const direction = sort.direction === \"desc\" ? \"DESC\" : \"ASC\";\n\n if (sort.key === \"type\") {\n return `type_sort COLLATE NOCASE ${direction}, name COLLATE NOCASE ASC, item_kind_sort ASC, item_id ASC`;\n }\n\n if (sort.key === \"created\") {\n return `created_at IS NULL ASC, created_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"modified\") {\n return `updated_at IS NULL ASC, updated_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"name\") {\n return `item_kind_sort ASC, name COLLATE NOCASE ${direction}, type_sort COLLATE NOCASE ASC, item_id ASC`;\n }\n\n return \"item_kind_sort ASC, name COLLATE NOCASE ASC, type_sort COLLATE NOCASE ASC, item_id ASC\";\n}\n\nexport function getContainerContentsDocumentPendingStateCtes(): string {\n return `\n document_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_pending_updates\n WHERE app_kind = 'documents'\n GROUP BY local_id\n ),\n document_pending_attachment_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_attachment_count,\n COALESCE(SUM(byte_length), 0) AS pending_attachment_bytes\n FROM document_pending_attachments\n GROUP BY local_id\n )\n `;\n}\n\ninterface ContainerSystemFilterCounts {\n visibleForeignSystemContainerNameCount: number;\n visibleSystemSlotCount: number;\n}\n\nexport function getContainerDisplayNameSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(${aliases.projectionAlias}.display_name, CASE WHEN ${aliases.containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;\n}\n\n/**\n * Display attribution for an object reached through a container: the\n * container's organization when attached, else the projection row's own.\n */\nexport function getContainerOrganizationAttributionSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(NULLIF(${aliases.containerAlias}.organization_id, ''), NULLIF(${aliases.projectionAlias}.organization_id, ''))`;\n}\n\nfunction getContainerContentsContainerSystemSlotFilter(\n counts: ContainerSystemFilterCounts,\n): string {\n const clauses = [\"c.system_slot IS NULL\"];\n\n if (counts.visibleSystemSlotCount > 0) {\n const visibleSystemSlotBindMarkers = Array.from(\n { length: counts.visibleSystemSlotCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(`c.system_slot IN (${visibleSystemSlotBindMarkers})`);\n }\n\n if (counts.visibleForeignSystemContainerNameCount > 0) {\n const visibleSystemNameBindMarkers = Array.from(\n { length: counts.visibleForeignSystemContainerNameCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(\n `(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} IN (${visibleSystemNameBindMarkers}))`,\n );\n }\n\n return `(${clauses.join(\" OR \")})`;\n}\n\n/**\n * A `(document, container)` placement under a tombstone hold is hidden from\n * container views: the server said the document left the container, but the\n * signed head that would prove it is not yet available, so the row is kept\n * and hidden rather than deleted (`container_document_tombstone_holds`).\n */\nfunction getHeldPlacementExclusionSql(\n documentIdSql: string,\n containerIdSql: string,\n): string {\n return `\n AND NOT EXISTS (\n SELECT 1\n FROM container_document_tombstone_holds hold\n WHERE hold.document_id = ${documentIdSql}\n AND hold.container_id = ${containerIdSql}\n AND hold.hidden = 1\n )`;\n}\n\nexport function getContainerContentsContainerItemsBaseSql(\n visibleSystemSlotCount = 0,\n visibleForeignSystemContainerNameCount = 0,\n): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_metadata_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_pending_updates\n WHERE app_kind = 'container-metadata'\n GROUP BY local_id\n ),\n pending_container_create_intents AS (\n SELECT\n container_id,\n MAX(last_error) AS last_error\n FROM container_create_intents\n WHERE intent_type = 'container.create'\n AND sync_status = 'pending'\n GROUP BY container_id\n ),\n container_items AS (\n SELECT\n 'container' AS item_kind,\n 0 AS item_kind_sort,\n c.id AS item_id,\n NULL AS document_id,\n NULL AS document_kind,\n c.metadata_document_id AS metadata_document_id,\n c.local_updated_at AS local_updated_at,\n c.server_created_at AS server_created_at,\n c.server_updated_at AS server_updated_at,\n cp.icon AS icon,\n COALESCE(container_updates.pending_update_count, 0) AS pending_update_count,\n 0 AS pending_attachment_count,\n 0 AS pending_attachment_bytes,\n create_intent.last_error AS sync_last_error,\n ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} AS name,\n 'folder' AS type_sort,\n COALESCE(c.server_created_at, c.local_created_at) AS created_at,\n COALESCE(c.server_updated_at, c.local_updated_at) AS updated_at\n FROM containers c\n LEFT JOIN container_projection cp ON cp.container_id = c.id\n LEFT JOIN container_metadata_pending_update_counts container_updates\n ON container_updates.local_id = c.id\n LEFT JOIN pending_container_create_intents create_intent\n ON create_intent.container_id = c.id\n WHERE c.parent_id = ?\n AND ${hydratedProjectionSql(\"c.id\", \"container-metadata\")}\n AND ${getContainerContentsContainerSystemSlotFilter({\n visibleForeignSystemContainerNameCount,\n visibleSystemSlotCount,\n })}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_items\n `;\n}\n\nexport function getContainerContentsDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_documents AS (\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n linked.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_documents\n `;\n}\n\nexport function getOrphanedDocumentItemsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n orphaned_document_items AS (\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n )\n SELECT *\n FROM orphaned_document_items\n `;\n}\n\nexport function getOrphanedDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n `;\n}\n\nexport function getOrphanedDocumentExistsSql(): string {\n return `\n SELECT 1\n FROM document_projection d\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n LIMIT 1\n `;\n}\n\nexport function getContainerContentsContainerDocumentSidebarOrderBy(): string {\n return \"updated_at IS NULL ASC, updated_at DESC, title COLLATE NOCASE ASC, local_id ASC\";\n}\n"]}
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["sql.ts"],"names":[],"mappings":"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","sourcesContent":["import { getOrphanedDocumentWhereSql } from \"../orphanedDocumentSql\";\nimport { hydratedProjectionSql } from \"./hydrationSql\";\nimport type { ContainerItemSort } from \"./types\";\n\n// Keep each IN clause below SQLite's historical 999 bind-parameter limit.\nconst CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE = 500;\nconst MAX_CONTAINER_ITEM_WINDOW_LIMIT = 200;\nconst MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT = 200;\n\nexport function listContainerContentsSqlIdBatches(\n values: ReadonlyArray<string>,\n): ReadonlyArray<ReadonlyArray<string>> {\n const batches: string[][] = [];\n\n for (\n let index = 0;\n index < values.length;\n index += CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE\n ) {\n batches.push(\n values.slice(index, index + CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE),\n );\n }\n\n return batches;\n}\n\nexport function clampContainerItemWindowValue(value: number): number {\n return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n}\n\nexport function getContainerItemWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_ITEM_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerDocumentSidebarWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerContentsContainerItemOrderBy(\n sort: ContainerItemSort,\n): string {\n const direction = sort.direction === \"desc\" ? \"DESC\" : \"ASC\";\n\n if (sort.key === \"type\") {\n return `type_sort COLLATE NOCASE ${direction}, name COLLATE NOCASE ASC, item_kind_sort ASC, item_id ASC`;\n }\n\n if (sort.key === \"created\") {\n return `created_at IS NULL ASC, created_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"modified\") {\n return `updated_at IS NULL ASC, updated_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"name\") {\n return `item_kind_sort ASC, name COLLATE NOCASE ${direction}, type_sort COLLATE NOCASE ASC, item_id ASC`;\n }\n\n return \"item_kind_sort ASC, name COLLATE NOCASE ASC, type_sort COLLATE NOCASE ASC, item_id ASC\";\n}\n\nexport function getContainerContentsDocumentPendingStateCtes(): string {\n return `\n document_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_history_updates\n WHERE app_kind = 'documents' AND update_id IS NOT NULL\n GROUP BY local_id\n ),\n document_pending_attachment_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_attachment_count,\n COALESCE(SUM(byte_length), 0) AS pending_attachment_bytes\n FROM document_pending_attachments\n GROUP BY local_id\n )\n `;\n}\n\ninterface ContainerSystemFilterCounts {\n visibleForeignSystemContainerNameCount: number;\n visibleSystemSlotCount: number;\n}\n\nexport function getContainerDisplayNameSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(${aliases.projectionAlias}.display_name, CASE WHEN ${aliases.containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;\n}\n\n/**\n * Display attribution for an object reached through a container: the\n * container's organization when attached, else the projection row's own.\n */\nexport function getContainerOrganizationAttributionSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(NULLIF(${aliases.containerAlias}.organization_id, ''), NULLIF(${aliases.projectionAlias}.organization_id, ''))`;\n}\n\nfunction getContainerContentsContainerSystemSlotFilter(\n counts: ContainerSystemFilterCounts,\n): string {\n const clauses = [\"c.system_slot IS NULL\"];\n\n if (counts.visibleSystemSlotCount > 0) {\n const visibleSystemSlotBindMarkers = Array.from(\n { length: counts.visibleSystemSlotCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(`c.system_slot IN (${visibleSystemSlotBindMarkers})`);\n }\n\n if (counts.visibleForeignSystemContainerNameCount > 0) {\n const visibleSystemNameBindMarkers = Array.from(\n { length: counts.visibleForeignSystemContainerNameCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(\n `(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} IN (${visibleSystemNameBindMarkers}))`,\n );\n }\n\n return `(${clauses.join(\" OR \")})`;\n}\n\n/**\n * A `(document, container)` placement under a tombstone hold is hidden from\n * container views: the server said the document left the container, but the\n * signed head that would prove it is not yet available, so the row is kept\n * and hidden rather than deleted (`container_document_tombstone_holds`).\n */\nfunction getHeldPlacementExclusionSql(\n documentIdSql: string,\n containerIdSql: string,\n): string {\n return `\n AND NOT EXISTS (\n SELECT 1\n FROM container_document_tombstone_holds hold\n WHERE hold.document_id = ${documentIdSql}\n AND hold.container_id = ${containerIdSql}\n AND hold.hidden = 1\n )`;\n}\n\nexport function getContainerContentsContainerItemsBaseSql(\n visibleSystemSlotCount = 0,\n visibleForeignSystemContainerNameCount = 0,\n): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_metadata_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_history_updates\n WHERE app_kind = 'container-metadata' AND update_id IS NOT NULL\n GROUP BY local_id\n ),\n pending_container_create_intents AS (\n SELECT\n container_id,\n MAX(last_error) AS last_error\n FROM container_create_intents\n WHERE intent_type = 'container.create'\n AND sync_status = 'pending'\n GROUP BY container_id\n ),\n container_items AS (\n SELECT\n 'container' AS item_kind,\n 0 AS item_kind_sort,\n c.id AS item_id,\n NULL AS document_id,\n NULL AS document_kind,\n c.metadata_document_id AS metadata_document_id,\n c.local_updated_at AS local_updated_at,\n c.server_created_at AS server_created_at,\n c.server_updated_at AS server_updated_at,\n cp.icon AS icon,\n COALESCE(container_updates.pending_update_count, 0) AS pending_update_count,\n 0 AS pending_attachment_count,\n 0 AS pending_attachment_bytes,\n create_intent.last_error AS sync_last_error,\n ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} AS name,\n 'folder' AS type_sort,\n COALESCE(c.server_created_at, c.local_created_at) AS created_at,\n COALESCE(c.server_updated_at, c.local_updated_at) AS updated_at\n FROM containers c\n LEFT JOIN container_projection cp ON cp.container_id = c.id\n LEFT JOIN container_metadata_pending_update_counts container_updates\n ON container_updates.local_id = c.id\n LEFT JOIN pending_container_create_intents create_intent\n ON create_intent.container_id = c.id\n WHERE c.parent_id = ?\n AND ${hydratedProjectionSql(\"c.id\", \"container-metadata\")}\n AND ${getContainerContentsContainerSystemSlotFilter({\n visibleForeignSystemContainerNameCount,\n visibleSystemSlotCount,\n })}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_items\n `;\n}\n\nexport function getContainerContentsDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_documents AS (\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n linked.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_documents\n `;\n}\n\nexport function getOrphanedDocumentItemsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n orphaned_document_items AS (\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n )\n SELECT *\n FROM orphaned_document_items\n `;\n}\n\nexport function getOrphanedDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n `;\n}\n\nexport function getOrphanedDocumentExistsSql(): string {\n return `\n SELECT 1\n FROM document_projection d\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n LIMIT 1\n `;\n}\n\nexport function getContainerContentsContainerDocumentSidebarOrderBy(): string {\n return \"updated_at IS NULL ASC, updated_at DESC, title COLLATE NOCASE ASC, local_id ASC\";\n}\n"]}
@@ -15,9 +15,10 @@ const DEFERRED_TAIL_CANDIDATE_SQL = `
15
15
  stored.updated_at AS updated_at,
16
16
  (
17
17
  SELECT pending.partial_end_version_vector
18
- FROM document_pending_updates pending
18
+ FROM document_history_updates pending
19
19
  WHERE pending.app_kind = stored.app_kind
20
20
  AND pending.local_id = stored.local_id
21
+ AND pending.update_id IS NOT NULL
21
22
  ORDER BY pending.created_at DESC, pending.rowid DESC
22
23
  LIMIT 1
23
24
  ) AS latest_pending_end_version,
@@ -63,9 +64,10 @@ const DEFERRED_TAIL_CANDIDATE_SQL = `
63
64
  stored.pending_base_version IS NOT NULL
64
65
  OR EXISTS (
65
66
  SELECT 1
66
- FROM document_pending_updates pending
67
+ FROM document_history_updates pending
67
68
  WHERE pending.app_kind = stored.app_kind
68
69
  AND pending.local_id = stored.local_id
70
+ AND pending.update_id IS NOT NULL
69
71
  )
70
72
  )
71
73
  `;
@@ -169,9 +171,10 @@ const DEFERRED_TAIL_SCOPE_SQL = `
169
171
  stored.pending_base_version AS pending_base_version,
170
172
  (
171
173
  SELECT pending.partial_end_version_vector
172
- FROM document_pending_updates pending
174
+ FROM document_history_updates pending
173
175
  WHERE pending.app_kind = stored.app_kind
174
176
  AND pending.local_id = stored.local_id
177
+ AND pending.update_id IS NOT NULL
175
178
  ORDER BY pending.created_at DESC, pending.rowid DESC
176
179
  LIMIT 1
177
180
  ) AS latest_pending_end_version
@@ -1 +1 @@
1
- {"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_pending_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql({\n containerAlias: \"metadata_container\",\n projectionAlias: \"container_projection\",\n })} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n failure.message AS failure_message,\n failure.attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = metadata_container.id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = stored.app_kind\n AND failure.local_id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_pending_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_pending_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
1
+ {"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql({\n containerAlias: \"metadata_container\",\n projectionAlias: \"container_projection\",\n })} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n failure.message AS failure_message,\n failure.attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = metadata_container.id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = stored.app_kind\n AND failure.local_id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
@@ -16,7 +16,8 @@ const PENDING_WRITE_SOURCE_SQL = `
16
16
  COUNT(*) AS operation_count,
17
17
  MIN(created_at) AS created_at,
18
18
  MAX(created_at) AS updated_at
19
- FROM document_pending_updates
19
+ FROM document_history_updates
20
+ WHERE update_id IS NOT NULL
20
21
  GROUP BY app_kind, local_id
21
22
  )
22
23
  SELECT
@@ -1 +1 @@
1
- {"version":3,"file":"sources.js","sourceRoot":"","sources":["sources.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type {\n PendingWriteCandidate,\n PendingWriteCandidateInclusion,\n} from \"./aggregation\";\nimport { readNumber, readString } from \"./rowReaders\";\n\nconst CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql({\n containerAlias: \"container\",\n projectionAlias: \"container_projection\",\n});\nconst DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({\n containerAlias: \"container\",\n projectionAlias: \"projection\",\n});\n\nconst PENDING_WRITE_SOURCE_SQL = `\n WITH pending_update_groups AS (\n SELECT\n app_kind,\n local_id,\n COUNT(*) AS operation_count,\n MIN(created_at) AS created_at,\n MAX(created_at) AS updated_at\n FROM document_pending_updates\n GROUP BY app_kind, local_id\n )\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = updates.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = updates.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'documents'\n\n UNION ALL\n\n -- Failure-only surface (edge-case row 13): a refused read-only\n -- revalidation records a durable failure row with NO pending work, so\n -- without this branch the refusal would never reach the queue view. The\n -- 'unless-item-covered' inclusion keeps it out whenever the document\n -- already has real operations — those candidates carry the same failure\n -- message through their own joins.\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n LEFT JOIN documents stored\n ON stored.app_kind = failure.app_kind\n AND stored.local_id = failure.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = failure.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE failure.app_kind = 'documents'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN containers container ON container.id = updates.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'container-metadata'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'container-metadata'\n -- Dormant retained metadata (container tombstoned access_revoked, row 4)\n -- has no containers row; keep it unsurfaced until rehydration re-attaches\n -- the container, or it renders as an anonymous phantom item.\n AND container.id IS NOT NULL\n\n UNION ALL\n\n -- An incoming metadata quarantine can exist without outbound updates. Keep\n -- it visible as a zero-operation diagnostic while the container is live;\n -- dormant retained metadata stays hidden until rehydration re-attaches it.\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n JOIN containers container ON container.id = failure.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = failure.local_id\n WHERE failure.app_kind = 'container-metadata'\n\n UNION ALL\n\n SELECT\n 'unknown' AS object_kind,\n updates.app_kind AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n NULL AS name,\n NULL AS container_id,\n NULL AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = updates.app_kind\n AND stored.local_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = updates.app_kind\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind NOT IN ('documents', 'container-metadata')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n attachment.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'attachment' AS operation_kind,\n COUNT(*) AS operation_count,\n COALESCE(SUM(attachment.byte_length), 0) AS byte_length,\n MIN(attachment.created_at) AS created_at,\n MAX(attachment.created_at) AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM document_pending_attachments attachment\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = attachment.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = attachment.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = attachment.local_id\n GROUP BY attachment.local_id\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n 'pending' AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_create_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.create'\n AND intent.sync_status = 'pending'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_move_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.move'\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n intent.local_id AS local_id,\n intent.document_id AS remote_id,\n projection.title AS name,\n COALESCE(projection.container_id, intent.target_container_id) AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,\n COALESCE(NULLIF(intent.last_error, ''), failure.message) AS last_error,\n COALESCE(intent.last_attempted_at, failure.attempted_at) AS last_attempted_at,\n 'always' AS inclusion\n FROM document_move_intents intent\n LEFT JOIN document_projection projection\n ON projection.local_id = intent.local_id\n LEFT JOIN containers container\n ON container.id = COALESCE(projection.container_id, intent.target_container_id)\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = intent.local_id\n WHERE intent.intent_type IN ('document.move', 'document.link')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n NULL AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n stored.updated_at AS created_at,\n stored.updated_at AS updated_at,\n projection.container_id AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND stored.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n container.local_created_at AS created_at,\n container.local_updated_at AS updated_at,\n container.parent_id AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = container.id\n WHERE container.server_created_at IS NULL\n OR container.metadata_document_id IS NULL\n OR metadata.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n NULL AS created_at,\n container.local_updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n WHERE container.local_updated_at IS NOT NULL\n AND (\n container.server_updated_at IS NULL\n OR container.local_updated_at > container.server_updated_at\n )\n`;\n\nfunction mapPendingWriteSourceRow(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const localId = readString(row, \"local_id\");\n const operationKind = readString(row, \"operation_kind\");\n if (\n !localId ||\n (operationKind !== \"attachment\" &&\n operationKind !== \"create\" &&\n operationKind !== \"move\" &&\n operationKind !== \"revalidation\" &&\n operationKind !== \"update\")\n ) {\n return null;\n }\n const rawObjectKind = readString(row, \"object_kind\");\n const objectKind =\n rawObjectKind === \"container\" || rawObjectKind === \"document\"\n ? rawObjectKind\n : \"unknown\";\n const rawInclusion = readString(row, \"inclusion\");\n const inclusion: PendingWriteCandidateInclusion =\n rawInclusion === \"unless-item-covered\" ||\n rawInclusion === \"unless-operation-covered\"\n ? rawInclusion\n : \"always\";\n\n return {\n byteLength: readNumber(row, \"byte_length\"),\n containerId: readString(row, \"container_id\"),\n // Diagnostic-only revalidation items carry NO local operations; clamping\n // them to 1 would falsely report pending local data.\n count:\n operationKind === \"revalidation\"\n ? 0\n : Math.max(1, readNumber(row, \"operation_count\")),\n createdAt: readString(row, \"created_at\"),\n inclusion,\n kind: operationKind,\n lastAttemptedAt: readString(row, \"last_attempted_at\"),\n lastError: readString(row, \"last_error\"),\n localId,\n name: readString(row, \"name\"),\n namespace: readString(row, \"namespace\"),\n objectKind,\n organizationId: readString(row, \"organization_id\"),\n remoteId: readString(row, \"remote_id\"),\n status:\n readString(row, \"operation_status\") === \"blocked\" ? \"blocked\" : \"pending\",\n targetContainerId: readString(row, \"target_container_id\"),\n updatedAt: readString(row, \"updated_at\"),\n };\n}\n\nexport async function listPersistedPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(PENDING_WRITE_SOURCE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapPendingWriteSourceRow(row);\n return candidate ? [candidate] : [];\n });\n}\n"]}
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["sources.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type {\n PendingWriteCandidate,\n PendingWriteCandidateInclusion,\n} from \"./aggregation\";\nimport { readNumber, readString } from \"./rowReaders\";\n\nconst CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql({\n containerAlias: \"container\",\n projectionAlias: \"container_projection\",\n});\nconst DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({\n containerAlias: \"container\",\n projectionAlias: \"projection\",\n});\n\nconst PENDING_WRITE_SOURCE_SQL = `\n WITH pending_update_groups AS (\n SELECT\n app_kind,\n local_id,\n COUNT(*) AS operation_count,\n MIN(created_at) AS created_at,\n MAX(created_at) AS updated_at\n FROM document_history_updates\n WHERE update_id IS NOT NULL\n GROUP BY app_kind, local_id\n )\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = updates.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = updates.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'documents'\n\n UNION ALL\n\n -- Failure-only surface (edge-case row 13): a refused read-only\n -- revalidation records a durable failure row with NO pending work, so\n -- without this branch the refusal would never reach the queue view. The\n -- 'unless-item-covered' inclusion keeps it out whenever the document\n -- already has real operations — those candidates carry the same failure\n -- message through their own joins.\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n LEFT JOIN documents stored\n ON stored.app_kind = failure.app_kind\n AND stored.local_id = failure.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = failure.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE failure.app_kind = 'documents'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN containers container ON container.id = updates.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'container-metadata'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'container-metadata'\n -- Dormant retained metadata (container tombstoned access_revoked, row 4)\n -- has no containers row; keep it unsurfaced until rehydration re-attaches\n -- the container, or it renders as an anonymous phantom item.\n AND container.id IS NOT NULL\n\n UNION ALL\n\n -- An incoming metadata quarantine can exist without outbound updates. Keep\n -- it visible as a zero-operation diagnostic while the container is live;\n -- dormant retained metadata stays hidden until rehydration re-attaches it.\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n JOIN containers container ON container.id = failure.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = failure.local_id\n WHERE failure.app_kind = 'container-metadata'\n\n UNION ALL\n\n SELECT\n 'unknown' AS object_kind,\n updates.app_kind AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n NULL AS name,\n NULL AS container_id,\n NULL AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = updates.app_kind\n AND stored.local_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = updates.app_kind\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind NOT IN ('documents', 'container-metadata')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n attachment.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'attachment' AS operation_kind,\n COUNT(*) AS operation_count,\n COALESCE(SUM(attachment.byte_length), 0) AS byte_length,\n MIN(attachment.created_at) AS created_at,\n MAX(attachment.created_at) AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM document_pending_attachments attachment\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = attachment.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = attachment.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = attachment.local_id\n GROUP BY attachment.local_id\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n 'pending' AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_create_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.create'\n AND intent.sync_status = 'pending'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_move_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.move'\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n intent.local_id AS local_id,\n intent.document_id AS remote_id,\n projection.title AS name,\n COALESCE(projection.container_id, intent.target_container_id) AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,\n COALESCE(NULLIF(intent.last_error, ''), failure.message) AS last_error,\n COALESCE(intent.last_attempted_at, failure.attempted_at) AS last_attempted_at,\n 'always' AS inclusion\n FROM document_move_intents intent\n LEFT JOIN document_projection projection\n ON projection.local_id = intent.local_id\n LEFT JOIN containers container\n ON container.id = COALESCE(projection.container_id, intent.target_container_id)\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = intent.local_id\n WHERE intent.intent_type IN ('document.move', 'document.link')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n NULL AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n stored.updated_at AS created_at,\n stored.updated_at AS updated_at,\n projection.container_id AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND stored.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n container.local_created_at AS created_at,\n container.local_updated_at AS updated_at,\n container.parent_id AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = container.id\n WHERE container.server_created_at IS NULL\n OR container.metadata_document_id IS NULL\n OR metadata.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n NULL AS created_at,\n container.local_updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n WHERE container.local_updated_at IS NOT NULL\n AND (\n container.server_updated_at IS NULL\n OR container.local_updated_at > container.server_updated_at\n )\n`;\n\nfunction mapPendingWriteSourceRow(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const localId = readString(row, \"local_id\");\n const operationKind = readString(row, \"operation_kind\");\n if (\n !localId ||\n (operationKind !== \"attachment\" &&\n operationKind !== \"create\" &&\n operationKind !== \"move\" &&\n operationKind !== \"revalidation\" &&\n operationKind !== \"update\")\n ) {\n return null;\n }\n const rawObjectKind = readString(row, \"object_kind\");\n const objectKind =\n rawObjectKind === \"container\" || rawObjectKind === \"document\"\n ? rawObjectKind\n : \"unknown\";\n const rawInclusion = readString(row, \"inclusion\");\n const inclusion: PendingWriteCandidateInclusion =\n rawInclusion === \"unless-item-covered\" ||\n rawInclusion === \"unless-operation-covered\"\n ? rawInclusion\n : \"always\";\n\n return {\n byteLength: readNumber(row, \"byte_length\"),\n containerId: readString(row, \"container_id\"),\n // Diagnostic-only revalidation items carry NO local operations; clamping\n // them to 1 would falsely report pending local data.\n count:\n operationKind === \"revalidation\"\n ? 0\n : Math.max(1, readNumber(row, \"operation_count\")),\n createdAt: readString(row, \"created_at\"),\n inclusion,\n kind: operationKind,\n lastAttemptedAt: readString(row, \"last_attempted_at\"),\n lastError: readString(row, \"last_error\"),\n localId,\n name: readString(row, \"name\"),\n namespace: readString(row, \"namespace\"),\n objectKind,\n organizationId: readString(row, \"organization_id\"),\n remoteId: readString(row, \"remote_id\"),\n status:\n readString(row, \"operation_status\") === \"blocked\" ? \"blocked\" : \"pending\",\n targetContainerId: readString(row, \"target_container_id\"),\n updatedAt: readString(row, \"updated_at\"),\n };\n}\n\nexport async function listPersistedPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(PENDING_WRITE_SOURCE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapPendingWriteSourceRow(row);\n return candidate ? [candidate] : [];\n });\n}\n"]}
@@ -78,8 +78,9 @@ async function hasQueuedScopeWork(execSql, scope) {
78
78
  ]);
79
79
  const rows = await execSql(`SELECT 1 AS present
80
80
  WHERE EXISTS (
81
- SELECT 1 FROM document_pending_updates pending
81
+ SELECT 1 FROM document_history_updates pending
82
82
  WHERE pending.app_kind = ? AND pending.local_id = ?
83
+ AND pending.update_id IS NOT NULL
83
84
  )
84
85
  OR EXISTS (
85
86
  SELECT 1 FROM document_pending_attachments attachment
@@ -1 +1 @@
1
- {"version":3,"file":"pendingWrites.js","sourceRoot":"","sources":["pendingWrites.ts"],"names":[],"mappings":"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","sourcesContent":["import { CONTAINER_METADATA_APP_KIND } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport { DOCUMENTS_APP_KIND } from \"../../data/persistence/documents/internal/constants\";\nimport {\n clearDocumentSyncFailure,\n resetDocumentPendingUpdateRekeyBudget,\n} from \"../../data/sqlite/documentPersistence\";\nimport {\n documentMoveIntentTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { defaultContainerContentsPersistence } from \"./containerPersistence\";\nimport { groupPendingWriteCandidates } from \"./pendingWrites/aggregation\";\nimport {\n hasDeferredTailScopeWork,\n listDeferredPendingWriteCandidates,\n} from \"./pendingWrites/deferredTails\";\nimport { listPersistedPendingWriteCandidates } from \"./pendingWrites/sources\";\nimport type { PendingWriteQueueItem } from \"./pendingWritesTypes\";\n\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\n/**\n * List identity-wide local state that still requires a remote write. The\n * returned diagnostic contains only navigation/display metadata and aggregate\n * counts; serialized updates, local storage keys, and upload crypto stay below\n * the workflow boundary.\n */\nexport async function listPendingWrites(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingWriteQueueItem>> {\n await defaultContainerContentsPersistence.ensureSchema(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await sqlDocumentMoveIntentPersistence.ensureSchema(execSql);\n\n const [persisted, deferred] = await Promise.all([\n listPersistedPendingWriteCandidates(execSql),\n listDeferredPendingWriteCandidates(execSql),\n ]);\n return groupPendingWriteCandidates([...persisted, ...deferred]);\n}\n\n/**\n * Explicit manual retry for one write-queue item: reset the durable re-key\n * budget for the item's ACTUAL pending-update scope (container metadata and\n * unknown document namespaces re-key through the same recovery path as\n * ordinary documents) and clear the recorded terminal failure — the next\n * pass re-records both if they still hold. The cap protects against a\n * server driving a network-speed re-key loop; a deliberate user retry is\n * the rate-limited signal that conditions have changed (e.g. an outage that\n * burned the budget has healed). The caller re-arms the sync lanes.\n */\nexport async function resetPendingWriteRetryState(\n execSql: ExecSql,\n input: {\n localId: string;\n /** The item's `namespace` — the unrecognized documents.app_kind, if any. */\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n },\n): Promise<void> {\n const appKind =\n input.objectKind === \"container\"\n ? CONTAINER_METADATA_APP_KIND\n : (input.namespace ??\n (input.objectKind === \"document\" ? DOCUMENTS_APP_KIND : null));\n if (appKind === null) {\n // An unknown object kind with no namespace: there is no scope to reset,\n // and guessing one could clear an unrelated scope sharing the localId.\n return;\n }\n const scope = { appKind, localId: input.localId };\n await resetDocumentPendingUpdateRekeyBudget(execSql, scope);\n if (appKind === DOCUMENTS_APP_KIND) {\n // A deliberate retry is the rate-limited signal that conditions changed:\n // a parked permission-denied move (row 7) replays once, like row 11's\n // re-key budget reset.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql, {\n localId: input.localId,\n });\n }\n // Clearing the failure row is part of the re-key budget reset (edge-case\n // row 11) and only makes sense alongside queued work. A failure-only item\n // (a refused revalidation, row 13) has no queued work: its row is the\n // priming ticket that re-drives the store, so it must survive the retry\n // and clear on the next clean pass instead of vanishing with no request.\n if (await hasQueuedScopeWork(execSql, scope)) {\n await clearDocumentSyncFailure(execSql, scope);\n }\n}\n\n/**\n * Whether ANY durable outbound work exists for the scope — CRDT updates,\n * staged attachment uploads, move intents, a never-created local document, or\n * a deferred write whose only durable content is the history tail ahead of\n * its covered frontier. Mirrors the queue's own document candidate sources,\n * so \"failure-only\" here agrees with the item the panel rendered.\n */\nasync function hasQueuedScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(\n `SELECT 1 AS present\n WHERE EXISTS (\n SELECT 1 FROM document_pending_updates pending\n WHERE pending.app_kind = ? AND pending.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM document_pending_attachments attachment\n WHERE attachment.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM document_move_intents intent\n WHERE intent.local_id = ? AND intent.intent_type IN ('document.move', 'document.link')\n )\n OR EXISTS (\n SELECT 1 FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.document_id IS NULL\n )\n LIMIT 1`,\n [\n scope.appKind,\n scope.localId,\n scope.localId,\n scope.localId,\n scope.appKind,\n scope.localId,\n ],\n );\n if (rows.length > 0) {\n return true;\n }\n // The queue's deferred-update source has no queued rows to probe: the\n // write lives in the durable history tail, detectable only by the\n // version-vector coverage check.\n return hasDeferredTailScopeWork(execSql, scope);\n}\n"]}
1
+ {"version":3,"file":"pendingWrites.js","sourceRoot":"","sources":["pendingWrites.ts"],"names":[],"mappings":"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","sourcesContent":["import { CONTAINER_METADATA_APP_KIND } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport { DOCUMENTS_APP_KIND } from \"../../data/persistence/documents/internal/constants\";\nimport {\n clearDocumentSyncFailure,\n resetDocumentPendingUpdateRekeyBudget,\n} from \"../../data/sqlite/documentPersistence\";\nimport {\n documentMoveIntentTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { defaultContainerContentsPersistence } from \"./containerPersistence\";\nimport { groupPendingWriteCandidates } from \"./pendingWrites/aggregation\";\nimport {\n hasDeferredTailScopeWork,\n listDeferredPendingWriteCandidates,\n} from \"./pendingWrites/deferredTails\";\nimport { listPersistedPendingWriteCandidates } from \"./pendingWrites/sources\";\nimport type { PendingWriteQueueItem } from \"./pendingWritesTypes\";\n\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\n/**\n * List identity-wide local state that still requires a remote write. The\n * returned diagnostic contains only navigation/display metadata and aggregate\n * counts; serialized updates, local storage keys, and upload crypto stay below\n * the workflow boundary.\n */\nexport async function listPendingWrites(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingWriteQueueItem>> {\n await defaultContainerContentsPersistence.ensureSchema(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await sqlDocumentMoveIntentPersistence.ensureSchema(execSql);\n\n const [persisted, deferred] = await Promise.all([\n listPersistedPendingWriteCandidates(execSql),\n listDeferredPendingWriteCandidates(execSql),\n ]);\n return groupPendingWriteCandidates([...persisted, ...deferred]);\n}\n\n/**\n * Explicit manual retry for one write-queue item: reset the durable re-key\n * budget for the item's ACTUAL pending-update scope (container metadata and\n * unknown document namespaces re-key through the same recovery path as\n * ordinary documents) and clear the recorded terminal failure — the next\n * pass re-records both if they still hold. The cap protects against a\n * server driving a network-speed re-key loop; a deliberate user retry is\n * the rate-limited signal that conditions have changed (e.g. an outage that\n * burned the budget has healed). The caller re-arms the sync lanes.\n */\nexport async function resetPendingWriteRetryState(\n execSql: ExecSql,\n input: {\n localId: string;\n /** The item's `namespace` — the unrecognized documents.app_kind, if any. */\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n },\n): Promise<void> {\n const appKind =\n input.objectKind === \"container\"\n ? CONTAINER_METADATA_APP_KIND\n : (input.namespace ??\n (input.objectKind === \"document\" ? DOCUMENTS_APP_KIND : null));\n if (appKind === null) {\n // An unknown object kind with no namespace: there is no scope to reset,\n // and guessing one could clear an unrelated scope sharing the localId.\n return;\n }\n const scope = { appKind, localId: input.localId };\n await resetDocumentPendingUpdateRekeyBudget(execSql, scope);\n if (appKind === DOCUMENTS_APP_KIND) {\n // A deliberate retry is the rate-limited signal that conditions changed:\n // a parked permission-denied move (row 7) replays once, like row 11's\n // re-key budget reset.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql, {\n localId: input.localId,\n });\n }\n // Clearing the failure row is part of the re-key budget reset (edge-case\n // row 11) and only makes sense alongside queued work. A failure-only item\n // (a refused revalidation, row 13) has no queued work: its row is the\n // priming ticket that re-drives the store, so it must survive the retry\n // and clear on the next clean pass instead of vanishing with no request.\n if (await hasQueuedScopeWork(execSql, scope)) {\n await clearDocumentSyncFailure(execSql, scope);\n }\n}\n\n/**\n * Whether ANY durable outbound work exists for the scope — CRDT updates,\n * staged attachment uploads, move intents, a never-created local document, or\n * a deferred write whose only durable content is the history tail ahead of\n * its covered frontier. Mirrors the queue's own document candidate sources,\n * so \"failure-only\" here agrees with the item the panel rendered.\n */\nasync function hasQueuedScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(\n `SELECT 1 AS present\n WHERE EXISTS (\n SELECT 1 FROM document_history_updates pending\n WHERE pending.app_kind = ? AND pending.local_id = ?\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1 FROM document_pending_attachments attachment\n WHERE attachment.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM document_move_intents intent\n WHERE intent.local_id = ? AND intent.intent_type IN ('document.move', 'document.link')\n )\n OR EXISTS (\n SELECT 1 FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.document_id IS NULL\n )\n LIMIT 1`,\n [\n scope.appKind,\n scope.localId,\n scope.localId,\n scope.localId,\n scope.appKind,\n scope.localId,\n ],\n );\n if (rows.length > 0) {\n return true;\n }\n // The queue's deferred-update source has no queued rows to probe: the\n // write lives in the durable history tail, detectable only by the\n // version-vector coverage check.\n return hasDeferredTailScopeWork(execSql, scope);\n}\n"]}
@@ -3,7 +3,7 @@ import { assertContainerAuthorAccess } from "../../../data/containers/shared/aut
3
3
  import { assertContainerChildPathFits } from "../../../data/containers/shared/containerPathLimits.js";
4
4
  import { buildContainerCreateBody, buildContainerCreateKeyEpoch, buildParentRecipientTargets, deriveContainerCreateManifest, resolveContainerKekEpochId, signContainerCreateEvent, } from "../../../data/containers/shared/events.js";
5
5
  import { acknowledgeContainerMutation } from "../../../data/containers/shared/mutationAcknowledgement.js";
6
- import { asContainerManifestBundle, getParentCreateContext, readContainerState, wrapContainerKeyToManagedPrincipal, wrapContainerKeyToParent, } from "../../../data/containers/shared/projection.js";
6
+ import { containerManifestRef, getParentCreateContext, readContainerState, wrapContainerKeyToManagedPrincipal, wrapContainerKeyToParent, } from "../../../data/containers/shared/projection.js";
7
7
  import { assertContainerKekPathCurrent } from "../../../data/documents/shared/containerKekCurrency.js";
8
8
  import { unwrapContainerKekPath } from "../../../data/documents/shared/projection.js";
9
9
  import { projectionVerificationOptions, } from "../../../data/documents/shared/types.js";
@@ -28,8 +28,8 @@ function buildContainerCreateRequest(input) {
28
28
  ...input,
29
29
  userRecipientKeys: [],
30
30
  }),
31
- previousManifest: null,
32
- parentContainerPath: input.parentProjection.path.map(asContainerManifestBundle),
31
+ previousManifestRef: null,
32
+ parentContainerPathRefs: input.parentProjection.path.map(containerManifestRef),
33
33
  predecessorBridge: null,
34
34
  keyring: null,
35
35
  parentKekState: readCanonicalRecord(input.parentKek, "Container create parent KEK state"),