@tearleads/client-sdk 0.1.61 → 0.1.62

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 (273) hide show
  1. package/client/containerContents/documentDiscovery.js +5 -5
  2. package/client/containerContents/documentDiscovery.js.map +1 -1
  3. package/client/containerContents/index.d.ts +7 -7
  4. package/client/containerContents/index.js +7 -7
  5. package/client/containerContents/index.js.map +1 -1
  6. package/client/containerContents/types.d.ts +6 -6
  7. package/client/containerContents/types.js.map +1 -1
  8. package/client/deviceFirst/index.js +2 -2
  9. package/client/deviceFirst/index.js.map +1 -1
  10. package/package.json +1 -1
  11. package/stores/container-contents/containerStatePersistence.js +1 -1
  12. package/stores/container-contents/documentRecovery.js +2 -2
  13. package/stores/container-contents/documentRecovery.js.map +1 -1
  14. package/stores/container-contents/documentWork.js.map +1 -1
  15. package/stores/container-contents/localRefresh.js +2 -2
  16. package/stores/container-contents/localRefresh.js.map +1 -1
  17. package/stores/container-contents/operations.js +2 -2
  18. package/stores/container-contents/operations.js.map +1 -1
  19. package/stores/container-contents/remoteContainerIngestion.js +1 -1
  20. package/stores/container-contents/remoteEventSync.js +1 -1
  21. package/stores/container-contents/remoteHydrationRequest.js +1 -1
  22. package/stores/container-contents/setContainerIconOperation.js +2 -2
  23. package/stores/container-contents/setContainerIconOperation.js.map +1 -1
  24. package/stores/container-contents/shareOperations.js +1 -1
  25. package/stores/container-contents/startupHydration.js +1 -1
  26. package/stores/container-contents/syncAgent.d.ts +2 -2
  27. package/stores/container-contents/syncAgentTypes.d.ts +1 -1
  28. package/stores/container-contents/syncLaneIteration.js +2 -2
  29. package/stores/container-contents/syncLaneIteration.js.map +1 -1
  30. package/stores/container-contents/systemContainerIcon.js +1 -1
  31. package/stores/container-contents/systemContainerIcon.js.map +1 -1
  32. package/workflows/container-contents/{documentAttributionRanges.d.ts → attribution/documentAttributionRanges.d.ts} +1 -1
  33. package/workflows/container-contents/{documentCharacterBlame.js → attribution/documentCharacterBlame.js} +3 -3
  34. package/workflows/container-contents/attribution/documentCharacterBlame.js.map +1 -0
  35. package/workflows/container-contents/{documentFieldBlame.js → attribution/documentFieldBlame.js} +4 -4
  36. package/workflows/container-contents/attribution/documentFieldBlame.js.map +1 -0
  37. package/workflows/container-contents/container-state/createIntentSync.js +1 -1
  38. package/workflows/container-contents/container-state/createIntentSync.js.map +1 -1
  39. package/workflows/container-contents/container-state/moveIntentSync.js +1 -1
  40. package/workflows/container-contents/container-state/moveIntentSync.js.map +1 -1
  41. package/workflows/container-contents/container-state/purgeTree.js +2 -2
  42. package/workflows/container-contents/container-state/purgeTree.js.map +1 -1
  43. package/workflows/container-contents/container-state/sharePersistence.js +2 -2
  44. package/workflows/container-contents/container-state/sharePersistence.js.map +1 -1
  45. package/workflows/container-contents/{containerDocumentListing.js → documentDiscovery/containerDocumentListing.js} +1 -1
  46. package/workflows/container-contents/{documentDiscoveryApply.js → documentDiscovery/documentDiscoveryApply.js} +3 -3
  47. package/workflows/container-contents/documentDiscovery/documentDiscoveryApply.js.map +1 -0
  48. package/workflows/container-contents/{documentDiscoveryCandidates.js.map → documentDiscovery/documentDiscoveryCandidates.js.map} +1 -1
  49. package/workflows/container-contents/{documentDiscoveryEvidence.js → documentDiscovery/documentDiscoveryEvidence.js} +1 -1
  50. package/workflows/container-contents/documentDiscovery/documentDiscoveryEvidence.js.map +1 -0
  51. package/workflows/container-contents/{documentDiscoveryInputs.js → documentDiscovery/documentDiscoveryInputs.js} +2 -2
  52. package/workflows/container-contents/documentDiscovery/documentDiscoveryInputs.js.map +1 -0
  53. package/workflows/container-contents/documentDiscovery/documentDiscoveryLanes.js.map +1 -0
  54. package/workflows/container-contents/{documentDiscoveryTypes.d.ts → documentDiscovery/documentDiscoveryTypes.d.ts} +4 -4
  55. package/workflows/container-contents/documentDiscovery/documentDiscoveryTypes.js.map +1 -0
  56. package/workflows/container-contents/{documentDiscovery.d.ts → documentDiscovery/index.d.ts} +1 -1
  57. package/workflows/container-contents/{documentDiscovery.js → documentDiscovery/index.js} +5 -5
  58. package/workflows/container-contents/documentDiscovery/index.js.map +1 -0
  59. package/workflows/container-contents/{availableDocumentLinkIntent.js → documentLinks/availableDocumentLinkIntent.js} +1 -1
  60. package/workflows/container-contents/documentLinks/availableDocumentLinkIntent.js.map +1 -0
  61. package/workflows/container-contents/{deferredDocumentLinks.js → documentLinks/deferredDocumentLinks.js} +1 -1
  62. package/workflows/container-contents/documentLinks/deferredDocumentLinks.js.map +1 -0
  63. package/workflows/container-contents/{documentLinkIntent.js → documentLinks/documentLinkIntent.js} +4 -4
  64. package/workflows/container-contents/documentLinks/documentLinkIntent.js.map +1 -0
  65. package/workflows/container-contents/documentLinks/documentLocalRelink.js.map +1 -0
  66. package/workflows/container-contents/{documentLinks.d.ts → documentLinks/index.d.ts} +5 -5
  67. package/workflows/container-contents/{documentLinks.js → documentLinks/index.js} +10 -10
  68. package/workflows/container-contents/documentLinks/index.js.map +1 -0
  69. package/workflows/container-contents/documentMove/documentMoveDeniedReplay.js.map +1 -0
  70. package/workflows/container-contents/{documentMoveFailure.js → documentMove/documentMoveFailure.js} +1 -1
  71. package/workflows/container-contents/documentMove/documentMoveFailure.js.map +1 -0
  72. package/workflows/container-contents/{documentMoveIntent.js → documentMove/documentMoveIntent.js} +7 -7
  73. package/workflows/container-contents/documentMove/documentMoveIntent.js.map +1 -0
  74. package/workflows/container-contents/{documentMoveIntentErrors.js → documentMove/documentMoveIntentErrors.js} +1 -1
  75. package/workflows/container-contents/documentMove/documentMoveIntentErrors.js.map +1 -0
  76. package/workflows/container-contents/{documentMoveIntentSettlement.js → documentMove/documentMoveIntentSettlement.js} +4 -4
  77. package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js.map +1 -0
  78. package/workflows/container-contents/{documentMoveIntentSync.js → documentMove/documentMoveIntentSync.js} +7 -7
  79. package/workflows/container-contents/documentMove/documentMoveIntentSync.js.map +1 -0
  80. package/workflows/container-contents/{documentMoveVanishedRefresh.js → documentMove/documentMoveVanishedRefresh.js} +3 -3
  81. package/workflows/container-contents/documentMove/documentMoveVanishedRefresh.js.map +1 -0
  82. package/workflows/container-contents/{documentHydrationProbe.js → documentPriming/documentHydrationProbe.js} +4 -4
  83. package/workflows/container-contents/documentPriming/documentHydrationProbe.js.map +1 -0
  84. package/workflows/container-contents/documentPriming/documentRuntimeTargetSync.js.map +1 -0
  85. package/workflows/container-contents/{documentPriming.js → documentPriming/index.js} +5 -5
  86. package/workflows/container-contents/documentPriming/index.js.map +1 -0
  87. package/workflows/container-contents/{documentStructure.d.ts → documentQueries/documentStructure.d.ts} +1 -1
  88. package/workflows/container-contents/{documentStructure.js → documentQueries/documentStructure.js} +4 -4
  89. package/workflows/container-contents/documentQueries/documentStructure.js.map +1 -0
  90. package/workflows/container-contents/{documentStructureTypes.d.ts → documentQueries/documentStructureTypes.d.ts} +4 -4
  91. package/workflows/container-contents/documentQueries/documentStructureTypes.js.map +1 -0
  92. package/workflows/container-contents/{documentSubtreeQueries.js → documentQueries/documentSubtreeQueries.js} +5 -5
  93. package/workflows/container-contents/documentQueries/documentSubtreeQueries.js.map +1 -0
  94. package/workflows/container-contents/{documentQueries.d.ts → documentQueries/index.d.ts} +8 -8
  95. package/workflows/container-contents/{documentQueries.js → documentQueries/index.js} +13 -13
  96. package/workflows/container-contents/documentQueries/index.js.map +1 -0
  97. package/workflows/container-contents/{orphanedDocumentSql.js → documentQueries/orphanedDocumentSql.js} +1 -1
  98. package/workflows/container-contents/documentQueries/orphanedDocumentSql.js.map +1 -0
  99. package/workflows/container-contents/{pendingDownloads.d.ts → documentQueries/pendingDownloads.d.ts} +1 -1
  100. package/workflows/container-contents/{pendingDownloads.js → documentQueries/pendingDownloads.js} +3 -3
  101. package/workflows/container-contents/documentQueries/pendingDownloads.js.map +1 -0
  102. package/workflows/container-contents/documentQueries/sql.js +1 -1
  103. package/workflows/container-contents/documentQueries/sql.js.map +1 -1
  104. package/workflows/container-contents/index.d.ts +13 -13
  105. package/workflows/container-contents/index.js +11 -11
  106. package/workflows/container-contents/index.js.map +1 -1
  107. package/workflows/container-contents/{blobInfo.d.ts → info/blobInfo.d.ts} +1 -1
  108. package/workflows/container-contents/{blobInfo.js → info/blobInfo.js} +4 -4
  109. package/workflows/container-contents/info/blobInfo.js.map +1 -0
  110. package/workflows/container-contents/{blobInfoTypes.d.ts → info/blobInfoTypes.d.ts} +1 -1
  111. package/workflows/container-contents/info/blobInfoTypes.js.map +1 -0
  112. package/workflows/container-contents/{containerInfo.d.ts → info/containerInfo.d.ts} +4 -4
  113. package/workflows/container-contents/{containerInfo.js → info/containerInfo.js} +5 -5
  114. package/workflows/container-contents/info/containerInfo.js.map +1 -0
  115. package/workflows/container-contents/{documentInfo.d.ts → info/documentInfo.d.ts} +3 -3
  116. package/workflows/container-contents/{documentInfo.js → info/documentInfo.js} +11 -11
  117. package/workflows/container-contents/info/documentInfo.js.map +1 -0
  118. package/workflows/container-contents/{documentInfoTypes.d.ts → info/documentInfoTypes.d.ts} +3 -3
  119. package/workflows/container-contents/info/documentInfoTypes.js.map +1 -0
  120. package/workflows/container-contents/{metadata.d.ts → metadata/index.d.ts} +2 -2
  121. package/workflows/container-contents/{metadata.js → metadata/index.js} +5 -5
  122. package/workflows/container-contents/metadata/index.js.map +1 -0
  123. package/workflows/container-contents/{metadataEvents.d.ts → metadata/metadataEvents.d.ts} +1 -1
  124. package/workflows/container-contents/{metadataEvents.js → metadata/metadataEvents.js} +1 -1
  125. package/workflows/container-contents/metadata/metadataEvents.js.map +1 -0
  126. package/workflows/container-contents/{metadataIncomingUpdateIsolation.js → metadata/metadataIncomingUpdateIsolation.js} +5 -5
  127. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -0
  128. package/workflows/container-contents/{metadataMutationPreparation.d.ts → metadata/metadataMutationPreparation.d.ts} +7 -7
  129. package/workflows/container-contents/{metadataMutationPreparation.js → metadata/metadataMutationPreparation.js} +5 -5
  130. package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -0
  131. package/workflows/container-contents/{metadataPersistence.d.ts → metadata/metadataPersistence.d.ts} +2 -2
  132. package/workflows/container-contents/{metadataPersistence.js → metadata/metadataPersistence.js} +4 -4
  133. package/workflows/container-contents/metadata/metadataPersistence.js.map +1 -0
  134. package/workflows/container-contents/{metadataPullContinuationInvalidation.js → metadata/metadataPullContinuationInvalidation.js} +4 -4
  135. package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js.map +1 -0
  136. package/workflows/container-contents/{metadataReadState.d.ts → metadata/metadataReadState.d.ts} +1 -1
  137. package/workflows/container-contents/metadata/metadataReadState.js.map +1 -0
  138. package/workflows/container-contents/{metadataRecord.js → metadata/metadataRecord.js} +2 -2
  139. package/workflows/container-contents/metadata/metadataRecord.js.map +1 -0
  140. package/workflows/container-contents/{metadataRemoteSync.d.ts → metadata/metadataRemoteSync.d.ts} +5 -5
  141. package/workflows/container-contents/{metadataRemoteSync.js → metadata/metadataRemoteSync.js} +3 -3
  142. package/workflows/container-contents/metadata/metadataRemoteSync.js.map +1 -0
  143. package/workflows/container-contents/{metadataStateInstallation.d.ts → metadata/metadataStateInstallation.d.ts} +1 -1
  144. package/workflows/container-contents/metadata/metadataStateInstallation.js.map +1 -0
  145. package/workflows/container-contents/{metadataStateIsolation.js → metadata/metadataStateIsolation.js} +3 -3
  146. package/workflows/container-contents/metadata/metadataStateIsolation.js.map +1 -0
  147. package/workflows/container-contents/{metadataSyncErrors.js → metadata/metadataSyncErrors.js} +3 -3
  148. package/workflows/container-contents/metadata/metadataSyncErrors.js.map +1 -0
  149. package/workflows/container-contents/{metadataSyncSettlement.d.ts → metadata/metadataSyncSettlement.d.ts} +2 -2
  150. package/workflows/container-contents/{metadataSyncSettlement.js → metadata/metadataSyncSettlement.js} +3 -3
  151. package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -0
  152. package/workflows/container-contents/{metadataTypes.d.ts → metadata/metadataTypes.d.ts} +5 -5
  153. package/workflows/container-contents/metadata/metadataTypes.js.map +1 -0
  154. package/workflows/container-contents/pendingWrites/aggregation.js.map +1 -1
  155. package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
  156. package/workflows/container-contents/{pendingWrites.d.ts → pendingWrites/index.d.ts} +1 -1
  157. package/workflows/container-contents/{pendingWrites.js → pendingWrites/index.js} +12 -12
  158. package/workflows/container-contents/pendingWrites/index.js.map +1 -0
  159. package/workflows/container-contents/projectionGeneration.js.map +1 -1
  160. package/workflows/container-contents/projectionView.js +1 -1
  161. package/workflows/container-contents/projectionView.js.map +1 -1
  162. package/workflows/container-contents/{folderRecovery.d.ts → recovery/folderRecovery.d.ts} +1 -1
  163. package/workflows/container-contents/{folderRecovery.js → recovery/folderRecovery.js} +4 -4
  164. package/workflows/container-contents/recovery/folderRecovery.js.map +1 -0
  165. package/workflows/container-contents/{staleRootRecovery.js → recovery/staleRootRecovery.js} +1 -1
  166. package/workflows/container-contents/recovery/staleRootRecovery.js.map +1 -0
  167. package/workflows/container-contents/remoteHydration/completeHydration.js +1 -1
  168. package/workflows/container-contents/remoteHydration/completeHydration.js.map +1 -1
  169. package/workflows/container-contents/remoteHydration/heldContainerRebind.js +1 -1
  170. package/workflows/container-contents/remoteHydration/heldContainerRebind.js.map +1 -1
  171. package/workflows/container-contents/{remoteHydration.d.ts → remoteHydration/index.d.ts} +2 -2
  172. package/workflows/container-contents/{remoteHydration.js → remoteHydration/index.js} +6 -6
  173. package/workflows/container-contents/remoteHydration/index.js.map +1 -0
  174. package/workflows/container-contents/{remoteContainerPageHydration.js → remoteHydration/remoteContainerPageHydration.js} +8 -8
  175. package/workflows/container-contents/remoteHydration/remoteContainerPageHydration.js.map +1 -0
  176. package/workflows/container-contents/{remoteContainerState.js → remoteHydration/remoteContainerState.js} +11 -11
  177. package/workflows/container-contents/remoteHydration/remoteContainerState.js.map +1 -0
  178. package/workflows/container-contents/remoteHydration/types.d.ts +1 -1
  179. package/workflows/container-contents/{documentPurge.d.ts → tombstones/documentPurge.d.ts} +6 -6
  180. package/workflows/container-contents/{documentPurge.js → tombstones/documentPurge.js} +6 -6
  181. package/workflows/container-contents/tombstones/documentPurge.js.map +1 -0
  182. package/workflows/container-contents/{documentTombstoneEvidence.js → tombstones/documentTombstoneEvidence.js} +9 -9
  183. package/workflows/container-contents/tombstones/documentTombstoneEvidence.js.map +1 -0
  184. package/workflows/container-contents/{documentTombstoneGate.js → tombstones/documentTombstoneGate.js} +1 -1
  185. package/workflows/container-contents/tombstones/documentTombstoneGate.js.map +1 -0
  186. package/workflows/container-contents/availableDocumentLinkIntent.js.map +0 -1
  187. package/workflows/container-contents/blobInfo.js.map +0 -1
  188. package/workflows/container-contents/blobInfoTypes.js.map +0 -1
  189. package/workflows/container-contents/containerInfo.js.map +0 -1
  190. package/workflows/container-contents/deferredDocumentLinks.js.map +0 -1
  191. package/workflows/container-contents/documentCharacterBlame.js.map +0 -1
  192. package/workflows/container-contents/documentDiscovery.js.map +0 -1
  193. package/workflows/container-contents/documentDiscoveryApply.js.map +0 -1
  194. package/workflows/container-contents/documentDiscoveryEvidence.js.map +0 -1
  195. package/workflows/container-contents/documentDiscoveryInputs.js.map +0 -1
  196. package/workflows/container-contents/documentDiscoveryLanes.js.map +0 -1
  197. package/workflows/container-contents/documentDiscoveryTypes.js.map +0 -1
  198. package/workflows/container-contents/documentFieldBlame.js.map +0 -1
  199. package/workflows/container-contents/documentHydrationProbe.js.map +0 -1
  200. package/workflows/container-contents/documentInfo.js.map +0 -1
  201. package/workflows/container-contents/documentInfoTypes.js.map +0 -1
  202. package/workflows/container-contents/documentLinkIntent.js.map +0 -1
  203. package/workflows/container-contents/documentLinks.js.map +0 -1
  204. package/workflows/container-contents/documentLocalRelink.js.map +0 -1
  205. package/workflows/container-contents/documentMoveDeniedReplay.js.map +0 -1
  206. package/workflows/container-contents/documentMoveFailure.js.map +0 -1
  207. package/workflows/container-contents/documentMoveIntent.js.map +0 -1
  208. package/workflows/container-contents/documentMoveIntentErrors.js.map +0 -1
  209. package/workflows/container-contents/documentMoveIntentSettlement.js.map +0 -1
  210. package/workflows/container-contents/documentMoveIntentSync.js.map +0 -1
  211. package/workflows/container-contents/documentMoveVanishedRefresh.js.map +0 -1
  212. package/workflows/container-contents/documentPriming.js.map +0 -1
  213. package/workflows/container-contents/documentPurge.js.map +0 -1
  214. package/workflows/container-contents/documentQueries.js.map +0 -1
  215. package/workflows/container-contents/documentRuntimeTargetSync.js.map +0 -1
  216. package/workflows/container-contents/documentStructure.js.map +0 -1
  217. package/workflows/container-contents/documentStructureTypes.js.map +0 -1
  218. package/workflows/container-contents/documentSubtreeQueries.js.map +0 -1
  219. package/workflows/container-contents/documentTombstoneEvidence.js.map +0 -1
  220. package/workflows/container-contents/documentTombstoneGate.js.map +0 -1
  221. package/workflows/container-contents/folderRecovery.js.map +0 -1
  222. package/workflows/container-contents/metadata.js.map +0 -1
  223. package/workflows/container-contents/metadataEvents.js.map +0 -1
  224. package/workflows/container-contents/metadataIncomingUpdateIsolation.js.map +0 -1
  225. package/workflows/container-contents/metadataMutationPreparation.js.map +0 -1
  226. package/workflows/container-contents/metadataPersistence.js.map +0 -1
  227. package/workflows/container-contents/metadataPullContinuationInvalidation.js.map +0 -1
  228. package/workflows/container-contents/metadataReadState.js.map +0 -1
  229. package/workflows/container-contents/metadataRecord.js.map +0 -1
  230. package/workflows/container-contents/metadataRemoteSync.js.map +0 -1
  231. package/workflows/container-contents/metadataStateInstallation.js.map +0 -1
  232. package/workflows/container-contents/metadataStateIsolation.js.map +0 -1
  233. package/workflows/container-contents/metadataSyncErrors.js.map +0 -1
  234. package/workflows/container-contents/metadataSyncSettlement.js.map +0 -1
  235. package/workflows/container-contents/metadataTypes.js.map +0 -1
  236. package/workflows/container-contents/orphanedDocumentSql.js.map +0 -1
  237. package/workflows/container-contents/pendingDownloads.js.map +0 -1
  238. package/workflows/container-contents/pendingWrites.js.map +0 -1
  239. package/workflows/container-contents/remoteContainerPageHydration.js.map +0 -1
  240. package/workflows/container-contents/remoteContainerState.js.map +0 -1
  241. package/workflows/container-contents/remoteHydration.js.map +0 -1
  242. package/workflows/container-contents/staleRootRecovery.js.map +0 -1
  243. /package/workflows/container-contents/{documentAttributionRanges.js → attribution/documentAttributionRanges.js} +0 -0
  244. /package/workflows/container-contents/{documentAttributionRanges.js.map → attribution/documentAttributionRanges.js.map} +0 -0
  245. /package/workflows/container-contents/{containerDocumentListing.js.map → documentDiscovery/containerDocumentListing.js.map} +0 -0
  246. /package/workflows/container-contents/{documentDiscoveryCandidates.js → documentDiscovery/documentDiscoveryCandidates.js} +0 -0
  247. /package/workflows/container-contents/{documentDiscoveryLanes.js → documentDiscovery/documentDiscoveryLanes.js} +0 -0
  248. /package/workflows/container-contents/{documentDiscoveryTypes.js → documentDiscovery/documentDiscoveryTypes.js} +0 -0
  249. /package/workflows/container-contents/{documentHeadScope.js → documentDiscovery/documentHeadScope.js} +0 -0
  250. /package/workflows/container-contents/{documentHeadScope.js.map → documentDiscovery/documentHeadScope.js.map} +0 -0
  251. /package/workflows/container-contents/{documentLocalRelink.js → documentLinks/documentLocalRelink.js} +0 -0
  252. /package/workflows/container-contents/{documentMoveDeniedReplay.js → documentMove/documentMoveDeniedReplay.js} +0 -0
  253. /package/workflows/container-contents/{documentMoveUnlinkIds.js → documentMove/documentMoveUnlinkIds.js} +0 -0
  254. /package/workflows/container-contents/{documentMoveUnlinkIds.js.map → documentMove/documentMoveUnlinkIds.js.map} +0 -0
  255. /package/workflows/container-contents/{documentRuntimeTargetSync.js → documentPriming/documentRuntimeTargetSync.js} +0 -0
  256. /package/workflows/container-contents/{documentStructureTypes.js → documentQueries/documentStructureTypes.js} +0 -0
  257. /package/workflows/container-contents/{blobInfoRows.js → info/blobInfoRows.js} +0 -0
  258. /package/workflows/container-contents/{blobInfoRows.js.map → info/blobInfoRows.js.map} +0 -0
  259. /package/workflows/container-contents/{blobInfoTypes.js → info/blobInfoTypes.js} +0 -0
  260. /package/workflows/container-contents/{documentInfoTypes.js → info/documentInfoTypes.js} +0 -0
  261. /package/workflows/container-contents/{metadataReadState.js → metadata/metadataReadState.js} +0 -0
  262. /package/workflows/container-contents/{metadataStateInstallation.js → metadata/metadataStateInstallation.js} +0 -0
  263. /package/workflows/container-contents/{metadataSyncFollowup.js → metadata/metadataSyncFollowup.js} +0 -0
  264. /package/workflows/container-contents/{metadataSyncFollowup.js.map → metadata/metadataSyncFollowup.js.map} +0 -0
  265. /package/workflows/container-contents/{metadataSyncRegistrations.d.ts → metadata/metadataSyncRegistrations.d.ts} +0 -0
  266. /package/workflows/container-contents/{metadataSyncRegistrations.js → metadata/metadataSyncRegistrations.js} +0 -0
  267. /package/workflows/container-contents/{metadataSyncRegistrations.js.map → metadata/metadataSyncRegistrations.js.map} +0 -0
  268. /package/workflows/container-contents/{metadataTypes.js → metadata/metadataTypes.js} +0 -0
  269. /package/workflows/container-contents/{pendingWritesTypes.d.ts → pendingWrites/pendingWritesTypes.d.ts} +0 -0
  270. /package/workflows/container-contents/{pendingWritesTypes.js → pendingWrites/pendingWritesTypes.js} +0 -0
  271. /package/workflows/container-contents/{pendingWritesTypes.js.map → pendingWrites/pendingWritesTypes.js.map} +0 -0
  272. /package/workflows/container-contents/{remoteHydrationLog.js → remoteHydration/remoteHydrationLog.js} +0 -0
  273. /package/workflows/container-contents/{remoteHydrationLog.js.map → remoteHydration/remoteHydrationLog.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentLocalRelink.js","sourceRoot":"","sources":["documentLocalRelink.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAW,MAW9D;IACC,MAAM,EACJ,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,WAAW,EACX,OAAO,EACP,iBAAiB,GAClB,GAAG,MAAM,CAAC;IAEX,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC;QACrD,WAAW;QACX,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;QAC7D,WAAW,EAAE,iBAAiB;QAC9B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,GAAG,WAAW;QACd,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,OAAO,EAAE,IAAI,CAAC,EAAE;KACjB,CAAC,CAAC;IACH,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,GAAG,CACd,4BAA4B,IAAI,CAAC,EAAE,oDAAoD,CACxF,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACxC,oBAAoB,CAAC,aAAa,CAChC,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAChD,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,oBAAoB,CAAC,WAAW,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport type { RemoteDocumentPersistedState } from \"./documentLinks\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRelinkInput,\n DocumentStructuralMutationRuntime,\n} from \"./documentStructureTypes\";\n\nexport async function relinkContainerDocumentLocally<TRuntime>(params: {\n accessEpoch: number;\n commitSideEffect?: DocumentStructuralMutationRelinkInput[\"commitSideEffect\"];\n accessStateHash?: string | null | undefined;\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n remoteState?: RemoteDocumentPersistedState | undefined;\n requestSync: boolean;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}) {\n const {\n accessEpoch,\n accessStateHash,\n currentDocumentStore,\n host,\n note,\n remoteState,\n requestSync,\n runtime,\n targetContainerId,\n } = params;\n\n const relinkedNote = await currentDocumentStore.relink({\n accessEpoch,\n ...(accessStateHash === undefined ? {} : { accessStateHash }),\n containerId: targetContainerId,\n commitSideEffect: params.commitSideEffect,\n ...remoteState,\n documentId: note.documentId,\n localId: note.id,\n });\n if (!relinkedNote) {\n runtime.util.log(\n `Container contents: note ${note.id} could not be relinked after a structural mutation`,\n );\n return null;\n }\n\n host.mergeDocumentSummary(relinkedNote);\n currentDocumentStore.updateRuntime(\n host.documentWorkflowRuntime(targetContainerId),\n );\n if (requestSync) {\n currentDocumentStore.requestSync();\n }\n return relinkedNote;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveDeniedReplay.js","sourceRoot":"","sources":["documentMoveDeniedReplay.ts"],"names":[],"mappings":"AAaA,+EAA+E;AAC/E,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,gFAAgF;AAChF,yEAAyE;AACzE,8CAA8C;AAC9C,MAAM,6BAA6B,GAAG,IAAI,OAAO,EAG9C,CAAC;AAEJ,MAAM,UAAU,6BAA6B,CAC3C,KAA4B,EAC5B,OAAgB;IAEhB,MAAM,SAAS,GAAG,6BAA6B,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3D,OAAO,CACL,SAAS,EAAE,OAAO,KAAK,OAAO;QAC9B,SAAS,CAAC,mBAAmB,KAAK,KAAK,CAAC,mBAAmB,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,KAA4B,EAC5B,OAAgB;IAEhB,6BAA6B,CAAC,GAAG,CAAC,KAAK,EAAE;QACvC,OAAO;QACP,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;KAC/C,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\ntype ExecSql = ContainerContentsWorkflowRuntime[\"infra\"][\"execSql\"];\n\ninterface DeniedReplayLifecycle {\n readonly lifecycleGeneration?: number | undefined;\n}\n\ninterface DeniedReplayGeneration {\n execSql: ExecSql;\n lifecycleGeneration: number | undefined;\n}\n\n// One replay per store/database generation: parked denied intents flip back to\n// pending ahead of its first scan (row 7). A restart loses the in-memory\n// access-restored edge, and replacing the executor or lifecycle can expose a\n// different durable queue. Running inside the scan keeps ordering trivially\n// correct: replayed intents are attempted by this same pass, not stranded until\n// an unrelated trigger. Marked complete only after the reset lands, so a\n// transient failure retries on the next pass.\nconst deniedReplayGenerationByState = new WeakMap<\n DeniedReplayLifecycle,\n DeniedReplayGeneration\n>();\n\nexport function deniedReplayMatchesGeneration(\n state: DeniedReplayLifecycle,\n execSql: ExecSql,\n): boolean {\n const completed = deniedReplayGenerationByState.get(state);\n return (\n completed?.execSql === execSql &&\n completed.lifecycleGeneration === state.lifecycleGeneration\n );\n}\n\nexport function markDeniedReplayGeneration(\n state: DeniedReplayLifecycle,\n execSql: ExecSql,\n): void {\n deniedReplayGenerationByState.set(state, {\n execSql,\n lifecycleGeneration: state.lifecycleGeneration,\n });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveFailure.js","sourceRoot":"","sources":["documentMoveFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAsB3F,MAAM,UAAU,8BAA8B;IAC5C,OAAO;QACL,OAAO,EAAE,IAAI;QACb,mBAAmB,EAAE,KAAK;QAC1B,oBAAoB,EAAE,KAAK;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAA+B,EAC/B,OAAuC;IAEvC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,KAAK,CAAC,mBAAmB;QACvB,KAAK,CAAC,mBAAmB,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,CAAC;IACtD,KAAK,CAAC,oBAAoB;QACxB,KAAK,CAAC,oBAAoB,IAAI,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAA+B;IAE/B,MAAM,MAAM,GAAG,KAAK,CAAC,oBAAoB;QACvC,CAAC,CAAC,8DAA8D;QAChE,CAAC,CAAC,kDAAkD,CAAC;IACvD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,KAAK,IAAI;QACrB,CAAC,CAAC,OAAO,CAAC,OAAO;QACjB,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC;IAC/C,OAAO,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import { isVanishedContainerFailure } from \"../../data/containers/shared/mutationFailures\";\nimport type { DocumentLinkSetMutationFailure } from \"../documents\";\n\n/**\n * What a queued document move learned from its remote link/unlink attempts.\n * Every failure handed to the move's `onFailure` folds into this state; the\n * verdict (`pending`, `blocked`, `denied`) is read off it afterwards.\n */\nexport interface DocumentMoveFailureState {\n current: DocumentLinkSetMutationFailure | null;\n /** A 403 anywhere in the pass parks the intent as denied (row 7). */\n sawPermissionDenial: boolean;\n /**\n * The server proved a cited container no longer exists (coded projection\n * 404 or coded commit 409 `container_unavailable`). Retrying the SAME\n * request can never succeed — but the cited container may be a stale\n * ancestor in a cached path, so the verdict triggers a projection refresh\n * (documentMoveVanishedRefresh) before the intent parks terminally.\n */\n sawVanishedContainer: boolean;\n}\n\nexport function createDocumentMoveFailureState(): DocumentMoveFailureState {\n return {\n current: null,\n sawPermissionDenial: false,\n sawVanishedContainer: false,\n };\n}\n\nexport function recordDocumentMoveFailure(\n state: DocumentMoveFailureState,\n failure: DocumentLinkSetMutationFailure,\n): void {\n state.current = failure;\n state.sawPermissionDenial =\n state.sawPermissionDenial || failure.status === 403;\n state.sawVanishedContainer =\n state.sawVanishedContainer || isVanishedContainerFailure(failure);\n}\n\n/**\n * The queue-facing description of a failed remote move. The stable prefixes\n * are kept so existing consumers keep matching; the captured detail appends\n * the HTTP status when one was seen, so a revoked permission (403) reads\n * differently from an offline blip.\n */\nexport function describeRejectedDocumentMove(\n state: DocumentMoveFailureState,\n): string {\n const prefix = state.sawVanishedContainer\n ? \"Remote document move cites a container deleted on the server\"\n : \"Remote document move was rejected or unavailable\";\n const failure = state.current;\n if (!failure) {\n return prefix;\n }\n const detail =\n failure.status === null\n ? failure.message\n : `${failure.message} (${failure.status})`;\n return `${prefix}: ${detail}`;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveIntent.js","sourceRoot":"","sources":["documentMoveIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,gCAAgC,EAAE,MAAM,yEAAyE,CAAC;AAC3H,OAAO,EAAE,yCAAyC,EAAE,MAAM,0EAA0E,CAAC;AACrI,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAQvE,KAAK,UAAU,kCAAkC,CAAC,KAMjD;IACC,IAAI,KAAK,CAAC,uBAAuB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,yBAAyB,GAAG,MAAM,8BAA8B,CACpE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B,KAAK,CAAC,UAAU,CACjB,CAAC;IACF,MAAM,kBAAkB,GACtB,yBAAyB,CAAC,MAAM,GAAG,CAAC;QAClC,CAAC,CAAC,yBAAyB;QAC3B,CAAC,CAAC,KAAK,CAAC,kBAAkB;YACxB,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;YAC5B,CAAC,CAAC,EAAE,CAAC;IAEX,OAAO,mBAAmB,CAAC;QACzB,GAAG,kBAAkB,CAAC,MAAM,CAC1B,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,KAAK,KAAK,CAAC,kBAAkB,CAC1D;QACD,KAAK,CAAC,iBAAiB;KACxB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,2BAA2B,CAAC,KAG1C;IACC,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,CAAC,YAAY,CACrE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B,KAAK,CAAC,OAAO,CACd,CAAC;IACF,4EAA4E;IAC5E,yEAAyE;IACzE,sDAAsD;IACtD,OAAO,gBAAgB,EAAE,WAAW,IAAI,6BAA6B,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAW,MAU7D;IACC,MAAM,EACJ,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,uBAAuB,EACvB,OAAO,EACP,YAAY,EACZ,gCAAgC,EAChC,iBAAiB,GAClB,GAAG,MAAM,CAAC;IACX,MAAM,kBAAkB,GAAG,MAAM,kCAAkC,CAAC;QAClE,kBAAkB,EAAE,IAAI,CAAC,WAAW;QACpC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,uBAAuB;QACvB,OAAO;QACP,iBAAiB;KAClB,CAAC,CAAC;IAEH,wEAAwE;IACxE,8EAA8E;IAC9E,6EAA6E;IAC7E,4EAA4E;IAC5E,mBAAmB;IACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAErC,MAAM,SAAS,GAAG,MAAM,8BAA8B,CAAC;QACrD,WAAW,EAAE,MAAM,2BAA2B,CAAC;YAC7C,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,OAAO;SACR,CAAC;QACF,oBAAoB;QACpB,IAAI;QACJ,IAAI;QACJ,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAClC,MAAM,gCAAgC,CAAC,iBAAiB,CAAC,OAAO,EAAE;gBAChE,EAAE,EAAE,QAAQ;gBACZ,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,OAAO,EAAE,IAAI,CAAC,EAAE;gBAChB,uBAAuB;gBACvB,iBAAiB,EAAE,IAAI,CAAC,WAAW;gBACnC,iBAAiB;aAClB,CAAC,CAAC;YACH,MAAM,yCAAyC,CAAC,oBAAoB,CAClE,OAAO,EACP,IAAI,CAAC,UAAU,EACf,kBAAkB,EAClB,EAAE,YAAY,EAAE,QAAQ,EAAE,CAC3B,CAAC;QACJ,CAAC;QACD,WAAW,EAAE,KAAK;QAClB,OAAO;QACP,iBAAiB;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,gCAAgC,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IACtE,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC9B,YAAY,EAAE,EAAE,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,GAAG,CACd,mCAAmC,SAAS,CAAC,EAAE,YAAY,iBAAiB,EAAE,CAC/E,CAAC;IACF,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACjD,CAAC","sourcesContent":["import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from \"../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { uniqueSortedStrings } from \"../../data/documents/shared/readers\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { defaultDocumentsPersistence } from \"../documents\";\nimport { listDocumentLinkedContainerIds } from \"./documentLinks\";\nimport { relinkContainerDocumentLocally } from \"./documentLocalRelink\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRuntime,\n SetLinkedContainerIdsForDocument,\n} from \"./documentStructureTypes\";\n\nasync function resolveOptimisticDocumentMoveLinks(input: {\n currentContainerId: string | null;\n documentId: string;\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}): Promise<string[]> {\n if (input.replaceLinkedContainers) {\n return [input.targetContainerId];\n }\n\n const currentLinkedContainerIds = await listDocumentLinkedContainerIds(\n input.runtime.infra.execSql,\n input.documentId,\n );\n const linkedContainerIds =\n currentLinkedContainerIds.length > 0\n ? currentLinkedContainerIds\n : input.currentContainerId\n ? [input.currentContainerId]\n : [];\n\n return uniqueSortedStrings([\n ...linkedContainerIds.filter(\n (containerId) => containerId !== input.currentContainerId,\n ),\n input.targetContainerId,\n ]);\n}\n\nasync function resolveLocalMoveAccessEpoch(input: {\n localId: string;\n runtime: DocumentStructuralMutationRuntime;\n}): Promise<number> {\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n input.runtime.infra.execSql,\n input.localId,\n );\n // The local relink must keep the document's current key epoch. Falling back\n // is only for partially seeded local state; downgrading synced documents\n // would make offline edits use stale access material.\n return existingDocument?.accessEpoch ?? DEFAULT_DOCUMENT_ACCESS_EPOCH;\n}\n\nexport async function moveRemoteDocumentLinkLocally<TRuntime>(params: {\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n expandNode: (nodeId: string) => void;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary & { documentId: string };\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<{ linksChanged: boolean; note: DocumentSummary | null }> {\n const {\n currentDocumentStore,\n expandNode,\n host,\n note,\n replaceLinkedContainers,\n runtime,\n scheduleSync,\n setLinkedContainerIdsForDocument,\n targetContainerId,\n } = params;\n const linkedContainerIds = await resolveOptimisticDocumentMoveLinks({\n currentContainerId: note.containerId,\n documentId: note.documentId,\n replaceLinkedContainers,\n runtime,\n targetContainerId,\n });\n\n // Apply the user's chosen placement locally now, then replay the signed\n // link-set mutation from this durable intent when auth/network/key context is\n // back. This mirrors container move intents: UI state should not wait on the\n // server, but the remote contract still converges through the normal writer\n // projection path.\n const intentId = crypto.randomUUID();\n\n const movedNote = await relinkContainerDocumentLocally({\n accessEpoch: await resolveLocalMoveAccessEpoch({\n localId: note.id,\n runtime,\n }),\n currentDocumentStore,\n host,\n note,\n commitSideEffect: async (execSql) => {\n await sqlDocumentMoveIntentPersistence.enqueueMoveIntent(execSql, {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n replaceLinkedContainers,\n sourceContainerId: note.containerId,\n targetContainerId,\n });\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n requestSync: false,\n runtime,\n targetContainerId,\n });\n if (!movedNote) {\n return { linksChanged: false, note: null };\n }\n\n setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n expandNode(targetContainerId);\n scheduleSync?.();\n runtime.util.log(\n `Container contents: queued note ${movedNote.id} move to ${targetContainerId}`,\n );\n return { linksChanged: true, note: movedNote };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveIntentErrors.js","sourceRoot":"","sources":["documentMoveIntentErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,yEAAyE,CAAC;AAG3H,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,KAU1D;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,gCAAgC,CAAC,qBAAqB,CAC1D,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EACjC;QACE,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY,EAAE,KAAK,CAAC,SAAS;QAC7B,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CACF,CAAC;IACF,OAAO,KAAK,CAAC,SAAS,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\nexport async function recordPendingDocumentMoveIntentError(input: {\n blocked?: boolean | undefined;\n denied?: boolean | undefined;\n documentId: string;\n expectedIntentId?: string | undefined;\n expectedUpdatedAt?: string | undefined;\n isCurrent: () => boolean;\n message: string;\n state: { runtime: ContainerContentsWorkflowRuntime };\n unavailable?: boolean | undefined;\n}): Promise<boolean> {\n if (!input.isCurrent()) return false;\n await sqlDocumentMoveIntentPersistence.recordMoveIntentError(\n input.state.runtime.infra.execSql,\n {\n blocked: input.blocked,\n denied: input.denied,\n documentId: input.documentId,\n expectedIntentId: input.expectedIntentId,\n expectedUpdatedAt: input.expectedUpdatedAt,\n message: input.message,\n stillCurrent: input.isCurrent,\n unavailable: input.unavailable,\n },\n );\n return input.isCurrent();\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveIntentSettlement.js","sourceRoot":"","sources":["documentMoveIntentSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gCAAgC,GACjC,MAAM,yEAAyE,CAAC;AACjF,OAAO,EAAE,yCAAyC,EAAE,MAAM,0EAA0E,CAAC;AACrI,OAAO,EAAE,yBAAyB,EAAE,MAAM,qDAAqD,CAAC;AAChG,OAAO,EAAE,iCAAiC,EAAE,MAAM,4CAA4C,CAAC;AAG/F,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAM9C;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAC5C,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EACnD,KAAK,CAAC,MAAM,CAAC,UAAU,CACxB,CAAC;QACF,IAAI,MAAM,EAAE,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE;YAChC,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;QACJ,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,gCAAgC,CAAC,oBAAoB,CACzE,KAAK,CAAC,OAAO,EACb;QACE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACjC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;KAC1C,CACF,CAAC;IACF,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IACD,MAAM,yCAAyC,CAAC,oBAAoB,CAClE,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,MAAM,CAAC,UAAU,EACvB,KAAK,CAAC,kBAAkB,CACzB,CAAC;AACJ,CAAC","sourcesContent":["import {\n type DocumentMoveIntentRecord,\n sqlDocumentMoveIntentPersistence,\n} from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { loadDocumentMovePlacement } from \"../../data/persistence/containers/documentPlacement\";\nimport { getClientSQLitePersistenceRuntime } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\nexport async function settleDocumentMoveIntent(input: {\n execSql: ExecSql;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n linkedContainerIds: readonly string[];\n partial: boolean;\n}): Promise<void> {\n if (!input.isCurrent()) {\n throw new Error(\"Document move generation changed before local settlement\");\n }\n if (input.partial) {\n const intent = await loadDocumentMovePlacement(\n getClientSQLitePersistenceRuntime(input.execSql).db,\n input.intent.documentId,\n );\n if (intent?.id !== input.intent.id)\n throw new Error(\n \"Document move intent was superseded before local settlement\",\n );\n return;\n }\n const settled = await sqlDocumentMoveIntentPersistence.markMoveIntentSynced(\n input.execSql,\n {\n documentId: input.intent.documentId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n },\n );\n if (!settled || !input.isCurrent()) {\n throw new Error(\n \"Document move intent was superseded before local settlement\",\n );\n }\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n input.execSql,\n input.intent.documentId,\n input.linkedContainerIds,\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveIntentSync.js","sourceRoot":"","sources":["documentMoveIntentSync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,+CAA+C,CAAC;AACxG,OAAO,EACL,yBAAyB,EAEzB,gCAAgC,GACjC,MAAM,yEAAyE,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAGL,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oCAAoC,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AAOjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AA0BnF,KAAK,UAAU,wBAAwB,CAAW,KAMjD;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC;QACjD,WAAW,EAAE,KAAK,CAAC,iBAAiB;QACpC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,MAAM,aAAa,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC;QAC1C,GAAG,KAAK,CAAC,WAAW;QACpB,YAAY,EAAE,KAAK,CAAC,SAAS;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa,CAAC,aAAa,CACzB,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAC5D,CAAC;IACF,OAAO,KAAK,CAAC,SAAS,EAAE,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAW,KAMnD;IACC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC7C,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,CAAC,YAAY,CACrE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B,MAAM,CAAC,OAAO,CACf,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,iBAAiB,GACrB,MAAM,CAAC,UAAU,KAAK,yBAAyB;QAC/C,gBAAgB,CAAC,WAAW;QAC5B,KAAK,CAAC,kBAAkB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC;QAC7D,CAAC,CAAC,gBAAgB,CAAC,WAAW;QAC9B,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;IAE5B,MAAM,WAAW,GAA0C;QACzD,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,gBAAgB,CAAC,WAAW;QAC9D,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,IAAI;YAChC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC;QAC/C,WAAW,EAAE,iBAAiB;QAC9B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;QAC5B,gBAAgB,EAAE,CAAC,kBAAkB,EAAE,EAAE,CACvC,wBAAwB,CAAC;YACvB,OAAO,EAAE,kBAAkB;YAC3B,MAAM;YACN,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;YAC5C,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS;SACpC,CAAC;KACL,CAAC;IAEF,OAAO,wBAAwB,CAAC;QAC9B,IAAI;QACJ,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM;QACN,WAAW;QACX,iBAAiB;KAClB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,iCAAiC,CAAW,KAK1D;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC;QAClD,yEAAyE;QACzE,4EAA4E;QAC5E,sEAAsE;QACtE,WAAW,EAAE,KAAK,CAAC,mBAAmB,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB;QACxE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,MAAM,cAAc,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,gBAAgB,GAAG,MAAM,cAAc,CAAC,yBAAyB,EAAE,CAAC;IAC1E,OAAO,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAW,KAOlD;IACC,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,KAAK,yBAAyB,CAAC;IACvE,MAAM,gBAAgB,GACpB,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM;QACvD,CAAC,CAAC,IAAI,UAAU,EAAE;QAClB,CAAC,CAAC,MAAM,iCAAiC,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,WAAoB,CAAC;IACzE,OAAO,2BAA2B,CAAC;QACjC,QAAQ;QACR,0BAA0B,EAAE,KAAK,CAAC,MAAM,CAAC,0BAA0B;QACnE,uBAAuB,EAAE,KAAK,CAAC,MAAM,CAAC,uBAAuB;QAC7D,kBAAkB,EAChB,KAAK,CAAC,MAAM,CAAC,iBAAiB;YAC9B,KAAK,CAAC,mBAAmB;YACzB,KAAK,CAAC,MAAM,CAAC,iBAAiB;QAChC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;QAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,uBAAuB,EAAE,KAAK,CAAC,MAAM,CAAC,uBAAuB;QAC7D,wBAAwB,EAAE,KAAK,CAAC,KAAK,CAAC,wBAAwB;QAC9D,gBAAgB;QAChB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;QAC5B,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,iBAAiB;KAClD,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAC,KAMzC;IAIC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAChC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5C,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,CAAC,YAAY,CACrE,OAAO,EACP,MAAM,CAAC,OAAO,CACf,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACvD,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;QAC3E,MAAM,oCAAoC,CAAC;YACzC,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,0DAA0D;YACnE,KAAK;SACN,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,IAAI,GAAG,CAAC;QAC7B,MAAM,CAAC,iBAAiB;QACxB,GAAG,CAAC,MAAM,CAAC,0BAA0B,IAAI,EAAE,CAAC;KAC7C,CAAC,EAAE,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,oCAAoC,CAAC;gBACzC,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,gBAAgB,EAAE,MAAM,CAAC,EAAE;gBAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;gBACnC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO,EACL,iEAAiE;gBACnE,KAAK;aACN,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,KAAK,CAAC,mBAAmB,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YACpE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/B,CAAC;QACD,IACE,CAAC,+BAA+B,CAAC,WAAW,CAAC;YAC7C,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,EAC/B,CAAC;YACD,MAAM,oCAAoC,CAAC;gBACzC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,gBAAgB,EAAE,MAAM,CAAC,EAAE;gBAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;gBACnC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO,EAAE,uDAAuD;gBAChE,KAAK;aACN,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAC,KAMzC;IACC,MAAM,oCAAoC,CAAC;QACzC,sEAAsE;QACtE,yDAAyD;QACzD,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,mBAAmB;QACzC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACjC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;QACzC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,4BAA4B,CAAC,KAAK,CAAC,OAAO,CAAC;QACpD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,gEAAgE;QAChE,sEAAsE;QACtE,0EAA0E;QAC1E,kEAAkE;QAClE,wEAAwE;QACxE,gEAAgE;QAChE,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAgC,EAChC,KAAkC;IAElC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,mDAAmD,MAAM,CAAC,UAAU,EAAE,CACvE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAW,KAQlD;IACC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACvC,IACE,CAAC,CAAC,MAAM,0BAA0B,CAAC;QACjC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM;QACN,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,KAAK;QACL,KAAK;KACN,CAAC,CAAC,EACH,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAAE,OAAO,WAAW,CAAC;QAC3C,MAAM,oCAAoC,CAAC;YACzC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,0DAA0D;YACnE,KAAK;SACN,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,oCAAoC,CAAC;YACzC,gEAAgE;YAChE,qDAAqD;YACrD,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,mBAAmB;YACzC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,wDAAwD;YACjE,KAAK;YACL,oEAAoE;YACpE,mEAAmE;YACnE,0DAA0D;YAC1D,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,gCAAgC,CAAW,KAOzD;IACC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACtC,MAAM,SAAS,GAAG,2BAA2B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAC3D,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAC7B,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC;QACjD,GAAG,KAAK;QACR,MAAM,EAAE,SAAS,CAAC,MAAM;KACzB,CAAC,CAAC;IACH,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,SAAS,CAAC,MAAM,CAAC;IAC1B,CAAC;IACD,MAAM,EAAE,gBAAgB,EAAE,GAAG,SAAS,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,gCAAgC,CAAC;YACrD,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS;YAClC,OAAO,EAAE,CAAC,SAAS,EAAE,EAAE,CACrB,yBAAyB,CAAC;gBACxB,mBAAmB,EAAE,gBAAgB,CAAC,WAAW;gBACjD,IAAI;gBACJ,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,SAAS;gBACT,KAAK;aACN,CAAC;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO;YACpC,mBAAmB,EAAE,gBAAgB,CAAC,WAAW;YACjD,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAC;QACH,IAAI,OAAO,KAAK,WAAW,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAAE,OAAO,WAAW,CAAC;QACtE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,0BAA0B,CAAC;gBAC/B,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,MAAM;gBACN,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,KAAK;gBACL,WAAW,EAAE,OAAO,CAAC,WAAW;aACjC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,MAAM,yBAAyB,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI;YACJ,MAAM;YACN,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK,EAAE,SAAS,CAAC,QAAQ;gBACvB,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE;gBACzC,CAAC,CAAC,OAAO,CAAC,KAAK;YACjB,KAAK;YACL,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAAE,OAAO,WAAW,CAAC;QAC3C,MAAM,uCAAuC,CAC3C,KAAK,EACL,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,EACzC;YACE,QAAQ,EAAE,MAAM,CAAC,UAAU;YAC3B,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,sBAAsB;SAClC,CACF,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAAE,OAAO,WAAW,CAAC;QAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,oCAAoC,CAAC;YACzC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,iCAAiC,OAAO,EAAE;YACnD,KAAK;SACN,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAW,KAO9D;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,CAAC,CAAC;IACjC,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC;IACnC,MAAM,KAAK,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5C,IAAI,CAAC,6BAA6B,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC;QAC5D,MAAM,gCAAgC,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAAE,OAAO,CAAC,CAAC;QACjC,0BAA0B,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,cAAc,GAClB,MAAM,gCAAgC,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,CAAC,CAAC;IACjC,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAAE,OAAO,UAAU,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,gCAAgC,CAAC;YACpD,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;YAC9C,MAAM;YACN,KAAK;SACN,CAAC,CAAC;QACH,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO,UAAU,CAAC;QAC9C,0EAA0E;QAC1E,qEAAqE;QACrE,sEAAsE;QACtE,yEAAyE;QACzE,kCAAkC;QAClC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,UAAU,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["import { reportAndRethrowKeyingVerificationError } from \"../../data/keyingProjectionVerification/error\";\nimport {\n DOCUMENT_LINK_INTENT_TYPE,\n type DocumentMoveIntentRecord,\n sqlDocumentMoveIntentPersistence,\n} from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { errorMessage } from \"../../data/shared/errorMessage\";\nimport {\n type DocumentLinkSetFailureHandler,\n type DocumentRecord,\n defaultDocumentsPersistence,\n} from \"../documents\";\nimport { availableDocumentLinkIntent } from \"./availableDocumentLinkIntent\";\nimport { moveRemoteContainerDocument } from \"./documentLinks\";\nimport {\n deniedReplayMatchesGeneration,\n markDeniedReplayGeneration,\n} from \"./documentMoveDeniedReplay\";\nimport {\n type DocumentMoveFailureState,\n describeRejectedDocumentMove,\n} from \"./documentMoveFailure\";\nimport { recordPendingDocumentMoveIntentError } from \"./documentMoveIntentErrors\";\nimport { settleDocumentMoveIntent } from \"./documentMoveIntentSettlement\";\nimport { moveWithVanishedContainerRefresh } from \"./documentMoveVanishedRefresh\";\nimport type {\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRelinkInput,\n} from \"./documentStructureTypes\";\nimport type { ContainerContentsProjectionUserKeyResolver } from \"./projectionKeys\";\nimport type { ContainerState } from \"./remoteHydration\";\nimport { hasRemoteContainerMetadataState } from \"./remoteHydration/reconciliation\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\ntype DocumentMoveIntentReplayResult =\n | \"abandoned\"\n | \"moved\"\n | \"partial\"\n | \"blocked\"\n | \"failed\";\n\nexport interface DocumentMoveIntentSyncHost<TRuntime> {\n documentWorkflowRuntime: (containerId: string) => TRuntime;\n openDocumentStore: (input: {\n containerId: string;\n documentId: string | null;\n localId: string;\n }) => DocumentStructuralMutationLocalStore<TRuntime>;\n}\n\ninterface DocumentMoveIntentSyncState {\n containersById: ReadonlyMap<string, ContainerState>;\n lifecycleGeneration?: number | undefined;\n resolveProjectionUserKey: ContainerContentsProjectionUserKeyResolver;\n runtime: ContainerContentsWorkflowRuntime;\n}\n\nasync function relinkMovedDocumentStore<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n relinkInput: DocumentStructuralMutationRelinkInput;\n targetContainerId: string;\n}): Promise<boolean> {\n if (!input.isCurrent()) return false;\n const documentStore = input.host.openDocumentStore({\n containerId: input.targetContainerId,\n documentId: input.intent.documentId,\n localId: input.intent.localId,\n });\n if (!(await documentStore.ensureInitialized()) || !input.isCurrent()) {\n return false;\n }\n\n const relinked = await documentStore.relink({\n ...input.relinkInput,\n stillCurrent: input.isCurrent,\n });\n if (!relinked || !input.isCurrent()) {\n return false;\n }\n\n documentStore.updateRuntime(\n input.host.documentWorkflowRuntime(input.targetContainerId),\n );\n return input.isCurrent();\n}\n\nasync function persistMovedDocumentReplay<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n moved: NonNullable<Awaited<ReturnType<typeof moveRemoteContainerDocument>>>;\n state: DocumentMoveIntentSyncState;\n}): Promise<boolean> {\n const { host, intent, moved, state } = input;\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n state.runtime.infra.execSql,\n intent.localId,\n );\n if (!input.isCurrent() || !existingDocument) {\n return false;\n }\n\n const targetContainerId =\n intent.intentType === DOCUMENT_LINK_INTENT_TYPE &&\n existingDocument.containerId &&\n moved.linkedContainerIds.includes(existingDocument.containerId)\n ? existingDocument.containerId\n : moved.nextContainerId;\n\n const relinkInput: DocumentStructuralMutationRelinkInput = {\n accessEpoch: moved.accessEpoch ?? existingDocument.accessEpoch,\n ...(moved.accessStateHash === null\n ? {}\n : { accessStateHash: moved.accessStateHash }),\n containerId: targetContainerId,\n documentId: intent.documentId,\n localId: intent.localId,\n ...(moved.remoteState ?? {}),\n commitSideEffect: (transactionExecSql) =>\n settleDocumentMoveIntent({\n execSql: transactionExecSql,\n intent,\n isCurrent: input.isCurrent,\n linkedContainerIds: moved.linkedContainerIds,\n partial: moved.status === \"partial\",\n }),\n };\n\n return relinkMovedDocumentStore({\n host,\n isCurrent: input.isCurrent,\n intent,\n relinkInput,\n targetContainerId,\n });\n}\n\nasync function assertMoveIntentRotationPreflight<TRuntime>(input: {\n existingContainerId: string | null | undefined;\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n}): Promise<Uint8Array | null> {\n if (!input.isCurrent()) return null;\n const preflightStore = input.host.openDocumentStore({\n // The optimistic move already changed local placement. Use that scope so\n // opening the destination view cannot invalidate this shared store's proof.\n // Remote link-set authorization still uses the intent's source below.\n containerId: input.existingContainerId ?? input.intent.targetContainerId,\n documentId: input.intent.documentId,\n localId: input.intent.localId,\n });\n if (!(await preflightStore.ensureInitialized())) {\n throw new Error(\"Document rotation preflight could not load the document\");\n }\n if (!input.isCurrent()) return null;\n const rotationSnapshot = await preflightStore.assertCanRotateContentKey();\n return input.isCurrent() ? rotationSnapshot : null;\n}\n\nasync function movePendingDocumentIntent<TRuntime>(input: {\n existingContainerId: string | null | undefined;\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n onFailure: DocumentLinkSetFailureHandler;\n state: DocumentMoveIntentSyncState;\n}) {\n // Adding links keeps the content key and needs no full-history rotation proof.\n const linkOnly = input.intent.intentType === DOCUMENT_LINK_INTENT_TYPE;\n const rotationSnapshot =\n linkOnly && !input.intent.removedLinkContainerIds?.length\n ? new Uint8Array()\n : await assertMoveIntentRotationPreflight(input);\n if (!rotationSnapshot || !input.isCurrent()) return \"abandoned\" as const;\n return moveRemoteContainerDocument({\n linkOnly,\n additionalLinkContainerIds: input.intent.additionalLinkContainerIds,\n removedLinkContainerIds: input.intent.removedLinkContainerIds,\n currentContainerId:\n input.intent.sourceContainerId ??\n input.existingContainerId ??\n input.intent.targetContainerId,\n documentId: input.intent.documentId,\n isCurrent: input.isCurrent,\n noteId: input.intent.localId,\n onFailure: input.onFailure,\n replaceLinkedContainers: input.intent.replaceLinkedContainers,\n resolveProjectionUserKey: input.state.resolveProjectionUserKey,\n rotationSnapshot,\n runtime: input.state.runtime,\n targetContainerId: input.intent.targetContainerId,\n });\n}\n\nasync function resolveMoveIntentPreflight(input: {\n isCreatePending: (containerId: string) => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n state: DocumentMoveIntentSyncState;\n}): Promise<\n | { existingDocument: DocumentRecord; result?: undefined }\n | { existingDocument?: undefined; result: DocumentMoveIntentReplayResult }\n> {\n const { intent, state } = input;\n const execSql = state.runtime.infra.execSql;\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n execSql,\n intent.localId,\n );\n if (!input.isCurrent()) return { result: \"abandoned\" };\n if (!existingDocument || existingDocument.documentId !== intent.documentId) {\n await recordPendingDocumentMoveIntentError({\n blocked: true,\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Document move intent references a missing local document\",\n state,\n });\n return { result: \"blocked\" };\n }\n\n for (const targetId of new Set([\n intent.targetContainerId,\n ...(intent.additionalLinkContainerIds ?? []),\n ])) {\n const targetState = state.containersById.get(targetId);\n if (!targetState) {\n await recordPendingDocumentMoveIntentError({\n blocked: true,\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message:\n \"Document move intent references a missing destination container\",\n state,\n });\n return { result: \"blocked\" };\n }\n if (input.isRemoteSyncBlocked(targetState.container.organizationId)) {\n return { result: \"blocked\" };\n }\n if (\n !hasRemoteContainerMetadataState(targetState) ||\n input.isCreatePending(targetId)\n ) {\n await recordPendingDocumentMoveIntentError({\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Document move destination container is not synced yet\",\n state,\n });\n return { result: \"failed\" };\n }\n }\n return { existingDocument };\n}\n\nasync function recordRejectedDocumentMove(input: {\n failure: DocumentMoveFailureState;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n state: DocumentMoveIntentSyncState;\n unavailable: boolean;\n}): Promise<void> {\n await recordPendingDocumentMoveIntentError({\n // A permission denial parks the intent for the access-restored signal\n // instead of replaying on every structural pass (row 7).\n denied: input.failure.sawPermissionDenial,\n documentId: input.intent.documentId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n isCurrent: input.isCurrent,\n message: describeRejectedDocumentMove(input.failure),\n state: input.state,\n // Terminal only after the vanished-container refresh proved the\n // destination itself gone: the intent can never commit as written and\n // nothing on this device can heal it, so it leaves the replay set instead\n // of re-issuing doomed requests every pass. The tombstone cascade\n // retargets it once hydration tears the deleted container down locally.\n // Every other vanished verdict stays pending for the next pass.\n unavailable: input.unavailable,\n });\n}\n\nfunction logSyncedDocumentMove(\n intent: DocumentMoveIntentRecord,\n state: DocumentMoveIntentSyncState,\n): void {\n state.runtime.util.log(\n `Container contents: synced queued document move ${intent.documentId}`,\n );\n}\n\nasync function settleMovedDocumentIntent<TRuntime>(input: {\n failure: DocumentMoveFailureState;\n host: DocumentMoveIntentSyncHost<TRuntime>;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n moved: NonNullable<Awaited<ReturnType<typeof moveRemoteContainerDocument>>>;\n state: DocumentMoveIntentSyncState;\n unavailable: boolean;\n}): Promise<DocumentMoveIntentReplayResult> {\n const { intent, moved, state } = input;\n if (\n !(await persistMovedDocumentReplay({\n host: input.host,\n intent,\n isCurrent: input.isCurrent,\n moved,\n state,\n }))\n ) {\n if (!input.isCurrent()) return \"abandoned\";\n await recordPendingDocumentMoveIntentError({\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Document move replay could not relink the local document\",\n state,\n });\n return \"failed\";\n }\n if (moved.status === \"partial\") {\n await recordPendingDocumentMoveIntentError({\n // An unlink refused for permissions parks like any other denied\n // move (row 7); other partials keep row 15's replay.\n denied: input.failure.sawPermissionDenial,\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Remote document move partially applied; retry required\",\n state,\n // Terminal only when the refresh proved the destination itself gone\n // after the link had already landed; a vanished unlink alone stays\n // pending with its live link for the next pass to revoke.\n unavailable: input.unavailable,\n });\n return \"partial\";\n }\n\n logSyncedDocumentMove(intent, state);\n return \"moved\";\n}\n\nasync function trySyncPendingDocumentMoveIntent<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCreatePending: (containerId: string) => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n state: DocumentMoveIntentSyncState;\n}): Promise<DocumentMoveIntentReplayResult> {\n const { host, intent, state } = input;\n const available = availableDocumentLinkIntent(intent, (id) =>\n state.containersById.has(id),\n );\n const preflight = await resolveMoveIntentPreflight({\n ...input,\n intent: available.intent,\n });\n if (preflight.result !== undefined) {\n return preflight.result;\n }\n const { existingDocument } = preflight;\n\n try {\n const outcome = await moveWithVanishedContainerRefresh({\n apiClient: state.runtime.apiClient,\n attempt: (onFailure) =>\n movePendingDocumentIntent({\n existingContainerId: existingDocument.containerId,\n host,\n isCurrent: input.isCurrent,\n intent: available.intent,\n onFailure,\n state,\n }),\n execSql: state.runtime.infra.execSql,\n existingContainerId: existingDocument.containerId,\n intent: available.intent,\n isCurrent: input.isCurrent,\n });\n if (outcome === \"abandoned\" || !input.isCurrent()) return \"abandoned\";\n if (!outcome.moved) {\n await recordRejectedDocumentMove({\n failure: outcome.failure,\n intent,\n isCurrent: input.isCurrent,\n state,\n unavailable: outcome.unavailable,\n });\n return \"failed\";\n }\n return await settleMovedDocumentIntent({\n failure: outcome.failure,\n host,\n intent,\n isCurrent: input.isCurrent,\n moved: available.deferred\n ? { ...outcome.moved, status: \"partial\" }\n : outcome.moved,\n state,\n unavailable: outcome.unavailable,\n });\n } catch (error: unknown) {\n if (!input.isCurrent()) return \"abandoned\";\n await reportAndRethrowKeyingVerificationError(\n error,\n state.runtime.util.reportSecurityIncident,\n {\n objectId: intent.documentId,\n objectKind: \"document\",\n operation: \"document.move.replay\",\n },\n );\n if (!input.isCurrent()) return \"abandoned\";\n const message = errorMessage(error);\n await recordPendingDocumentMoveIntentError({\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: `Failed to sync document move: ${message}`,\n state,\n });\n return \"failed\";\n }\n}\n\nexport async function syncPendingDocumentMoveIntents<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n /** A destination whose create has not settled takes no document yet. */\n isCreatePending: (containerId: string) => boolean;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n state: DocumentMoveIntentSyncState;\n}): Promise<number> {\n if (!input.isCurrent()) return 0;\n const lifecycleState = input.state;\n const state = { ...lifecycleState };\n const execSql = state.runtime.infra.execSql;\n if (!deniedReplayMatchesGeneration(lifecycleState, execSql)) {\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql);\n if (!input.isCurrent()) return 0;\n markDeniedReplayGeneration(lifecycleState, execSql);\n }\n const pendingIntents =\n await sqlDocumentMoveIntentPersistence.listPendingMoveIntents(execSql);\n if (!input.isCurrent()) return 0;\n let movedCount = 0;\n\n for (const intent of pendingIntents) {\n if (!input.isCurrent()) return movedCount;\n const result = await trySyncPendingDocumentMoveIntent({\n host: input.host,\n isCreatePending: input.isCreatePending,\n isCurrent: input.isCurrent,\n isRemoteSyncBlocked: input.isRemoteSyncBlocked,\n intent,\n state,\n });\n if (result === \"abandoned\") return movedCount;\n // A \"partial\" result (link applied, unlink still pending) must not count:\n // the caller re-arms this same structural lane whenever the count is\n // positive, so a deterministically failing unlink hot-looped the pump\n // (issue #1744). The intent row stays pending; event-driven, manual, and\n // startup lane requests retry it.\n if (result === \"moved\") {\n movedCount += 1;\n }\n }\n\n return movedCount;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentMoveVanishedRefresh.js","sourceRoot":"","sources":["documentMoveVanishedRefresh.ts"],"names":[],"mappings":"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","sourcesContent":["import { isContainerNotFoundFailure } from \"../../data/containers/shared/mutationFailures\";\nimport { readLinkedContainerIdsFromDocumentManifest } from \"../../data/documents/shared/projection\";\nimport type { DocumentMoveIntentRecord } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { DocumentLinkSetFailureHandler } from \"../documents\";\nimport { listDocumentLinkedContainerIds } from \"./documentLinks\";\nimport {\n createDocumentMoveFailureState,\n type DocumentMoveFailureState,\n recordDocumentMoveFailure,\n} from \"./documentMoveFailure\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\nexport interface VanishedContainerRefreshOutcome<TMoved> {\n readonly failure: DocumentMoveFailureState;\n readonly moved: TMoved;\n /**\n * Park the intent terminally. True only when the destination itself is\n * proven gone: a coded 404 on its projection probe after eviction. No\n * mutation verdict — first attempt or retry — is ever terminal.\n */\n readonly unavailable: boolean;\n}\n\n/**\n * Every container the unlink half of the move can cite. The unlink set is\n * read off the REMOTE document manifest's link set, so that set — refetched\n * after eviction so it is current — is the authority; the local link\n * projection, the intent's source, and the document's local placement are\n * unioned in so a source known only on one side still gets its cached path\n * refreshed. A superset is harmless: an eviction only forces a refetch, and\n * nothing here decides what gets unlinked.\n */\nasync function listMoveSourceContainerIds(input: {\n apiClient: ContainerContentsWorkflowRuntime[\"apiClient\"];\n execSql: ExecSql;\n existingContainerId: string | null | undefined;\n intent: DocumentMoveIntentRecord;\n}): Promise<string[]> {\n const { documentId, targetContainerId } = input.intent;\n const [remote, local] = await Promise.all([\n input.apiClient.getDocumentWriterProjectionResult(documentId, {\n reportErrors: false,\n }),\n listDocumentLinkedContainerIds(input.execSql, documentId),\n ]);\n const remoteLinkedContainerIds = remote.ok\n ? readLinkedContainerIdsFromDocumentManifest(remote.data)\n : [];\n return Array.from(\n new Set([\n ...remoteLinkedContainerIds,\n ...local,\n input.intent.sourceContainerId,\n input.existingContainerId,\n ]),\n )\n .filter(\n (containerId): containerId is string =>\n typeof containerId === \"string\" && containerId !== targetContainerId,\n )\n .sort();\n}\n\n/**\n * A vanished-container verdict (coded container 404 or `container_unavailable`\n * 409) does not by itself doom a queued move. The deleted container may be a\n * stale ANCESTOR in a cached path — the destination or a source was moved\n * under a live parent before its former parent was deleted — and the local\n * tombstone cascade cannot rescue that intent (it retargets only intents whose\n * source or destination IS the tombstoned container). So refresh before\n * declaring terminal: evict the cached destination, document, and source\n * projections, probe the destination, and retry once with the fresh paths.\n *\n * Only the destination's fate is terminal, and only as proven by its own\n * probe. Sources are evicted, never judged: the retry's unlink set comes from\n * the verified manifest alone, so a server-asserted \"source gone\" can neither\n * skip a revoke nor complete the move — a retry whose link landed but whose\n * unlink still vanished stays partial (pending) with a live link the queue\n * keeps trying to revoke. The retry's own vanished verdict, on either side, is\n * likewise never terminal: with the destination live it can only name another\n * ancestor deleted mid-pass, which the next pass's fresh paths outrun. The\n * pass is bounded to one retry; a transient probe failure leaves the intent\n * retriable (or denied on 403) for a later pass.\n */\nexport async function moveWithVanishedContainerRefresh<TMoved>(input: {\n apiClient: ContainerContentsWorkflowRuntime[\"apiClient\"];\n attempt: (\n onFailure: DocumentLinkSetFailureHandler,\n ) => Promise<TMoved | \"abandoned\">;\n execSql: ExecSql;\n existingContainerId: string | null | undefined;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n}): Promise<VanishedContainerRefreshOutcome<TMoved> | \"abandoned\"> {\n const { apiClient, intent } = input;\n const firstFailure = createDocumentMoveFailureState();\n const first = await input.attempt((failure) =>\n recordDocumentMoveFailure(firstFailure, failure),\n );\n if (first === \"abandoned\" || !input.isCurrent()) return \"abandoned\";\n if (!firstFailure.sawVanishedContainer) {\n return { failure: firstFailure, moved: first, unavailable: false };\n }\n\n for (const targetContainerId of new Set([\n intent.targetContainerId,\n ...(intent.additionalLinkContainerIds ?? []),\n ])) {\n apiClient.evictContainerWriterProjection(targetContainerId);\n const destination = await apiClient.getContainerWriterProjectionResult(\n targetContainerId,\n { reportErrors: false },\n );\n apiClient.evictDocumentWriterProjection(intent.documentId);\n if (!input.isCurrent()) return \"abandoned\";\n if (!destination.ok) {\n destination.report();\n recordDocumentMoveFailure(firstFailure, destination);\n return {\n failure: firstFailure,\n moved: first,\n unavailable: isContainerNotFoundFailure(destination),\n };\n }\n }\n\n for (const sourceContainerId of await listMoveSourceContainerIds(input)) {\n apiClient.evictContainerWriterProjection(sourceContainerId);\n }\n if (!input.isCurrent()) return \"abandoned\";\n\n const retryFailure = createDocumentMoveFailureState();\n const retried = await input.attempt((failure) =>\n recordDocumentMoveFailure(retryFailure, failure),\n );\n if (retried === \"abandoned\" || !input.isCurrent()) return \"abandoned\";\n // The retry's own vanished verdict is never terminal. The destination was\n // just proven live, so a second `container_unavailable` can only name\n // another ancestor deleted during the refreshed attempt (or a source): the\n // intent stays pending with its failure recorded and the next pass starts\n // over with freshly evicted projections. One retry per pass keeps it\n // bounded; nothing in the queue backs a pending intent off between passes.\n return { failure: retryFailure, moved: retried, unavailable: false };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentPriming.js","sourceRoot":"","sources":["documentPriming.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n documentContainerProjectionTables,\n documentPlacementIntentTables,\n documentProjectionTables,\n documentTables,\n LOCAL_INTENT_LANES,\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 stored.sync_failure_message IS NOT NULL\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 local_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.lane = '${LOCAL_INTENT_LANES.documentPlacement}'\n AND 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 ...documentPlacementIntentTables,\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 +0,0 @@
1
- {"version":3,"file":"documentPurge.js","sourceRoot":"","sources":["documentPurge.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentPurgeResponse } from \"@tearleads/validators/response\";\nimport type { StoredDocumentKind } from \"../../data/documents/documentKinds\";\nimport type { ProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../data/keyingProjectionVerification/error\";\nimport { rethrowProjectionVerificationCancelled } from \"../../data/keyingProjectionVerification/types\";\nimport { errorMessage } from \"../../data/shared/errorMessage\";\nimport {\n type DocumentsPersistence,\n defaultDocumentsPersistence,\n deletePersistedDocument,\n purgeRemoteDocument,\n reclaimDocumentOrphanBlobs,\n resolveDocumentCreateAuthor,\n} from \"../documents\";\nimport { ensureDocumentClientProjectionTables } from \"../documents/persistence\";\nimport type { SubtreePurgeRoot } from \"../documents/subtreePurgeScope\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../principals/runtimePolicyWarmer\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\ntype ContainerDocumentPurgeApi = Pick<\n ContainerContentsWorkflowRuntime[\"apiClient\"],\n | \"getPrincipalPolicyPages\"\n | \"getProjectionPolicyHistoryPages\"\n | \"getDocumentPurgeProof\"\n | \"getDocumentWriterProjectionResult\"\n | \"purgeDocument\"\n>;\ntype DocumentPurgeResult =\n | DocumentPurgeResponse\n | {\n readonly documentId: string;\n readonly purgedAt: string;\n readonly reclaimedBlobStorageKeys: readonly string[];\n }\n | null;\n\ninterface ContainerDocumentPurgeRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n apiClient: ContainerDocumentPurgeApi;\n}\n\ninterface PurgeRemoteContainerDocumentInput {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n stillCurrent?: (() => boolean) | undefined;\n documentKind: StoredDocumentKind;\n noteId: string;\n persistence?: DocumentsPersistence | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentPurgeRuntime;\n}\n\nasync function deleteAbsentDocumentState(input: {\n readonly commitPurgeProof: (\n transactionExecSql: ContainerDocumentPurgeRuntime[\"infra\"][\"execSql\"],\n ) => Promise<void>;\n readonly documentId: string;\n readonly documentKind: StoredDocumentKind;\n readonly noteId: string;\n readonly persistence: DocumentsPersistence;\n readonly runtime: ContainerDocumentPurgeRuntime;\n}): Promise<boolean> {\n return input.persistence.deleteDocumentSideRowsIfAbsent(\n input.runtime.infra.execSql,\n input.noteId,\n input.documentId,\n async (transactionExecSql) => {\n await input.runtime.infra.documentProjectors.deleteStoredDocumentClientProjection(\n {\n documentKind: input.documentKind,\n execSql: transactionExecSql,\n localId: input.noteId,\n },\n );\n await input.commitPurgeProof(transactionExecSql);\n },\n );\n}\n\nasync function commitVerifiedDocumentPurge(input: {\n readonly commitPurgeProof: (\n transactionExecSql: ContainerDocumentPurgeRuntime[\"infra\"][\"execSql\"],\n ) => Promise<void>;\n readonly documentId: string;\n readonly documentKind: StoredDocumentKind;\n readonly noteId: string;\n readonly persistence: DocumentsPersistence;\n readonly runtime: ContainerDocumentPurgeRuntime;\n}): Promise<boolean> {\n await input.persistence.ensureSchema(input.runtime.infra.execSql);\n await ensureDocumentClientProjectionTables({\n documentProjectors: input.runtime.infra.documentProjectors,\n execSql: input.runtime.infra.execSql,\n });\n const expectedRecord = await input.persistence.loadDocument(\n input.runtime.infra.execSql,\n input.noteId,\n );\n if (expectedRecord && expectedRecord.documentId !== input.documentId) {\n throw new Error(\n \"Local document identity changed while its remote purge was committing\",\n );\n }\n const deleted = expectedRecord\n ? await deletePersistedDocument({\n beforeDeleteInTransaction: input.commitPurgeProof,\n documentProjectors: input.runtime.infra.documentProjectors,\n execSql: input.runtime.infra.execSql,\n expectedRecord,\n localId: input.noteId,\n persistence: input.persistence,\n })\n : await deleteAbsentDocumentState(input);\n if (!deleted) {\n throw new Error(\n \"Local document state changed while its remote purge was committing\",\n );\n }\n return true;\n}\n\nexport async function purgeRemoteContainerDocument(\n input: PurgeRemoteContainerDocumentInput,\n): Promise<DocumentPurgeResult> {\n const { documentId, noteId, runtime } = input;\n const persistence = input.persistence ?? defaultDocumentsPersistence;\n try {\n const author = resolveDocumentCreateAuthor(runtime);\n if (!author) {\n runtime.util.log(\n `Container contents: failed to purge note ${noteId} because the local signing context is unavailable`,\n );\n return null;\n }\n let deleted = false;\n const response = await purgeRemoteDocument({\n apiClient: runtime.apiClient,\n beforeSubmit: input.beforeSubmit,\n author,\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n stillCurrent: input.stillCurrent,\n execSql: runtime.infra.execSql,\n onVerifiedPurge: async ({ commitPurgeProof }) => {\n deleted = await commitVerifiedDocumentPurge({\n commitPurgeProof,\n documentId,\n documentKind: input.documentKind,\n noteId,\n persistence,\n runtime,\n });\n },\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!response) {\n runtime.util.log(\n `Container contents: failed to purge note ${noteId} (document ${documentId})`,\n );\n return null;\n }\n if (deleted) {\n void reclaimDocumentOrphanBlobs(runtime, persistence);\n }\n runtime.util.log(\n `Container contents: purged note ${noteId} (document ${documentId})`,\n );\n return response;\n } catch (error) {\n // A cancelled verification is neither a failure nor a completed purge; the\n // caller that owns the generation decides what to do with it.\n rethrowProjectionVerificationCancelled(error);\n await reportAndRethrowKeyingVerificationError(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: \"document.purge\",\n },\n );\n runtime.util.log(\n `Container contents: failed to purge note ${noteId} (document ${documentId}): ${errorMessage(error)}`,\n );\n return null;\n }\n}\n\ninterface ContainerDocumentLocalPurgeRuntime\n extends Pick<ContainerContentsWorkflowRuntime, \"infra\" | \"util\"> {}\n\nexport async function purgeLocalContainerDocument(input: {\n beforeDeleteInTransaction?: Parameters<\n typeof deletePersistedDocument\n >[0][\"beforeDeleteInTransaction\"];\n noteId: string;\n expectedContainerId?: string | null | undefined;\n persistence?: DocumentsPersistence | undefined;\n runtime: ContainerDocumentLocalPurgeRuntime;\n}): Promise<DocumentPurgeResult> {\n const { noteId, runtime } = input;\n const persistence = input.persistence ?? defaultDocumentsPersistence;\n try {\n await persistence.ensureSchema(runtime.infra.execSql);\n const expectedRecord = await persistence.loadDocument(\n runtime.infra.execSql,\n noteId,\n );\n if (\n !expectedRecord ||\n expectedRecord.documentId !== null ||\n (input.expectedContainerId !== undefined &&\n expectedRecord.containerId !== input.expectedContainerId)\n ) {\n runtime.util.log(\n `Container contents: local-only purge refused for note ${noteId} because it is absent or remote-backed`,\n );\n return null;\n }\n const deleted = await deletePersistedDocument({\n beforeDeleteInTransaction: input.beforeDeleteInTransaction,\n documentProjectors: runtime.infra.documentProjectors,\n execSql: runtime.infra.execSql,\n expectedRecord,\n localId: noteId,\n persistence,\n });\n if (!deleted) {\n runtime.util.log(\n `Container contents: local-only purge refused for note ${noteId} because its identity changed`,\n );\n return null;\n }\n if (deleted) {\n void reclaimDocumentOrphanBlobs(runtime, persistence);\n }\n runtime.util.log(`Container contents: purged local-only note ${noteId}`);\n return {\n documentId: noteId,\n purgedAt: new Date().toISOString(),\n reclaimedBlobStorageKeys: [],\n };\n } catch (error) {\n runtime.util.log(\n `Container contents: failed to purge local-only note ${noteId}: ${errorMessage(error)}`,\n );\n return null;\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentQueries.js","sourceRoot":"","sources":["documentQueries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { SyncWatermark } from \"@tearleads/validators/response\";\nimport type {\n DiscoveredDocumentInput,\n DocumentSummary,\n} from \"../../data/documents/documentSummary\";\nimport {\n hasRetainedContainerMetadata,\n listRecoveryFolderMoveIds,\n} from \"../../data/persistence/container-contents/containerRecoveryPersistence\";\nimport { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport {\n containerContentsSyncLane,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../data/persistence/containers/containerSyncWatermarkPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport {\n applyContainerDocumentTombstones as applyPersistedContainerDocumentTombstones,\n sqlDocumentsPersistence,\n upsertDiscoveredDocuments,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport { localIntentTables } from \"../../data/sqlite/schema\";\nimport { type ExecSql, ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { hydratedProjectionSql } from \"./documentQueries/hydrationSql\";\nimport {\n mapContainerContentsDocumentSummaryRow,\n mapContainerContentsDocumentSyncStateRow,\n mapContainerDocumentSidebarRow,\n mapContainerItemRow,\n readContainerContentsContainerItemCount,\n} from \"./documentQueries/rows\";\nimport {\n clampContainerItemWindowValue,\n getContainerContentsContainerDocumentSidebarOrderBy,\n getContainerContentsContainerItemOrderBy,\n getContainerContentsContainerItemsBaseSql,\n getContainerContentsDocumentPendingStateCtes,\n getContainerContentsDocumentRowsBaseSql,\n getContainerDocumentSidebarWindowLimit,\n getContainerItemWindowLimit,\n getOrphanedDocumentExistsSql,\n getOrphanedDocumentItemsBaseSql,\n getOrphanedDocumentRowsBaseSql,\n listContainerContentsSqlIdBatches,\n} from \"./documentQueries/sql\";\nimport type {\n ContainerDocumentLinkInput,\n ContainerDocumentQueriesRuntime,\n ContainerDocumentSidebarWindow,\n ContainerDocumentTombstone,\n ContainerItemSort,\n ContainerItemWindow,\n} from \"./documentQueries/types\";\nimport {\n createFolderRecoveryQueries,\n type RecoveryFolder,\n} from \"./folderRecovery\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\nimport {\n listPendingDownloads,\n type PendingDownloadQueueItem,\n} from \"./pendingDownloads\";\nimport {\n listPendingWrites,\n type PendingWriteQueueItem,\n resetPendingWriteRetryState,\n} from \"./pendingWrites\";\nimport type { ContainerDocumentObjectSyncState } from \"./syncState\";\n\nexport type {\n ContainerDocumentLinkInput,\n ContainerDocumentSidebarRow,\n ContainerDocumentTombstone,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n} from \"./documentQueries/types\";\n\ninterface ListContainerItemWindowInput {\n /** Null selects the virtual orphaned-documents recovery collection. */\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n sort: ContainerItemSort;\n visibleForeignSystemContainerNames?: ReadonlyArray<string> | undefined;\n visibleSystemSlots?: ReadonlyArray<ContainerSystemSlot> | undefined;\n}\n\nexport interface ContainerDocumentQueries {\n listRecoveryFolderMoveIds(input: {\n currentOrganizationId: string | null;\n }): Promise<string[]>;\n listRecoveryFolders(input: {\n currentOrganizationId: string | null;\n }): Promise<RecoveryFolder[]>;\n discardRecoveryFolder(\n input: Pick<RecoveryFolder, \"containerId\" | \"organizationId\" | \"revision\">,\n ): Promise<boolean>;\n applyContainerDocumentTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n ): Promise<ReadonlyArray<DocumentSummary>>;\n hasOrphanedDocuments(input: {\n currentOrganizationId: string | null;\n }): Promise<boolean>;\n listContainerDocumentSidebarWindow(input: {\n /** Null selects the virtual orphaned-documents recovery collection. */\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n }): Promise<ContainerDocumentSidebarWindow>;\n listContainerItemWindow(\n input: ListContainerItemWindowInput,\n ): Promise<ContainerItemWindow>;\n loadDocumentSyncState(\n localId: string,\n ): Promise<ContainerDocumentObjectSyncState | null>;\n loadDocumentSummary(\n localId: string,\n options?: { requireHydrated?: boolean },\n ): Promise<DocumentSummary | null>;\n loadOrphanedDocumentSummary(input: {\n requireHydrated?: boolean;\n currentOrganizationId: string | null;\n localId: string;\n }): Promise<DocumentSummary | null>;\n loadContainerDocumentWatermark(\n containerId: string,\n ): Promise<SyncWatermark | null>;\n listLinkedContainerIdsByDocumentIds(\n documentIds: ReadonlyArray<string>,\n ): Promise<ReadonlyMap<string, ReadonlyArray<string>>>;\n listPendingDownloads(): Promise<ReadonlyArray<PendingDownloadQueueItem>>;\n listPendingWrites(): Promise<ReadonlyArray<PendingWriteQueueItem>>;\n retryPendingWriteItem(input: {\n localId: string;\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n }): Promise<void>;\n replaceDocumentLinksBatch(\n inputs: ReadonlyArray<ContainerDocumentLinkInput>,\n ): Promise<void>;\n saveContainerDocumentWatermark(\n containerId: string,\n watermark: SyncWatermark,\n ): Promise<void>;\n upsertDiscoveredDocuments(\n inputs: ReadonlyArray<DiscoveredDocumentInput>,\n ): Promise<ReadonlyArray<DocumentSummary>>;\n}\n\nasync function listContainerItemWindow(\n execSql: ExecSql,\n input: ListContainerItemWindowInput,\n): Promise<ContainerItemWindow> {\n await ensureContainerTables(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, localIntentTables);\n\n const limit = getContainerItemWindowLimit(input.limit);\n const offset = clampContainerItemWindowValue(input.offset);\n const visibleSystemSlots = Array.from(\n new Set(input.visibleSystemSlots ?? []),\n );\n const currentOrganizationId = input.currentOrganizationId || null;\n const visibleForeignSystemContainerNames = currentOrganizationId\n ? Array.from(new Set(input.visibleForeignSystemContainerNames ?? []))\n : [];\n const orphaned = input.containerId === null;\n const bind = orphaned\n ? getOrphanedDocumentQueryBind(input.currentOrganizationId)\n : [\n input.containerId,\n ...visibleSystemSlots,\n ...(visibleForeignSystemContainerNames.length > 0\n ? [currentOrganizationId, ...visibleForeignSystemContainerNames]\n : []),\n input.containerId,\n input.containerId,\n ];\n const baseSql = orphaned\n ? getOrphanedDocumentItemsBaseSql()\n : getContainerContentsContainerItemsBaseSql(\n visibleSystemSlots.length,\n visibleForeignSystemContainerNames.length,\n );\n const countRows = await execSql(\n `SELECT COUNT(*) AS total_count FROM (${baseSql})`,\n bind,\n );\n const totalCount = readContainerContentsContainerItemCount(\n countRows[0] ?? {},\n );\n\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const rows = await execSql(\n `${baseSql} ORDER BY ${getContainerContentsContainerItemOrderBy(input.sort)} LIMIT ? OFFSET ?`,\n [...bind, limit, offset],\n );\n\n return {\n rows: rows.map((row) => mapContainerItemRow(input.containerId, row)),\n totalCount,\n };\n}\n\nasync function hasOrphanedDocuments(\n execSql: ExecSql,\n currentOrganizationId: string | null,\n): Promise<boolean> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n getOrphanedDocumentExistsSql(),\n getOrphanedDocumentQueryBind(currentOrganizationId),\n );\n return (\n rows.length > 0 ||\n (await hasRetainedContainerMetadata(execSql, currentOrganizationId)) ||\n (await listRecoveryFolderMoveIds(execSql, currentOrganizationId)).length > 0\n );\n}\n\nasync function listContainerDocumentSidebarWindow(\n execSql: ExecSql,\n input: {\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n },\n): Promise<ContainerDocumentSidebarWindow> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const limit = getContainerDocumentSidebarWindowLimit(input.limit);\n const offset = clampContainerItemWindowValue(input.offset);\n const orphaned = input.containerId === null;\n const bind = orphaned\n ? getOrphanedDocumentQueryBind(input.currentOrganizationId)\n : [input.containerId, input.containerId];\n const baseSql = orphaned\n ? getOrphanedDocumentRowsBaseSql()\n : getContainerContentsDocumentRowsBaseSql();\n const countRows = await execSql(\n `SELECT COUNT(*) AS total_count FROM (${baseSql})`,\n bind,\n );\n const totalCount = readContainerContentsContainerItemCount(\n countRows[0] ?? {},\n );\n\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const rows = await execSql(\n `${baseSql} ORDER BY ${getContainerContentsContainerDocumentSidebarOrderBy()} LIMIT ? OFFSET ?`,\n [...bind, limit, offset],\n );\n\n return {\n rows: rows.map(mapContainerDocumentSidebarRow),\n totalCount,\n };\n}\n\nasync function queryContainerContentsDocumentSummary(\n execSql: ExecSql,\n localId: string,\n scope: { bind: ReadonlyArray<string | null>; whereSql: string },\n): Promise<DocumentSummary | null> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const rows = await execSql(\n `\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 d.title AS title,\n d.updated_at AS updated_at,\n stored.access_state_hash AS access_state_hash,\n stored.effective_access_level AS effective_access_level\n FROM document_projection d\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = d.local_id\n WHERE d.local_id = ?\n ${scope.whereSql}\n LIMIT 1\n `,\n [localId, ...scope.bind],\n );\n\n return mapContainerContentsDocumentSummaryRow(rows[0] ?? {});\n}\n\nfunction loadContainerContentsDocumentSummary(\n execSql: ExecSql,\n localId: string,\n requireHydrated: boolean,\n): Promise<DocumentSummary | null> {\n return queryContainerContentsDocumentSummary(execSql, localId, {\n bind: [],\n whereSql: requireHydrated\n ? `AND ${hydratedProjectionSql(\"d.local_id\", \"documents\")}`\n : \"\",\n });\n}\n\nfunction loadContainerContentsOrphanedDocumentSummary(\n execSql: ExecSql,\n localId: string,\n currentOrganizationId: string | null,\n requireHydrated: boolean,\n): Promise<DocumentSummary | null> {\n return queryContainerContentsDocumentSummary(execSql, localId, {\n bind: getOrphanedDocumentQueryBind(currentOrganizationId),\n whereSql: `${requireHydrated ? `AND ${hydratedProjectionSql(\"d.local_id\", \"documents\")}` : \"\"} AND ${getOrphanedDocumentWhereSql(\n {\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n },\n )}`,\n });\n}\n\nasync function loadContainerContentsDocumentSyncState(\n execSql: ExecSql,\n localId: string,\n): Promise<ContainerDocumentObjectSyncState | null> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const rows = await execSql(\n `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.document_id AS document_id,\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 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 d.local_id = ?\n LIMIT 1\n `,\n [localId],\n );\n const [row] = rows;\n if (!row) {\n return null;\n }\n\n return mapContainerContentsDocumentSyncStateRow(row);\n}\n\nasync function listContainerContentsLinkedContainerIdsByDocumentIds(\n execSql: ExecSql,\n documentIds: ReadonlyArray<string>,\n): Promise<ReadonlyMap<string, ReadonlyArray<string>>> {\n const uniqueDocumentIds = Array.from(new Set(documentIds));\n if (uniqueDocumentIds.length === 0) {\n return new Map();\n }\n\n const linkedContainerIdsByDocumentId = new Map<string, string[]>();\n for (const documentId of uniqueDocumentIds) {\n linkedContainerIdsByDocumentId.set(documentId, []);\n }\n\n for (const documentIdBatch of listContainerContentsSqlIdBatches(\n uniqueDocumentIds,\n )) {\n const batchLinkedContainerIdsByDocumentId =\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n execSql,\n documentIdBatch,\n );\n for (const [\n documentId,\n linkedContainerIds,\n ] of batchLinkedContainerIdsByDocumentId.entries()) {\n linkedContainerIdsByDocumentId.set(\n documentId,\n Array.from(linkedContainerIds),\n );\n }\n }\n\n return linkedContainerIdsByDocumentId;\n}\n\nexport function createContainerDocumentQueriesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): ContainerDocumentQueries {\n const execSql = runtime.infra.execSql;\n return {\n ...createFolderRecoveryQueries(execSql),\n applyContainerDocumentTombstones(tombstones) {\n return applyPersistedContainerDocumentTombstones(execSql, tombstones);\n },\n hasOrphanedDocuments({ currentOrganizationId }) {\n return hasOrphanedDocuments(execSql, currentOrganizationId);\n },\n listContainerDocumentSidebarWindow(input) {\n return listContainerDocumentSidebarWindow(execSql, input);\n },\n listContainerItemWindow(input) {\n return listContainerItemWindow(execSql, input);\n },\n loadDocumentSyncState(localId) {\n return loadContainerContentsDocumentSyncState(execSql, localId);\n },\n loadDocumentSummary(localId, options) {\n return loadContainerContentsDocumentSummary(\n execSql,\n localId,\n options?.requireHydrated ?? false,\n );\n },\n loadOrphanedDocumentSummary({\n currentOrganizationId,\n localId,\n requireHydrated = false,\n }) {\n return loadContainerContentsOrphanedDocumentSummary(\n execSql,\n localId,\n currentOrganizationId,\n requireHydrated,\n );\n },\n loadContainerDocumentWatermark(containerId) {\n return sqlContainerSyncWatermarkPersistence.loadWatermark(\n execSql,\n containerContentsSyncLane(containerId),\n );\n },\n listLinkedContainerIdsByDocumentIds(documentIds) {\n return listContainerContentsLinkedContainerIdsByDocumentIds(\n execSql,\n documentIds,\n );\n },\n listPendingDownloads() {\n return listPendingDownloads(execSql);\n },\n listPendingWrites() {\n return listPendingWrites(execSql);\n },\n retryPendingWriteItem(input) {\n return resetPendingWriteRetryState(execSql, input);\n },\n replaceDocumentLinksBatch(inputs) {\n return sqlDocumentContainerProjectionPersistence.replaceDocumentLinksBatch(\n execSql,\n inputs,\n );\n },\n async saveContainerDocumentWatermark(containerId, watermark) {\n await sqlContainerSyncWatermarkPersistence.saveWatermark(\n execSql,\n containerContentsSyncLane(containerId),\n watermark,\n );\n },\n upsertDiscoveredDocuments(inputs) {\n return upsertDiscoveredDocuments(execSql, inputs);\n },\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentRuntimeTargetSync.js","sourceRoot":"","sources":["documentRuntimeTargetSync.ts"],"names":[],"mappings":"AAMA,+EAA+E;AAC/E,8EAA8E;AAC9E,6CAA6C;AAC7C,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAEzC,KAAK,UAAU,wBAAwB,CAAmB,KAYzD;IACC,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC5C,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAA2B,CAAC;IACjE,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAElD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO,iBAAiB,CAAC;QAC3C,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QACD,IACE,iBAAiB,CAAC,IAAI,GAAG,CAAC;YAC1B,iBAAiB,CAAC,IAAI,GAAG,8BAA8B,KAAK,CAAC,EAC7D,CAAC;YACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7D,IAAI,CAAC,SAAS,EAAE;gBAAE,OAAO,iBAAiB,CAAC;QAC7C,CAAC;QAED,IAAI,OAAO,GAAG,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACnE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;YACxE,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC;YACzC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO;SACR,CAAC,CAAC;QACH,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAW,KAI1D;IACC,OAAO,wBAAwB,CAAC;QAC9B,GAAG,KAAK;QACR,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACxC,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAW,KAIhE;IACC,OAAO,wBAAwB,CAAC;QAC9B,GAAG,KAAK;QACR,yEAAyE;QACzE,uEAAuE;QACvE,qEAAqE;QACrE,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE;KACvD,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type {\n ContainerContentsDocumentRuntimeTarget,\n ContainerDocumentPrimeHost,\n ContainerDocumentProbeHost,\n} from \"./documentQueries/types\";\n\n// Stores opened per macrotask. Opening is fire-and-forget, so yielding between\n// chunks keeps the main thread and serialized SQLite queue responsive while a\n// restored replica schedules a real backlog.\nconst DOCUMENT_STORE_OPEN_CHUNK_SIZE = 8;\n\nasync function requestRuntimeTargetSync<TRuntime, TStore>(input: {\n readonly host: {\n documentWorkflowRuntime: (containerId: string | null) => TRuntime;\n openDocumentStore: (input: {\n documentId: string | null;\n localId: string;\n runtime: TRuntime;\n }) => TStore;\n };\n readonly isCurrent?: (() => boolean) | undefined;\n readonly requestStoreSync: (store: TStore) => void;\n readonly targets: ReadonlyArray<ContainerContentsDocumentRuntimeTarget>;\n}): Promise<ReadonlySet<string>> {\n const requestedLocalIds = new Set<string>();\n const runtimesByContainerId = new Map<string | null, TRuntime>();\n const isCurrent = input.isCurrent ?? (() => true);\n\n for (const target of input.targets) {\n if (!isCurrent()) return requestedLocalIds;\n if (requestedLocalIds.has(target.localId)) {\n continue;\n }\n if (\n requestedLocalIds.size > 0 &&\n requestedLocalIds.size % DOCUMENT_STORE_OPEN_CHUNK_SIZE === 0\n ) {\n await new Promise<void>((resolve) => setTimeout(resolve, 0));\n if (!isCurrent()) return requestedLocalIds;\n }\n\n let runtime = runtimesByContainerId.get(target.runtimeContainerId);\n if (runtime === undefined) {\n runtime = input.host.documentWorkflowRuntime(target.runtimeContainerId);\n runtimesByContainerId.set(target.runtimeContainerId, runtime);\n }\n\n const store = input.host.openDocumentStore({\n documentId: target.documentId,\n localId: target.localId,\n runtime,\n });\n requestedLocalIds.add(target.localId);\n input.requestStoreSync(store);\n }\n\n return requestedLocalIds;\n}\n\nexport function requestDocumentRuntimeTargetSync<TRuntime>(input: {\n readonly host: ContainerDocumentPrimeHost<TRuntime>;\n readonly isCurrent?: (() => boolean) | undefined;\n readonly targets: ReadonlyArray<ContainerContentsDocumentRuntimeTarget>;\n}): Promise<ReadonlySet<string>> {\n return requestRuntimeTargetSync({\n ...input,\n requestStoreSync: (store) => {\n if (store.getSnapshot?.().ready ?? true) {\n store.requestSync();\n }\n },\n });\n}\n\nexport function requestRemoteDocumentRuntimeTargetSync<TRuntime>(input: {\n readonly host: ContainerDocumentProbeHost<TRuntime>;\n readonly isCurrent?: (() => boolean) | undefined;\n readonly targets: ReadonlyArray<ContainerContentsDocumentRuntimeTarget>;\n}): Promise<ReadonlySet<string>> {\n return requestRuntimeTargetSync({\n ...input,\n // Unlike ordinary startup priming, a probe must survive a freshly opened\n // store's initialization. requestRemoteSync records that intent before\n // scheduling, so the first ready pass performs an HTTP revalidation.\n requestStoreSync: (store) => store.requestRemoteSync(),\n });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentStructure.js","sourceRoot":"","sources":["documentStructure.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from \"../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport {\n addDocumentLinkLocally,\n removeDocumentLinkLocally,\n} from \"./documentLinkIntent\";\nimport { relinkContainerDocumentLocally } from \"./documentLocalRelink\";\nimport { moveRemoteDocumentLinkLocally } from \"./documentMoveIntent\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationRuntime,\n SetLinkedContainerIdsForDocument,\n} from \"./documentStructureTypes\";\n\nexport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationRelinkInput,\n DocumentStructuralMutationRuntime,\n MergeDocumentSummary,\n SetLinkedContainerIdsForDocument,\n} from \"./documentStructureTypes\";\n\ninterface DocumentStructuralMutationInput<TRuntime> {\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n requireDocumentId: boolean;\n runtime: DocumentStructuralMutationRuntime;\n}\n\nexport function canMutateDocumentLink(runtime: {\n readonly auth: Pick<\n DocumentStructuralMutationRuntime[\"auth\"],\n \"isAuthenticated\"\n >;\n readonly infra: Pick<DocumentStructuralMutationRuntime[\"infra\"], \"dbStatus\">;\n readonly state: Pick<DocumentStructuralMutationRuntime[\"state\"], \"online\">;\n}): boolean {\n return (\n runtime.infra.dbStatus === \"ready\" &&\n runtime.auth.isAuthenticated &&\n runtime.state.online\n );\n}\n\nexport function canMutateLocalDocumentLink(runtime: {\n readonly infra: Pick<DocumentStructuralMutationRuntime[\"infra\"], \"dbStatus\">;\n}): boolean {\n return runtime.infra.dbStatus === \"ready\";\n}\n\nasync function openDocumentStoreForStructuralMutation<TRuntime>({\n host,\n note,\n requireDocumentId,\n runtime,\n}: DocumentStructuralMutationInput<TRuntime>) {\n if (requireDocumentId && !note.documentId) {\n return null;\n }\n\n const documentStore = host.openDocumentStore({\n containerId: note.containerId,\n documentId: note.documentId,\n localId: note.id,\n });\n if (!(await documentStore.ensureInitialized())) {\n runtime.util.log(\n `Container contents: note ${note.id} is not ready to mutate locally`,\n );\n return null;\n }\n\n return documentStore;\n}\n\nexport async function moveLocalDocumentLink<TRuntime>(params: {\n expandNode: (nodeId: string) => void;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}): Promise<DocumentSummary | null> {\n const { expandNode, host, note, runtime, targetContainerId } = params;\n if (note.containerId === targetContainerId) {\n return null;\n }\n\n const currentDocumentStore = await openDocumentStoreForStructuralMutation({\n host,\n note,\n requireDocumentId: false,\n runtime,\n });\n if (!currentDocumentStore) {\n return null;\n }\n\n const movedNote = await relinkContainerDocumentLocally({\n accessEpoch: DEFAULT_DOCUMENT_ACCESS_EPOCH,\n currentDocumentStore,\n host,\n note,\n requestSync: true,\n runtime,\n targetContainerId,\n });\n if (!movedNote) {\n return null;\n }\n\n expandNode(targetContainerId);\n runtime.util.log(\n `Container contents: moved local note ${movedNote.id} to ${targetContainerId}`,\n );\n return movedNote;\n}\n\nexport async function moveDocumentLink<TRuntime>(params: {\n expandNode: (nodeId: string) => void;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<{ linksChanged: boolean; note: DocumentSummary | null }> {\n const {\n expandNode,\n host,\n note,\n replaceLinkedContainers,\n runtime,\n scheduleSync,\n setLinkedContainerIdsForDocument,\n targetContainerId,\n } = params;\n if (note.containerId === targetContainerId) {\n return { linksChanged: false, note: null };\n }\n if (!note.documentId) {\n const movedNote = await moveLocalDocumentLink({\n expandNode,\n host,\n note,\n runtime,\n targetContainerId,\n });\n return {\n linksChanged: movedNote !== null,\n note: movedNote,\n };\n }\n\n const currentDocumentStore = await openDocumentStoreForStructuralMutation({\n host,\n note,\n requireDocumentId: true,\n runtime,\n });\n if (!currentDocumentStore) {\n return { linksChanged: false, note: null };\n }\n\n const queuedMove = await moveRemoteDocumentLinkLocally({\n currentDocumentStore,\n expandNode,\n host,\n note: {\n ...note,\n documentId: note.documentId,\n },\n replaceLinkedContainers,\n runtime,\n scheduleSync,\n setLinkedContainerIdsForDocument,\n targetContainerId,\n });\n return queuedMove;\n}\n\nexport async function addDocumentLink<TRuntime>(params: {\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<DocumentSummary | null> {\n const { host, note, runtime } = params;\n if (!note.documentId || !note.containerId) {\n return null;\n }\n\n const currentDocumentStore = await openDocumentStoreForStructuralMutation({\n host,\n note,\n requireDocumentId: true,\n runtime,\n });\n if (!currentDocumentStore) {\n return null;\n }\n\n return addDocumentLinkLocally({\n ...params,\n currentDocumentStore,\n note: {\n ...note,\n documentId: note.documentId,\n containerId: note.containerId,\n },\n });\n}\n\nexport async function removeDocumentLink<TRuntime>(params: {\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n removedContainerId: string;\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n}): Promise<DocumentSummary | null> {\n const { host, note, runtime } = params;\n if (!note.documentId || !note.containerId) {\n return null;\n }\n\n const currentDocumentStore = await openDocumentStoreForStructuralMutation({\n host,\n note,\n requireDocumentId: true,\n runtime,\n });\n if (!currentDocumentStore) {\n return null;\n }\n\n // Keep the rotation preflight before accepting an unlink. Replay proves it\n // again before publishing the signed key rotation from the durable intent.\n await currentDocumentStore.assertCanRotateContentKey();\n return removeDocumentLinkLocally({\n ...params,\n currentDocumentStore,\n note: {\n ...note,\n documentId: note.documentId,\n containerId: note.containerId,\n },\n });\n}\n\nexport async function activateDocumentLink<TRuntime>(params: {\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}): Promise<DocumentSummary | null> {\n const { host, note, runtime, targetContainerId } = params;\n if (\n !note.documentId ||\n !note.containerId ||\n note.containerId === targetContainerId\n ) {\n return null;\n }\n\n const currentDocumentStore = await openDocumentStoreForStructuralMutation({\n host,\n note,\n requireDocumentId: true,\n runtime,\n });\n if (!currentDocumentStore) {\n return null;\n }\n\n const relinkedNote = await relinkContainerDocumentLocally({\n accessEpoch: DEFAULT_DOCUMENT_ACCESS_EPOCH,\n currentDocumentStore,\n host,\n note,\n requestSync: false,\n runtime,\n targetContainerId,\n });\n if (!relinkedNote) {\n return null;\n }\n\n runtime.util.log(\n `Container contents: switched active note ${relinkedNote.id} to ${targetContainerId}`,\n );\n return relinkedNote;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentStructureTypes.js","sourceRoot":"","sources":["documentStructureTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport type { ExecSql, RelinkPersistedDocumentInput } from \"../documents\";\nimport type { ContainerContentsProjectionUserKeyResolver } from \"./projectionKeys\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\nexport type MergeDocumentSummary = (nextDocument: DocumentSummary) => void;\nexport type SetLinkedContainerIdsForDocument = (\n documentId: string,\n linkedContainerIds: ReadonlyArray<string>,\n) => void;\n\nexport type DocumentStructuralMutationRuntime =\n ContainerContentsWorkflowRuntime & {\n resolveProjectionUserKey: ContainerContentsProjectionUserKeyResolver;\n };\n\nexport interface DocumentStructuralMutationRelinkInput\n extends RelinkPersistedDocumentInput {\n commitSideEffect?:\n | ((transactionExecSql: ExecSql) => Promise<void>)\n | undefined;\n contentKeyBundle?: string | null | undefined;\n documentKekTargets?: string | null | undefined;\n documentManifestBundle?: string | null | undefined;\n stillCurrent?: (() => boolean) | undefined;\n}\n\nexport interface DocumentStructuralMutationLocalStore<TRuntime> {\n assertCanRotateContentKey: () => Promise<Uint8Array>;\n ensureInitialized: () => Promise<boolean>;\n relink: (\n input: DocumentStructuralMutationRelinkInput,\n ) => Promise<DocumentSummary | null>;\n requestSync: () => void;\n updateRuntime: (runtime: TRuntime) => void;\n}\n\nexport interface DocumentStructuralMutationHost<TRuntime> {\n documentWorkflowRuntime: (containerId: string | null) => TRuntime;\n mergeDocumentSummary: MergeDocumentSummary;\n openDocumentStore: (input: {\n containerId: string | null;\n documentId: string | null;\n localId: string;\n }) => DocumentStructuralMutationLocalStore<TRuntime>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentSubtreeQueries.js","sourceRoot":"","sources":["documentSubtreeQueries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport {\n containerDocumentPlacementKey,\n listContainerDocumentTombstoneHoldsForDocuments,\n} from \"../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { compareContainerContentsDocumentSummaries } from \"./documentQueries/rows\";\nimport { listContainerContentsSqlIdBatches } from \"./documentQueries/sql\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerContentsSharedDocumentSummaries,\n ContainerDocumentQueriesRuntime,\n} from \"./documentQueries/types\";\n\nfunction addContainerContentsDocumentSummaries(\n documentSummariesById: Map<string, DocumentSummary>,\n documentSummaries: ReadonlyArray<DocumentSummary>,\n): void {\n for (const documentSummary of documentSummaries) {\n documentSummariesById.set(documentSummary.id, documentSummary);\n }\n}\n\nasync function listContainerContentsDocumentIdsByContainerIds(\n execSql: ExecSql,\n containerIds: ReadonlyArray<string>,\n): Promise<string[]> {\n const documentIds = new Set<string>();\n\n for (const containerIdBatch of listContainerContentsSqlIdBatches(\n containerIds,\n )) {\n const batchDocumentIds =\n await sqlDocumentContainerProjectionPersistence.listDocumentIdsByContainerIds(\n execSql,\n containerIdBatch,\n );\n for (const documentId of batchDocumentIds) {\n documentIds.add(documentId);\n }\n }\n\n return Array.from(documentIds).sort();\n}\n\nasync function listContainerContentsDocumentSummariesByContainerIdsOrDocumentIds(\n execSql: ExecSql,\n input: {\n containerIds: ReadonlyArray<string>;\n documentIds: ReadonlyArray<string>;\n sortDocumentSummaries: boolean;\n },\n): Promise<DocumentSummary[]> {\n const documentSummariesById = new Map<string, DocumentSummary>();\n\n for (const containerIdBatch of listContainerContentsSqlIdBatches(\n input.containerIds,\n )) {\n addContainerContentsDocumentSummaries(\n documentSummariesById,\n await sqlDocumentsPersistence.listDocumentsByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds: containerIdBatch,\n documentIds: [],\n },\n ),\n );\n }\n\n for (const documentIdBatch of listContainerContentsSqlIdBatches(\n input.documentIds,\n )) {\n addContainerContentsDocumentSummaries(\n documentSummariesById,\n await sqlDocumentsPersistence.listDocumentsByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds: [],\n documentIds: documentIdBatch,\n },\n ),\n );\n }\n\n const documentSummaries = Array.from(documentSummariesById.values());\n return input.sortDocumentSummaries\n ? documentSummaries.sort(compareContainerContentsDocumentSummaries)\n : documentSummaries;\n}\n\nfunction heldPlacementKey(\n documentId: string | null,\n containerId: string,\n): string {\n return containerDocumentPlacementKey({\n containerId,\n documentId: documentId ?? \"\",\n });\n}\n\nfunction withoutHeldPlacements(\n linkedContainerIdsByDocumentId: ReadonlyMap<string, ReadonlyArray<string>>,\n holds: ReadonlyArray<{ containerId: string; documentId: string }>,\n): {\n held: ReadonlySet<string>;\n links: ReadonlyMap<string, ReadonlyArray<string>>;\n} {\n const held = new Set(\n holds.map((hold) => heldPlacementKey(hold.documentId, hold.containerId)),\n );\n if (held.size === 0) {\n return { held, links: linkedContainerIdsByDocumentId };\n }\n return {\n held,\n links: new Map(\n Array.from(linkedContainerIdsByDocumentId, ([documentId, ids]) => [\n documentId,\n ids.filter((id) => !held.has(heldPlacementKey(documentId, id))),\n ]),\n ),\n };\n}\n\n/**\n * Shared batched read pipeline for a flat set of container ids: linked\n * document ids → document summaries → linked container ids per document.\n * Sorting is optional so device-first projection reads can skip it.\n */\nexport async function listContainerContentsDocumentsForContainers(\n execSql: ExecSql,\n containerIds: ReadonlyArray<string>,\n options: { sortDocumentSummaries: boolean },\n): Promise<ContainerContentsSharedDocumentSummaries> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const linkedDocumentIds =\n await listContainerContentsDocumentIdsByContainerIds(execSql, containerIds);\n const documentSummaries =\n await listContainerContentsDocumentSummariesByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds,\n documentIds: linkedDocumentIds,\n sortDocumentSummaries: options.sortDocumentSummaries,\n },\n );\n const documentIds = Array.from(\n new Set(\n documentSummaries.flatMap((documentSummary) =>\n documentSummary.documentId ? [documentSummary.documentId] : [],\n ),\n ),\n );\n const linkedContainerIdsByDocumentId = withoutHeldPlacements(\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n execSql,\n documentIds,\n ),\n await listContainerDocumentTombstoneHoldsForDocuments(execSql, documentIds),\n );\n\n // An earlier link-id read can race a move. Recheck membership against the\n // summaries and final link read so a fresh trash summary cannot ride stale\n // root ids into the root view. Notification fences reject older summaries.\n // A held placement (a listing tombstone awaiting signed evidence) is not a\n // membership here either, matching the container item and sidebar views.\n const requestedIds = new Set(containerIds);\n return {\n documentSummaries: documentSummaries.filter(\n (summary) =>\n (summary.containerId !== null &&\n requestedIds.has(summary.containerId) &&\n !linkedContainerIdsByDocumentId.held.has(\n heldPlacementKey(summary.documentId, summary.containerId),\n )) ||\n (summary.documentId !== null &&\n linkedContainerIdsByDocumentId.links\n .get(summary.documentId)\n ?.some((id) => requestedIds.has(id))),\n ),\n linkedContainerIdsByDocumentId: linkedContainerIdsByDocumentId.links,\n };\n}\n\nfunction listContainerContentsContainerSubtreeIds(\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>,\n rootContainerId: string,\n): string[] {\n const childrenByParentId = new Map<string, string[]>();\n for (const containerState of containersById.values()) {\n const parentId = containerState.container.parentId;\n if (parentId === null) {\n continue;\n }\n\n const children = childrenByParentId.get(parentId);\n if (children) {\n children.push(containerState.container.id);\n } else {\n childrenByParentId.set(parentId, [containerState.container.id]);\n }\n }\n\n const subtreeIds: string[] = [];\n const stack = [rootContainerId];\n const visited = new Set<string>();\n while (stack.length > 0) {\n const containerId = stack.pop();\n if (containerId === undefined || visited.has(containerId)) {\n continue;\n }\n visited.add(containerId);\n\n if (containersById.has(containerId)) {\n subtreeIds.push(containerId);\n }\n\n const children = childrenByParentId.get(containerId);\n if (children) {\n stack.push(...children);\n }\n }\n\n return subtreeIds;\n}\n\nfunction resolveContainerContentsDocumentRuntimeContainerId(params: {\n documentSummary: Pick<DocumentSummary, \"containerId\" | \"documentId\">;\n linkedContainerIdsByDocumentId: ReadonlyMap<string, ReadonlyArray<string>>;\n sharedContainerIds: ReadonlySet<string>;\n}): string | null {\n const {\n documentSummary,\n linkedContainerIdsByDocumentId,\n sharedContainerIds,\n } = params;\n if (\n documentSummary.containerId &&\n sharedContainerIds.has(documentSummary.containerId)\n ) {\n return documentSummary.containerId;\n }\n\n if (!documentSummary.documentId) {\n return null;\n }\n\n return (\n linkedContainerIdsByDocumentId\n .get(documentSummary.documentId)\n ?.find((containerId) => sharedContainerIds.has(containerId)) ?? null\n );\n}\n\nasync function listDocumentRuntimeTargetsForContainerSubtree(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n execSql: ExecSql;\n rootContainerId: string;\n}): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n const { containersById, execSql, rootContainerId } = input;\n const sharedContainerIds = new Set(\n listContainerContentsContainerSubtreeIds(containersById, rootContainerId),\n );\n if (sharedContainerIds.size === 0) {\n return [];\n }\n\n const { documentSummaries, linkedContainerIdsByDocumentId } =\n await listContainerContentsDocumentsForContainers(\n execSql,\n Array.from(sharedContainerIds),\n { sortDocumentSummaries: true },\n );\n\n return documentSummaries.flatMap((documentSummary) => {\n const runtimeContainerId =\n resolveContainerContentsDocumentRuntimeContainerId({\n documentSummary,\n linkedContainerIdsByDocumentId,\n sharedContainerIds,\n });\n if (!runtimeContainerId) {\n return [];\n }\n\n return [\n {\n documentId: documentSummary.documentId,\n localId: documentSummary.id,\n runtimeContainerId,\n },\n ];\n });\n}\n\nexport function listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n runtime,\n ...input\n}: Omit<\n Parameters<typeof listDocumentRuntimeTargetsForContainerSubtree>[0],\n \"execSql\"\n> & {\n runtime: ContainerDocumentQueriesRuntime;\n}): ReturnType<typeof listDocumentRuntimeTargetsForContainerSubtree> {\n return listDocumentRuntimeTargetsForContainerSubtree({\n ...input,\n execSql: runtime.infra.execSql,\n });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentTombstoneEvidence.js","sourceRoot":"","sources":["documentTombstoneEvidence.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,GAE9B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,wCAAwC,EAAE,MAAM,wCAAwC,CAAC;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,oCAAoC,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAE,yCAAyC,EAAE,MAAM,+CAA+C,CAAC;AAC1G,OAAO,EAAE,+BAA+B,EAAE,MAAM,yDAAyD,CAAC;AAC1G,OAAO,EAAE,2BAA2B,EAAE,MAAM,2DAA2D,CAAC;AACxG,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AAMvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AA+BtE,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,KAAK,UAAU,mBAAmB,CAChC,OAAyC,EACzC,IAAmC,EACnC,UAAkB,EAClB,UAA4C;IAE5C,MAAM,QAAQ,GAA4C,EAAE,CAAC;IAC7D,MAAM,IAAI,CAAC,wCAAwC,CAAC,UAAU,EAAE;QAC9D,wEAAwE;QACxE,iCAAiC;QACjC,0BAA0B,EAAE,IAAI;QAChC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9B,uBAAuB,EAAE,CAAC,aAAa,EAAE,EAAE;YACzC,MAAM,IAAI,GAAG,aAAa,CAAC,sBAAsB,CAAC,GAAG,CACnD,UAAU,CAAC,gBAAgB,CAAC,YAAY,CACzC,CAAC;YACF,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACjD,QAAQ,CAAC,KAAK,GAAG;oBACf,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;oBACzC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;oBAC7B,eAAe,EAAE,IAAI,CAAC,YAAY;oBAClC,kBAAkB,EAAE,mBAAmB,CACrC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAC9B;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,wBAAwB,EAAE,+BAA+B,CAAC,OAAO,CAAC;QAClE,+BAA+B,EAC7B,kCAAkC,CAAC,OAAO,CAAC;KAC9C,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,OAAyC,EACzC,UAAkB,EAClB,KAAc;IAEd,MAAM,gBAAgB,GAAG,MAAM,yCAAyC,CACtE,KAAK,EACL,OAAO,CAAC,IAAI,CAAC,sBAAsB,EACnC;QACE,QAAQ,EAAE,UAAU;QACpB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,6BAA6B;KACzC,CACF,CAAC;IACF,IAAI,CAAC;QACH,IACE,CAAC,gBAAgB;YACjB,KAAK,YAAY,oCAAoC,EACrD,CAAC;YACD,uEAAuE;YACvE,gEAAgE;YAChE,OAAO,CAAC,SAAS,CAAC,6BAA6B,CAAC,UAAU,CAAC,CAAC;YAC5D,OAAO,CAAC,IAAI,CAAC,GAAG,CACd,uDAAuD,UAAU,qCAAqC,CACvG,CAAC;YACF,OAAO;QACT,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CACrB,uDAAuD,EACvD,KAAK,CACN,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,OAAyC,EACzC,OAAsC;IACpC,wCAAwC;IACxC,2BAA2B;CAC5B;IAED,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,EAAE;QAChD,IAAI,CAAC;YACH,uEAAuE;YACvE,0BAA0B;YAC1B,IACE,MAAM,IAAI,CAAC,2BAA2B,CACpC,OAAO,CAAC,KAAK,CAAC,OAAO,EACrB,UAAU,CACX,EACD,CAAC;gBACD,OAAO;oBACL,cAAc,EAAE,IAAI;oBACpB,WAAW,EAAE,MAAM,CAAC,gBAAgB;oBACpC,kBAAkB,EAAE,EAAE;iBACvB,CAAC;YACJ,CAAC;YACD,wEAAwE;YACxE,uEAAuE;YACvE,IAAI,CAAC,oBAAoB;gBACvB,OAAO,CAAC,SAAS,CAAC,6BAA6B,CAAC,UAAU,CAAC,CAAC;YAC9D,IAAI,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,iCAAiC,CACpE,UAAU,EACV,EAAE,YAAY,EAAE,KAAK,EAAE,CACxB,CAAC;YACF,IACE,oBAAoB;gBACpB,MAAM,CAAC,EAAE;gBACT,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,KAAK,oBAAoB,EAClE,CAAC;gBACD,OAAO,CAAC,SAAS,CAAC,6BAA6B,CAAC,UAAU,CAAC,CAAC;gBAC5D,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,iCAAiC,CAChE,UAAU,EACV,EAAE,YAAY,EAAE,KAAK,EAAE,CACxB,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,IACE,MAAM,CAAC,MAAM,KAAK,GAAG;oBACrB,MAAM,CAAC,IAAI,KAAK,6BAA6B;oBAE7C,OAAO,WAAW,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,GAAG,CACd,uDAAuD,UAAU,oBAAoB,MAAM,CAAC,MAAM,IAAI,SAAS,GAAG,CACnH,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,MAAM,mBAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,oEAAoE;YACpE,4DAA4D;YAC5D,MAAM,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CACtB,UAAqD,EACrD,IAAwC;IAExC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAqC,EAAE;QACrE,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;QAC3C,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5D,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;gBAC3C,SAAS;aACV,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE;gBACT,GAAG,SAAS;gBACZ,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;aAC5C;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wCAAwC,CACtD,cAAkC,EAClC,uBAAkD,EAClD,4BAA4D;IAE5D,OAAO,KAAK,EAAE,UAAU,EAAE,EAAE;QAC1B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAwC,CAAC;QACrE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAA0C,MAAM,CAAC,GAAG,CAChE,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,EAAuC,EAAE,CACxD,KAAK,GAAG,2BAA2B;YACjC,CAAC,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC;YAC9B,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,CAClE,CAAC;QACF,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,OAAO,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,EAAE,CAAC;gBACnE,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;gBACrB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5B,IAAI,CAAC,KAAK;oBAAE,MAAM;gBAClB,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC;gBAClC,MAAM,IAAI,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC;gBACvD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,WAAW;oBAAE,SAAS;gBACpD,IAAI,CAAC,+BAA+B,CAAC,IAAI,EAAE,cAAc,CAAC;oBAAE,SAAS;gBACrE,qEAAqE;gBACrE,mEAAmE;gBACnE,MAAM,UAAU,GAAG,MAAM,4BAA4B,CAAC,UAAU,CAAC,CAAC,KAAK,CACrE,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAC9B,CAAC;gBACF,IAAI,IAAI,CAAC,WAAW,GAAG,UAAU;oBAAE,SAAS;gBAC5C,QAAQ,CAAC,KAAK,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACjD,CAAC;QACH,CAAC,CAAC;QACF,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CACR,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EACnE,MAAM,CACP,CACF,CAAC;QACF,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {\n DOCUMENT_NOT_FOUND_ERROR_CODE,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../data/documents/shared/projection\";\nimport { uniqueSortedStrings } from \"../../data/documents/shared/readers\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { reportKeyingVerificationErrorInCauseChain } from \"../../data/keyingProjectionVerification/error\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport { loadDocumentPurgeCheckpoint } from \"../../data/persistence/documentPurgeCheckpointPersistence\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../principals/runtimePolicyWarmer\";\nimport type {\n ContainerDocumentTombstone,\n ContainerDocumentTombstoneVerdict,\n ContainerDocumentTombstoneVerifier,\n} from \"./documentDiscoveryTypes\";\nimport { documentHeadMatchesOrganization } from \"./documentHeadScope\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\nexport interface VerifiedDocumentHeadLinkSet {\n readonly organizationId: string | null;\n readonly accessEpoch: number;\n /** Present for a signed head; a terminal purge has no live access state. */\n readonly accessStateHash?: string;\n readonly linkedContainerIds: ReadonlyArray<string>;\n}\n\n/**\n * The document's verified head link set, or `null` when no verified head is\n * available: the projection could not be fetched (the requester may no\n * longer read the document, or it was purged) or failed verification.\n */\nexport type DocumentHeadLinkSetLoader = (\n documentId: string,\n expectedManifestHash?: string,\n) => Promise<VerifiedDocumentHeadLinkSet | \"not-found\" | null>;\n\n/** The highest access epoch local state records for the document. */\nexport type LocalDocumentAccessEpochLoader = (\n documentId: string,\n) => Promise<number>;\n\nexport interface DocumentHeadLinkSetLoaderDeps {\n readonly assertDocumentWriterProjectionConsistent: typeof assertDocumentWriterProjectionConsistent;\n readonly loadDocumentPurgeCheckpoint: typeof loadDocumentPurgeCheckpoint;\n}\n\nexport const HEAD_LINK_SET_LOAD_CONCURRENCY = 4;\n/**\n * Head loads per settle. Tombstones beyond it stay unverified and are held\n * for a later, backed-off retry, so a bulk move out of a folder does not cost\n * every device an unbounded burst of fetches before the watermark advances.\n */\nexport const HEAD_LINK_SET_LOADS_PER_RUN = 32;\n\nasync function verifiedHeadLinkSet(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps,\n documentId: string,\n projection: DocumentWriterProjectionResponse,\n): Promise<VerifiedDocumentHeadLinkSet> {\n const verified: { value?: VerifiedDocumentHeadLinkSet } = {};\n await deps.assertDocumentWriterProjectionConsistent(projection, {\n // Only the link set is read; a bundle wrapped to superseded KEK targets\n // still carries the signed head.\n allowStaleContentKeyBundle: true,\n execSql: runtime.infra.execSql,\n onVerifiedAuthorization: (authorization) => {\n const head = authorization.documentManifestByHash.get(\n projection.documentManifest.manifestHash,\n );\n if (head && head.state.documentId === documentId) {\n verified.value = {\n organizationId: head.state.organizationId,\n accessEpoch: head.state.epoch,\n accessStateHash: head.manifestHash,\n linkedContainerIds: uniqueSortedStrings(\n head.state.linkedContainerIds,\n ),\n };\n }\n },\n resolveProjectionUserKey: createProjectionUserKeyResolver(runtime),\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!verified.value) {\n throw new Error(\"Tombstone evidence lacks a verified document head\");\n }\n return verified.value;\n}\n\nasync function reportUnavailableHead(\n runtime: ContainerContentsWorkflowRuntime,\n documentId: string,\n error: unknown,\n): Promise<void> {\n const integrityFailure = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: \"document.tombstone-evidence\",\n },\n );\n try {\n if (\n !integrityFailure &&\n error instanceof ProjectionDependencyUnavailableError\n ) {\n // A policy can advance without changing this document's hash. Drop its\n // cached evidence so the held head can recover on the next run.\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is awaiting current policy history`,\n );\n return;\n }\n runtime.util.logError?.(\n \"Container contents: tombstone evidence is unavailable\",\n error,\n );\n } catch {\n // A host logger that throws must not fail the discovery pass.\n }\n}\n\nexport function createDocumentHeadLinkSetLoader(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps = {\n assertDocumentWriterProjectionConsistent,\n loadDocumentPurgeCheckpoint,\n },\n): DocumentHeadLinkSetLoader {\n return async (documentId, expectedManifestHash) => {\n try {\n // A verified purge proof is terminal signed evidence that the document\n // links nothing any more.\n if (\n await deps.loadDocumentPurgeCheckpoint(\n runtime.infra.execSql,\n documentId,\n )\n ) {\n return {\n organizationId: null,\n accessEpoch: Number.MAX_SAFE_INTEGER,\n linkedContainerIds: [],\n };\n }\n // Tombstones require a fresh head. Listings can reuse a matching cached\n // projection, whose signature and local checkpoint are still verified.\n if (!expectedManifestHash)\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n let result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n if (\n expectedManifestHash &&\n result.ok &&\n result.data.documentManifest.manifestHash !== expectedManifestHash\n ) {\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n }\n if (!result.ok) {\n if (\n result.status === 404 &&\n result.code === DOCUMENT_NOT_FOUND_ERROR_CODE\n )\n return \"not-found\";\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is unavailable (${result.status ?? \"offline\"})`,\n );\n return null;\n }\n return await verifiedHeadLinkSet(runtime, deps, documentId, result.data);\n } catch (error) {\n // Any failure leaves the tombstone unverified (held and retried); a\n // thrown error here must not fail the whole discovery pass.\n await reportUnavailableHead(runtime, documentId, error);\n return null;\n }\n };\n}\n\nfunction judgeTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n head: VerifiedDocumentHeadLinkSet | null,\n): ContainerDocumentTombstoneVerdict[] {\n return tombstones.map((tombstone): ContainerDocumentTombstoneVerdict => {\n if (head === null) {\n return { kind: \"unverified\", tombstone };\n }\n if (head.linkedContainerIds.includes(tombstone.containerId)) {\n return {\n kind: \"refuted\",\n linkedContainerIds: head.linkedContainerIds,\n tombstone,\n };\n }\n return {\n kind: \"verified\",\n tombstone: {\n ...tombstone,\n accessEpoch: head.accessEpoch,\n linkedContainerIds: head.linkedContainerIds,\n },\n };\n });\n}\n\n/**\n * Judge listing tombstones against each document's verified head link set,\n * fetched once per document with bounded concurrency and a per-run cap. A\n * head whose epoch is below local document state is no evidence: it may be a\n * lagging replica or a replay, and applying it could delete rows a newer\n * listing or settled move wrote.\n */\nexport function createContainerDocumentTombstoneVerifier(\n organizationId: string | undefined,\n loadDocumentHeadLinkSet: DocumentHeadLinkSetLoader,\n loadLocalDocumentAccessEpoch: LocalDocumentAccessEpochLoader,\n): ContainerDocumentTombstoneVerifier {\n return async (tombstones) => {\n const byDocumentId = new Map<string, ContainerDocumentTombstone[]>();\n for (const tombstone of tombstones) {\n const group = byDocumentId.get(tombstone.documentId) ?? [];\n group.push(tombstone);\n byDocumentId.set(tombstone.documentId, group);\n }\n const groups = [...byDocumentId.entries()];\n const verdicts: ContainerDocumentTombstoneVerdict[][] = groups.map(\n ([, group], index): ContainerDocumentTombstoneVerdict[] =>\n index < HEAD_LINK_SET_LOADS_PER_RUN\n ? judgeTombstones(group, null)\n : group.map((tombstone) => ({ kind: \"deferred\", tombstone })),\n );\n let next = 0;\n const worker = async () => {\n while (next < Math.min(groups.length, HEAD_LINK_SET_LOADS_PER_RUN)) {\n const index = next++;\n const entry = groups[index];\n if (!entry) break;\n const [documentId, group] = entry;\n const head = await loadDocumentHeadLinkSet(documentId);\n if (head === null || head === \"not-found\") continue;\n if (!documentHeadMatchesOrganization(head, organizationId)) continue;\n // A local-state read that fails is treated like an unavailable head:\n // the tombstones stay held rather than failing the discovery pass.\n const localEpoch = await loadLocalDocumentAccessEpoch(documentId).catch(\n () => Number.MAX_SAFE_INTEGER,\n );\n if (head.accessEpoch < localEpoch) continue;\n verdicts[index] = judgeTombstones(group, head);\n }\n };\n await Promise.all(\n Array.from(\n { length: Math.min(HEAD_LINK_SET_LOAD_CONCURRENCY, groups.length) },\n worker,\n ),\n );\n return verdicts.flat();\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"documentTombstoneGate.js","sourceRoot":"","sources":["documentTombstoneGate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { containerDocumentPlacementKey as placementKey } from \"../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport type {\n ContainerDocumentPlacement,\n ContainerDocumentTombstone,\n ContainerDocumentTombstoneVerdict,\n DiscoverContainerDocumentsOptions,\n} from \"./documentDiscoveryTypes\";\n\ntype TombstoneGateStore = Pick<\n DiscoverContainerDocumentsOptions,\n | \"applyContainerDocumentTombstones\"\n | \"holdContainerDocumentTombstones\"\n | \"listHeldContainerDocumentTombstones\"\n | \"listKnownContainerDocumentPlacements\"\n | \"refuteContainerDocumentTombstoneHolds\"\n | \"verifyContainerDocumentTombstones\"\n>;\n\nfunction dedupePlacements<T extends ContainerDocumentPlacement>(\n placements: ReadonlyArray<T>,\n): T[] {\n const seen = new Set<string>();\n return placements.filter((placement) => {\n const key = placementKey(placement);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * One candidate per placement the device actually holds; the newest server\n * timestamp wins. A tombstone for a placement this device never had has\n * nothing to remove or hide, so its head is not fetched.\n */\nasync function mergeTombstoneCandidates(\n store: TombstoneGateStore,\n listed: ReadonlyArray<ContainerDocumentTombstone>,\n held: ReadonlyArray<ContainerDocumentTombstone>,\n): Promise<ContainerDocumentTombstone[]> {\n const known = new Set(\n (await store.listKnownContainerDocumentPlacements(listed)).map(\n placementKey,\n ),\n );\n const byPlacement = new Map<string, ContainerDocumentTombstone>();\n for (const tombstone of [\n ...held,\n ...listed.filter((tombstone) => known.has(placementKey(tombstone))),\n ]) {\n const key = placementKey(tombstone);\n const current = byPlacement.get(key);\n if (\n !current ||\n Date.parse(current.updatedAt) < Date.parse(tombstone.updatedAt)\n ) {\n byPlacement.set(key, tombstone);\n }\n }\n return [...byPlacement.values()];\n}\n\nfunction assertVerdictsCoverCandidates(\n candidates: ReadonlyArray<ContainerDocumentTombstone>,\n verdicts: ReadonlyArray<ContainerDocumentTombstoneVerdict>,\n): void {\n const verdictKeys = new Set(\n verdicts.map((verdict) => placementKey(verdict.tombstone)),\n );\n if (\n verdictKeys.size !== verdicts.length ||\n verdictKeys.size !== candidates.length ||\n candidates.some((candidate) => !verdictKeys.has(placementKey(candidate)))\n ) {\n throw new Error(\n \"Container document tombstone verification must return one verdict per tombstone\",\n );\n }\n}\n\n/**\n * Apply a tombstone only when the signed head omits its container. Unavailable\n * heads leave hidden placements. A head that still links a container keeps its\n * placement visible, but retains a backed-off retry: even an uncached signed\n * head can lag the listing, so its refutation must not discard an honest move.\n * Listing items pass their own signed-head gate before reaching persistence.\n */\nexport async function settleContainerDocumentTombstones(input: {\n containerIds: ReadonlyArray<string>;\n store: TombstoneGateStore;\n tombstones: ReadonlyArray<ContainerDocumentTombstone>;\n}): Promise<ReadonlyArray<DocumentSummary>> {\n const { store } = input;\n const held = await store.listHeldContainerDocumentTombstones(\n input.containerIds,\n );\n const candidates = await mergeTombstoneCandidates(\n store,\n input.tombstones,\n held,\n );\n if (candidates.length === 0) {\n return [];\n }\n\n const verdicts = await store.verifyContainerDocumentTombstones(candidates);\n assertVerdictsCoverCandidates(candidates, verdicts);\n const verified = verdicts.flatMap((verdict) =>\n verdict.kind === \"verified\" ? [verdict.tombstone] : [],\n );\n const refuted = verdicts.flatMap((verdict) =>\n verdict.kind === \"refuted\" ? [verdict.tombstone] : [],\n );\n const unverified = verdicts.flatMap((verdict) =>\n verdict.kind === \"unverified\" ? [verdict.tombstone] : [],\n );\n const deferred = verdicts.flatMap((verdict) =>\n verdict.kind === \"deferred\"\n ? [{ ...verdict.tombstone, deferred: true }]\n : [],\n );\n // A loaded head is evidence for every placement it links, including holds\n // on this document that were not due this run: make them visible while\n // retaining each retry, since the head may lag any of those tombstones.\n const headLinkedPlacements = verdicts.flatMap((verdict) => {\n if (verdict.kind !== \"verified\" && verdict.kind !== \"refuted\") return [];\n const linked =\n verdict.kind === \"verified\"\n ? verdict.tombstone.linkedContainerIds\n : verdict.linkedContainerIds;\n return linked.map((containerId) => ({\n containerId,\n documentId: verdict.tombstone.documentId,\n }));\n });\n\n const summaries =\n verified.length > 0\n ? await store.applyContainerDocumentTombstones(verified)\n : [];\n const retryKeys = new Set(refuted.map(placementKey));\n const visibleRetries = dedupePlacements(headLinkedPlacements).filter(\n (placement) => !retryKeys.has(placementKey(placement)),\n );\n if (visibleRetries.length > 0) {\n await store.refuteContainerDocumentTombstoneHolds(visibleRetries);\n }\n const retries = [\n ...unverified,\n ...deferred,\n ...refuted.map((tombstone) => ({ ...tombstone, refuted: true })),\n ];\n if (retries.length > 0) await store.holdContainerDocumentTombstones(retries);\n return summaries;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"folderRecovery.js","sourceRoot":"","sources":["folderRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,iDAAiD,CAAC;AACzD,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,wEAAwE,CAAC;AAahF,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC1D,OAAO;QACL,yBAAyB,CAAC,KAEzB;YACC,OAAO,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,mBAAmB,CAAC,KAEzB;YACC,MAAM,OAAO,GAAG,MAAM,6BAA6B,CACjD,OAAO,EACP,KAAK,CAAC,qBAAqB,CAC5B,CAAC;YACF,OAAO,OAAO,CAAC,GAAG,CAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE;gBACnD,MAAM,GAAG,GAAG,MAAM,+BAA+B,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBACtE,IAAI,CAAC;oBACH,IAAI,eAAe;wBACjB,aAAa,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;oBACvD,OAAO;wBACL,GAAG,MAAM;wBACT,GAAG,0BAA0B,CAAC,GAAG,EAAE,iBAAiB,CAAC;qBACtD,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACT,GAAG,CAAC,IAAI,EAAE,CAAC;gBACb,CAAC;YACH,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QACD,qBAAqB,CACnB,KAGC;YAED,OAAO,gCAAgC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport {\n createContainerMetadataDocument,\n readContainerMetadataValue,\n} from \"../../data/containers/containerMetadataDocument\";\nimport {\n discardRetainedContainerMetadata,\n listRecoveryFolderMoveIds,\n listRetainedContainerMetadata,\n} from \"../../data/persistence/container-contents/containerRecoveryPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\nexport interface RecoveryFolder {\n containerId: string;\n organizationId: string;\n name: string;\n icon: string | null;\n pendingUpdateCount: number;\n hasStructuralIntent: boolean;\n revision: string;\n}\n\nexport function createFolderRecoveryQueries(execSql: ExecSql) {\n return {\n listRecoveryFolderMoveIds(input: {\n currentOrganizationId: string | null;\n }): Promise<string[]> {\n return listRecoveryFolderMoveIds(execSql, input.currentOrganizationId);\n },\n async listRecoveryFolders(input: {\n currentOrganizationId: string | null;\n }): Promise<RecoveryFolder[]> {\n const records = await listRetainedContainerMetadata(\n execSql,\n input.currentOrganizationId,\n );\n return Promise.all(\n records.map(async ({ metadataUpdates, ...record }) => {\n const doc = await createContainerMetadataDocument(record.containerId);\n try {\n if (metadataUpdates)\n importUpdates(doc, [base64ToBytes(metadataUpdates)]);\n return {\n ...record,\n ...readContainerMetadataValue(doc, \"Untitled folder\"),\n };\n } finally {\n doc.free();\n }\n }),\n );\n },\n discardRecoveryFolder(\n input: Pick<\n RecoveryFolder,\n \"containerId\" | \"organizationId\" | \"revision\"\n >,\n ): Promise<boolean> {\n return discardRetainedContainerMetadata(execSql, input);\n },\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"metadata.js","sourceRoot":"","sources":["metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n encodeVersionVector,\n exportFullHistorySnapshot,\n} from \"@tearleads/loro\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { readPullContinuation } from \"../../data/documents/shared/syncPagination\";\nimport type { ProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport type { ContainerContentsPersistence } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { PendingUpdateRecord } from \"../../data/sqlite/documentPersistence\";\nimport { settleOutgoingPassAndDecideReArm } from \"../../data/sync/outgoingUpdateSettlement\";\nimport { shouldClearDocumentSyncFailureAfterPass } from \"../documents\";\nimport { applyIncomingContainerMetadataUpdates } from \"./metadataIncomingUpdateIsolation\";\nimport {\n currentMetadataPullContinuation,\n hasCurrentContainerMetadataReadState,\n installContainerMetadataRecord,\n persistContainerMetadataStateFromRuntime,\n} from \"./metadataPersistence\";\nimport {\n type ContainerMetadataSyncAttempt,\n type ContainerMetadataSyncRuntime,\n syncRemoteContainerMetadata,\n} from \"./metadataRemoteSync\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"./metadataStateIsolation\";\nimport { shouldRequestContainerMetadataFollowup } from \"./metadataSyncFollowup\";\n\nexport {\n hasContainerMetadataDocumentUpdateEvent,\n listContainerMetadataDocumentUpdateIds,\n} from \"./metadataEvents\";\nexport {\n installContainerMetadataRecord,\n persistContainerMetadataStateFromRuntime,\n renameContainerMetadataStateFromRuntime,\n setContainerIconMetadataStateFromRuntime,\n} from \"./metadataPersistence\";\n\nimport { invalidateContainerMetadataPullContinuation } from \"./metadataPullContinuationInvalidation\";\nimport {\n cleanupContainerMetadataRegistrationsOnFailure,\n discardUnacceptedContainerMetadataUpdateIds,\n preRegisterMaterializedContainerMetadataUpdateIds,\n} from \"./metadataSyncRegistrations\";\nimport type {\n ContainerMetadataState,\n MissingContainerMetadataState,\n SyncedContainerMetadataState,\n} from \"./metadataTypes\";\n\nexport {\n cleanupContainerMetadataRegistrationsOnFailure,\n preRegisterMaterializedContainerMetadataUpdateIds,\n} from \"./metadataSyncRegistrations\";\nexport type { ContainerMetadataPatch } from \"./metadataTypes\";\n\nexport function settleContainerMetadataOutgoingPass(\n metadataState: ContainerMetadataState,\n attempt: ContainerMetadataSyncAttempt,\n): boolean {\n const shouldReArmOutgoing = settleOutgoingPassAndDecideReArm(metadataState, {\n exhaustedPendingUpdateCount: attempt.synced.exhaustedPendingUpdateCount,\n outgoingUpdateCount: attempt.outgoingUpdateCount,\n rekeyedUpdateCount: attempt.synced.rekeyedPendingUpdateIds.length,\n settledUpdateCount: attempt.synced.settledPendingUpdateIds.length,\n acceptedRecoveryBaseline: attempt.synced.acceptedRecoveryBaseline,\n });\n return (\n attempt.synced.hasDeferredPendingUpdates ||\n shouldReArmOutgoing ||\n attempt.synced.hasIncompletePull\n );\n}\n\nfunction documentWriterProjectionMatchesMetadataSyncResponse(\n writerProjection: DocumentWriterProjectionResponse,\n synced: ContainerMetadataSyncAttempt[\"synced\"],\n): boolean {\n return (\n writerProjection.contentKeyBundle.contentKeyEpoch ===\n synced.response.contentKeyBundle.contentKeyEpoch &&\n writerProjection.contentKeyBundle.linkSetManifestHash ===\n synced.response.contentKeyBundle.linkSetManifestHash &&\n writerProjection.contentKeyBundle.targetHash ===\n synced.response.contentKeyBundle.targetHash &&\n writerProjection.documentKekTargets.linkSetManifestHash ===\n synced.response.documentKekTargets.linkSetManifestHash &&\n writerProjection.documentKekTargets.documentKeyTargetHash ===\n synced.response.documentKekTargets.documentKeyTargetHash\n );\n}\n\nfunction resolveSyncedContainerMetadataWriterProjection(\n metadataState: ContainerMetadataState,\n synced: ContainerMetadataSyncAttempt[\"synced\"],\n): DocumentWriterProjectionResponse | null {\n const writerProjection =\n synced.writerProjection ??\n (metadataState.metadataWriterProjection?.documentId ===\n synced.plan.documentId\n ? metadataState.metadataWriterProjection\n : null);\n return writerProjection &&\n documentWriterProjectionMatchesMetadataSyncResponse(\n writerProjection,\n synced,\n )\n ? writerProjection\n : null;\n}\n\n/**\n * Heals a stale metadata content-key bundle by rotating to a fresh content\n * key anchored by this full-history snapshot.\n */\nfunction metadataRotationSnapshotProvider(\n metadataState: ContainerMetadataState,\n): () => Promise<Uint8Array | null> {\n return async () => exportFullHistorySnapshot(metadataState.doc);\n}\n\ninterface SyncContainerMetadataStateInput {\n forceReadSync?: boolean | undefined;\n isCurrent: () => boolean;\n /**\n * Register sent ids before the network await so early self echoes cannot arm\n * a redundant read-sync. Shared with {@link listContainerMetadataDocumentUpdateIds}.\n */\n locallyAcceptedUpdateIds?: Set<string> | undefined;\n metadataState: ContainerMetadataState;\n onDurableStateNeedsReload?: (() => void) | undefined;\n persistence: ContainerContentsPersistence;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerMetadataSyncRuntime;\n targetSecretKey: Uint8Array;\n}\n\nasync function requestContainerMetadataSync(input: {\n documentId: string;\n metadataState: ContainerMetadataState;\n pendingUpdates: readonly PendingUpdateRecord[];\n sentUpdateIds: string[];\n syncInput: SyncContainerMetadataStateInput;\n}): Promise<ContainerMetadataSyncAttempt | null> {\n const { metadataState, sentUpdateIds, syncInput } = input;\n const { isCurrent, persistence, runtime } = syncInput;\n return cleanupContainerMetadataRegistrationsOnFailure(\n syncInput.locallyAcceptedUpdateIds,\n sentUpdateIds,\n () =>\n syncRemoteContainerMetadata({\n buildRotationSnapshot: metadataRotationSnapshotProvider(metadataState),\n containerId: metadataState.container.id,\n currentDocument: metadataState.doc,\n documentId: input.documentId,\n isCurrent,\n lastCommitLsn: metadataState.record.lastCommitLsn,\n localVersionVector: encodeVersionVector(metadataState.doc),\n onOutgoingUpdatesMaterialized: (updateIds) => {\n if (isCurrent()) {\n preRegisterMaterializedContainerMetadataUpdateIds(\n syncInput.locallyAcceptedUpdateIds,\n sentUpdateIds,\n updateIds,\n );\n }\n },\n onPullContinuationInvalidated: (continuation) =>\n invalidateContainerMetadataPullContinuation({\n continuation,\n isCurrent,\n metadataState,\n persistence,\n runtime,\n }),\n pendingUpdates: input.pendingUpdates,\n persistedState: metadataState.record,\n pullContinuation:\n currentMetadataPullContinuation(metadataState) ?? undefined,\n rekeyPendingUpdate: persistence.rekeyPendingUpdate,\n resolveProjectionUserKey: syncInput.resolveProjectionUserKey,\n runtime,\n targetSecretKey: syncInput.targetSecretKey,\n writerProjection:\n metadataState.metadataWriterProjection?.documentId ===\n input.documentId\n ? metadataState.metadataWriterProjection\n : undefined,\n }),\n );\n}\n\nexport async function syncContainerMetadataState(\n input: SyncContainerMetadataStateInput,\n): Promise<\n SyncedContainerMetadataState | MissingContainerMetadataState | null\n> {\n const { persistence, runtime } = input;\n const liveMetadataState = input.metadataState;\n const { isCurrent } = input;\n if (!isCurrent()) {\n return null;\n }\n const { documentId } = liveMetadataState.record;\n if (!documentId) {\n return null;\n }\n const execSql = runtime.infra.execSql;\n\n const pendingUpdates = await persistence.listPendingUpdates(\n execSql,\n liveMetadataState.container.id,\n );\n if (!isCurrent()) {\n return null;\n }\n if (\n pendingUpdates.length === 0 &&\n currentMetadataPullContinuation(liveMetadataState) === null &&\n !liveMetadataState.record.pullContinuationRecoveryRequired &&\n !input.forceReadSync &&\n hasCurrentContainerMetadataReadState(liveMetadataState.record)\n ) {\n return null;\n }\n const metadataState =\n await createDetachedContainerMetadataState(liveMetadataState);\n if (!isCurrent()) {\n return null;\n }\n\n const sentUpdateIds: string[] = [];\n\n const syncAttempt = await requestContainerMetadataSync({\n documentId,\n metadataState,\n pendingUpdates,\n sentUpdateIds,\n syncInput: input,\n });\n if (!syncAttempt) {\n return null;\n }\n if (!isCurrent()) {\n discardUnacceptedContainerMetadataUpdateIds(\n input.locallyAcceptedUpdateIds,\n sentUpdateIds,\n [],\n );\n return null;\n }\n const finalized = await finalizeContainerMetadataSync({\n documentId,\n isCurrent,\n locallyAcceptedUpdateIds: input.locallyAcceptedUpdateIds,\n metadataState,\n onDurableStateNeedsReload: input.onDurableStateNeedsReload,\n persistence,\n runtime,\n sentUpdateIds,\n syncAttempt,\n });\n if (!isCurrent() || !finalized) {\n return null;\n }\n if (!(\"missing\" in finalized)) {\n installDetachedContainerMetadataState(liveMetadataState, metadataState, {\n preserveConcurrentMetadataEdit: true,\n });\n }\n return finalized;\n}\n\nasync function finalizeContainerMetadataSync(input: {\n documentId: string;\n isCurrent: () => boolean;\n locallyAcceptedUpdateIds: Set<string> | undefined;\n metadataState: ContainerMetadataState;\n onDurableStateNeedsReload?: (() => void) | undefined;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataSyncRuntime;\n sentUpdateIds: readonly string[];\n syncAttempt: ContainerMetadataSyncAttempt;\n}): Promise<\n SyncedContainerMetadataState | MissingContainerMetadataState | null\n> {\n const { metadataState, syncAttempt } = input;\n const { outgoingUpdateCount, synced } = syncAttempt;\n if (!input.isCurrent()) {\n discardUnacceptedContainerMetadataUpdateIds(\n input.locallyAcceptedUpdateIds,\n input.sentUpdateIds,\n [],\n );\n return null;\n }\n // An id sent but not accepted will never be echoed. Accepted ids stay\n // registered until their realtime echo consumes them.\n discardUnacceptedContainerMetadataUpdateIds(\n input.locallyAcceptedUpdateIds,\n input.sentUpdateIds,\n synced.response.acceptedOutgoingUpdateIds,\n );\n metadataState.metadataWriterProjection =\n resolveSyncedContainerMetadataWriterProjection(metadataState, synced);\n if (synced.decryptedUpdates.length > 0) {\n applyIncomingContainerMetadataUpdates(metadataState.doc, synced);\n }\n const persisted = await persistContainerMetadataStateFromRuntime({\n acceptedPendingUpdateIds: synced.settledPendingUpdateIds,\n clearSyncFailure: shouldClearDocumentSyncFailureAfterPass(\n synced,\n outgoingUpdateCount,\n ),\n expectedSyncState: {\n pullContinuation: syncAttempt.consumedPullContinuation ?? null,\n record: syncAttempt.requestRecord,\n },\n metadataState,\n onDurableStateNeedsReload: input.onDurableStateNeedsReload,\n patch: {\n ...synced.persistedState,\n documentId: input.documentId,\n lastCommitLsn:\n synced.response.commitLsn ?? metadataState.record.lastCommitLsn ?? null,\n metadataDocumentId: input.documentId,\n pullContinuation: readPullContinuation(synced.response),\n },\n persistence: input.persistence,\n runtime: input.runtime,\n stillCurrent: input.isCurrent,\n });\n if (!input.isCurrent()) {\n discardUnacceptedContainerMetadataUpdateIds(\n input.locallyAcceptedUpdateIds,\n input.sentUpdateIds,\n [],\n );\n return null;\n }\n if (!persisted) {\n discardUnacceptedContainerMetadataUpdateIds(\n input.locallyAcceptedUpdateIds,\n input.sentUpdateIds,\n [],\n );\n metadataState.metadataWriterProjection = null;\n return { missing: true };\n }\n metadataState.container = persisted.container;\n installContainerMetadataRecord(metadataState, persisted.record);\n if (persisted.pullContinuationSuperseded) {\n // The response's accepted IDs were not durably settled. Treat every\n // pre-registration as unapplied so an early echo cannot hide work that the\n // forced follow-up still needs to reconcile.\n discardUnacceptedContainerMetadataUpdateIds(\n input.locallyAcceptedUpdateIds,\n input.sentUpdateIds,\n [],\n );\n metadataState.metadataWriterProjection = null;\n }\n\n return {\n ...persisted,\n shouldRequestFollowupSync: shouldRequestContainerMetadataFollowup({\n persisted,\n settleOutgoingPass: () =>\n settleContainerMetadataOutgoingPass(metadataState, syncAttempt),\n }),\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"metadataEvents.js","sourceRoot":"","sources":["metadataEvents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAGjF,MAAM,UAAU,uCAAuC,CACrD,MAA8B,EAC9B,cAAwE,EACxE,wBAAsC;IAEtC,0EAA0E;IAC1E,mCAAmC;IACnC,OAAO,CACL,sCAAsC,CACpC,MAAM,EACN,cAAc,EACd,wBAAwB,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,SAAS,CACzE,CAAC,MAAM,GAAG,CAAC,CACb,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAS,4BAA4B,CACnC,KAAoD,EACpD,wBAAiD;IAEjD,IACE,CAAC,wBAAwB;QACzB,CAAC,KAAK,CAAC,SAAS;QAChB,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAC5B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACvC,IAAI,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,iBAAiB,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,sCAAsC,CACpD,MAA8B,EAC9B,cAAwE,EACxE,wBAAsC;IAEtC,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9C,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,IAAI,OAAO,aAAa,CAAC,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACxD,mBAAmB,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,IAAI,mBAAmB,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE9C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IACE,CAAC,4BAA4B,CAAC,KAAK,CAAC;YACpC,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,EAC1C,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,4BAA4B,CAAC,KAAK,EAAE,wBAAwB,CAAC,EAAE,CAAC;YACnE,SAAS;QACX,CAAC;QACD,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import { isDocumentUpdateCreatedEvent } from \"../../data/documents/documentSync\";\nimport type { DocumentRecord } from \"../../data/sqlite/documentPersistence\";\n\nexport function hasContainerMetadataDocumentUpdateEvent(\n events: ReadonlyArray<unknown>,\n metadataStates: Iterable<{ record: Pick<DocumentRecord, \"documentId\"> }>,\n locallyAcceptedUpdateIds?: Set<string>,\n): boolean {\n // A boolean predicate must not consume self-echo ids before the real list\n // pass classifies the same events.\n return (\n listContainerMetadataDocumentUpdateIds(\n events,\n metadataStates,\n locallyAcceptedUpdateIds ? new Set(locallyAcceptedUpdateIds) : undefined,\n ).length > 0\n );\n}\n\n/** Consume local ids and report whether an event still contains a peer id. */\nfunction metadataEventHasRemoteUpdate(\n event: { updateIds?: readonly string[] | undefined },\n locallyAcceptedUpdateIds: Set<string> | undefined,\n): boolean {\n if (\n !locallyAcceptedUpdateIds ||\n !event.updateIds ||\n event.updateIds.length === 0\n ) {\n return true;\n }\n\n let remoteUpdateFound = false;\n for (const updateId of event.updateIds) {\n if (locallyAcceptedUpdateIds.has(updateId)) {\n locallyAcceptedUpdateIds.delete(updateId);\n } else {\n remoteUpdateFound = true;\n }\n }\n return remoteUpdateFound;\n}\n\nexport function listContainerMetadataDocumentUpdateIds(\n events: ReadonlyArray<unknown>,\n metadataStates: Iterable<{ record: Pick<DocumentRecord, \"documentId\"> }>,\n locallyAcceptedUpdateIds?: Set<string>,\n): string[] {\n const metadataDocumentIds = new Set<string>();\n for (const metadataState of metadataStates) {\n if (typeof metadataState.record.documentId === \"string\") {\n metadataDocumentIds.add(metadataState.record.documentId);\n }\n }\n if (metadataDocumentIds.size === 0) return [];\n\n const eventDocumentIds = new Set<string>();\n for (const event of events) {\n if (\n !isDocumentUpdateCreatedEvent(event) ||\n !metadataDocumentIds.has(event.documentId)\n ) {\n continue;\n }\n if (!metadataEventHasRemoteUpdate(event, locallyAcceptedUpdateIds)) {\n continue;\n }\n eventDocumentIds.add(event.documentId);\n }\n\n return Array.from(eventDocumentIds);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"metadataIncomingUpdateIsolation.js","sourceRoot":"","sources":["metadataIncomingUpdateIsolation.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,yDAAyD,CAAC;AAEjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,iCAAiC,EAAE,MAAM,4CAA4C,CAAC;AAC/F,OAAO,EAEL,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAIzF,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,KAStD;IACC,MAAM,wBAAwB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;QACpE,MAAM,iCAAiC,CAAC,aAAa,CAAC,CAAC,kBAAkB,CACvE,KAAK,IAAI,EAAE;YACT,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,KAAK,KAAK;gBAAE,OAAO;YAC1C,MAAM,yBAAyB,CAC7B,aAAa,EACb,KAAK,CAAC,aAAa,EACnB,KAAK,CAAC,OAAO,CACd,CAAC;QACJ,CAAC,EACD,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,KAAK,KAAK,CACpC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,eAA8C,EAC9C,MAA0D;IAE1D,kCAAkC,CAAC,eAAe,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,KAM/C;IACC,OAAO;QACL,gCAAgC,EAAE,KAAK,EACrC,OAAyC,EACzC,EAAE;YACF,MAAM,gCAAgC,CAAC;gBACrC,GAAG,KAAK;gBACR,OAAO,EAAE;oBACP,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACrC,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,IAAI;iBACb;aACF,CAAC,CAAC;YACH,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,KAAK,KAAK;gBAAE,OAAO;YAC1C,4BAA4B,CAC1B,KAAK,CAAC,eAAe,EACrB,KAAK,CAAC,QAAQ,EACd,OAAO,CACR,CAAC;QACJ,CAAC;QACD,uBAAuB,EAAE,CACvB,MAAuE,EACvE,EAAE,CACF,iCAAiC,CAAC;YAChC,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;SACzC,CAAC;KACL,CAAC;AACJ,CAAC","sourcesContent":["import {\n type DocumentSyncUpdateIsolationError,\n importDecryptedDocumentSyncUpdates,\n validateDocumentSyncUpdateImports,\n} from \"../../data/documents/shared/documentSyncUpdateIsolation\";\nimport type { SyncRemoteDocumentResult } from \"../../data/documents/shared/types\";\nimport { recordDocumentSyncFailure } from \"../../data/sqlite/documentPersistence\";\nimport { getClientSQLitePersistenceRuntime } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport {\n type ExecSql,\n runSerializedSqlMutation,\n} from \"../../data/sqlite/sqlSchema\";\nimport { reportDocumentSyncQuarantine } from \"../documents/reportDocumentSyncQuarantine\";\nimport type { WorkflowRuntimeUtilInput } from \"../shared/runtimeInput\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport async function recordCurrentMetadataSyncFailure(input: {\n execSql: ExecSql;\n failure: {\n readonly attemptedAt: string;\n readonly message: string;\n readonly status: number | null;\n };\n isCurrent?: (() => boolean) | undefined;\n metadataScope: { appKind: string; localId: string };\n}): Promise<void> {\n await runSerializedSqlMutation(input.execSql, async (lockedExecSql) => {\n await getClientSQLitePersistenceRuntime(lockedExecSql).guardedTransaction(\n async () => {\n if (input.isCurrent?.() === false) return;\n await recordDocumentSyncFailure(\n lockedExecSql,\n input.metadataScope,\n input.failure,\n );\n },\n () => input.isCurrent?.() !== false,\n );\n });\n}\n\nexport function applyIncomingContainerMetadataUpdates(\n currentDocument: ContainerMetadataState[\"doc\"],\n result: Pick<SyncRemoteDocumentResult, \"decryptedUpdates\">,\n): void {\n importDecryptedDocumentSyncUpdates(currentDocument, result.decryptedUpdates);\n}\n\nexport function metadataIncomingUpdateIsolation(input: {\n currentDocument: ContainerMetadataState[\"doc\"];\n execSql: ExecSql;\n isCurrent?: (() => boolean) | undefined;\n logError?: WorkflowRuntimeUtilInput[\"logError\"] | undefined;\n metadataScope: { appKind: string; localId: string };\n}) {\n return {\n onIncomingUpdateIsolationFailure: async (\n failure: DocumentSyncUpdateIsolationError,\n ) => {\n await recordCurrentMetadataSyncFailure({\n ...input,\n failure: {\n attemptedAt: new Date().toISOString(),\n message: failure.message,\n status: null,\n },\n });\n if (input.isCurrent?.() === false) return;\n reportDocumentSyncQuarantine(\n input.currentDocument,\n input.logError,\n failure,\n );\n },\n validateIncomingUpdates: (\n result: Pick<SyncRemoteDocumentResult, \"decryptedUpdates\" | \"response\">,\n ) =>\n validateDocumentSyncUpdateImports({\n currentDocument: input.currentDocument,\n decryptedUpdates: result.decryptedUpdates,\n responseUpdates: result.response.updates,\n }),\n };\n}\n"]}