@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 +1 @@
1
- {"version":3,"file":"createIntentSync.js","sourceRoot":"","sources":["createIntentSync.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContainerPathTooDeepError } from \"../../../data/containers/shared/containerPathLimits\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { ContainerCreateIntentSupersededError } from \"../../../data/persistence/container-contents/containerIntentPersistence\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"../metadataStateIsolation\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { hasRemoteContainerMetadataState } from \"../remoteHydration/reconciliation\";\nimport { syncListedContainerCreate } from \"./createAdoption\";\nimport {\n deferTooDeepCreate,\n recordRefusedTooDeepCreate,\n} from \"./createIntentDepth\";\nimport { CONTAINER_ALREADY_COMMITTED } from \"./createWithMetadata\";\nimport { createRemoteContainer, deleteRemoteContainer } from \"./remote\";\nimport type {\n ContainerCreateIntentSyncHost,\n ContainerCreateIntentSyncInput,\n ContainerCreateIntentSyncState,\n CreatedRemoteContainerState,\n} from \"./types\";\n\nclass IncompleteContainerCreateSettlementError extends Error {}\n\ntype CreateIntentSyncResult = \"abandoned\" | \"blocked\" | \"created\" | \"failed\";\n\nfunction currentCreateResult<\n Result extends Exclude<CreateIntentSyncResult, \"abandoned\">,\n>(isCurrent: () => boolean, result: Result): \"abandoned\" | Result {\n return isCurrent() ? result : \"abandoned\";\n}\n\nasync function reportContainerCreateIntegrityFailure(input: {\n readonly containerId: string;\n readonly error: unknown;\n readonly organizationId: string;\n readonly state: ContainerCreateIntentSyncState;\n}): Promise<void> {\n await reportAndRethrowKeyingVerificationError(\n input.error,\n input.state.runtime.util.reportSecurityIncident,\n {\n objectId: input.containerId,\n objectKind: \"container\",\n operation: \"container.create.replay\",\n organizationId: input.organizationId,\n },\n );\n}\n\nasync function recordContainerCreateFailure(input: {\n readonly error: unknown;\n readonly isCurrent: () => boolean;\n readonly intent: ContainerCreateIntentSyncInput[\"intent\"];\n readonly organizationId: string;\n readonly state: ContainerCreateIntentSyncState;\n}): Promise<\"abandoned\" | \"failed\"> {\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n await reportContainerCreateIntegrityFailure({\n containerId: input.intent.containerId,\n error: input.error,\n organizationId: input.organizationId,\n state: input.state,\n });\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n await input.state.persistence.recordCreateIntentRevisionError(\n input.state.runtime.infra.execSql,\n {\n containerId: input.intent.containerId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n message: `${input.error instanceof IncompleteContainerCreateSettlementError ? \"Container create persistence failed\" : \"Remote container create failed\"}: ${errorMessage(input.error)}`,\n stillCurrent: input.isCurrent,\n },\n );\n return currentCreateResult(input.isCurrent, \"failed\");\n}\n\nasync function persistCreatedRemoteContainerStateFromIntent(input: {\n containerState: ContainerState;\n created: CreatedRemoteContainerState;\n host: ContainerCreateIntentSyncHost;\n isCurrent: () => boolean;\n intent: ContainerCreateIntentSyncInput[\"intent\"];\n state: ContainerCreateIntentSyncState;\n}): Promise<\n | \"abandoned\"\n | \"identity-superseded\"\n | \"intent-superseded\"\n | \"missing\"\n | \"persisted\"\n> {\n const { containerState, created, host, intent, state } = input;\n if (!input.isCurrent()) return \"abandoned\";\n const persistenceCandidate =\n await createDetachedContainerMetadataState(containerState);\n if (!input.isCurrent()) return \"abandoned\";\n persistenceCandidate.container = {\n ...persistenceCandidate.container,\n createdAt: created.createdAt,\n serverCreatedAt: created.createdAt,\n serverUpdatedAt: created.updatedAt,\n updatedAt: created.updatedAt,\n };\n\n let persistenceResult: Awaited<\n ReturnType<ContainerCreateIntentSyncHost[\"persistContainerState\"]>\n >;\n try {\n persistenceResult = await host.persistContainerState(\n persistenceCandidate,\n {\n accessEpoch: 1,\n accessStateHash: created.accessManifestHash,\n lastCommitLsn: null,\n metadataDocumentId: created.metadataDocumentId,\n systemSlot: created.systemSlot,\n organizationId: created.organizationId,\n parentId: created.parentId,\n ...created.persistedMetadataState,\n },\n false,\n {\n serverTimestamps: {\n createdAt: created.createdAt,\n updatedAt: created.updatedAt,\n },\n },\n {\n createIntentSettlement: {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n remoteContainerId: created.containerId,\n remoteMetadataAccessStateHash: created.accessManifestHash,\n remoteMetadataDocumentId: created.metadataDocumentId,\n supersededMovePreviousParentId: created.parentId,\n },\n expectedStateWhenMissing: containerState,\n isCurrent: input.isCurrent,\n preserveDurableStructureWhenPending: true,\n },\n );\n } catch (error) {\n if (error instanceof ContainerCreateIntentSupersededError) {\n return \"intent-superseded\";\n }\n throw error;\n }\n if (!input.isCurrent() || persistenceResult.status === \"stale-generation\") {\n return \"abandoned\";\n }\n if (persistenceResult.status !== \"persisted\") return persistenceResult.status;\n if (persistenceResult.createIntentSettled !== true) {\n throw new IncompleteContainerCreateSettlementError(\n \"Container create persistence must settle the intent atomically\",\n );\n }\n const { record: nextRecord } = persistenceResult;\n if (!input.isCurrent()) return \"abandoned\";\n const currentContainerState = state.containersById.get(intent.containerId);\n if (!currentContainerState) return \"missing\";\n if (currentContainerState !== containerState) return \"identity-superseded\";\n\n installDetachedContainerMetadataState(containerState, persistenceCandidate, {\n candidateRecord: nextRecord,\n preserveConcurrentMetadataEdit: true,\n });\n containerState.container = {\n ...containerState.container,\n metadataDocumentId: created.metadataDocumentId,\n systemSlot: created.systemSlot,\n organizationId: created.organizationId,\n parentId: persistenceCandidate.container.parentId,\n serverCreatedAt: created.createdAt,\n serverUpdatedAt: created.updatedAt,\n createdAt: created.createdAt,\n updatedAt: created.updatedAt,\n };\n return \"persisted\";\n}\n\nasync function discardOrphanedRemoteContainer(input: {\n created: CreatedRemoteContainerState;\n isCurrent: () => boolean;\n state: ContainerCreateIntentSyncState;\n}): Promise<void> {\n if (!input.isCurrent()) {\n return;\n }\n const discardFailure = await deleteRemoteContainer({\n containerId: input.created.containerId,\n organizationId: input.created.organizationId,\n runtime: input.state.runtime,\n }).then(\n (deleted) => (deleted ? null : \"the server rejected the delete\"),\n (error: unknown) => errorMessage(error),\n );\n if (input.isCurrent() && discardFailure !== null) {\n input.state.runtime.util.log(\n `Container contents: failed to discard orphaned remote container ${input.created.containerId} after local delete: ${discardFailure}`,\n );\n }\n}\n\nasync function settleRemoteContainerCreate(input: {\n containerState: ContainerState;\n created: Awaited<ReturnType<typeof createRemoteContainer>>;\n syncInput: ContainerCreateIntentSyncInput;\n}): Promise<CreateIntentSyncResult> {\n const { containerState, created, syncInput } = input;\n const { host, intent, state } = syncInput;\n if (created === CONTAINER_ALREADY_COMMITTED) {\n // A lost create response leaves the intent pending until hydration installs\n // the committed remote metadata state.\n state.runtime.util.log(\n `Container contents: deferred create intent for ${intent.containerId}; container already committed remotely, awaiting hydration.`,\n );\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"blocked\";\n }\n if (!created) {\n await state.persistence.recordCreateIntentRevisionError(\n state.runtime.infra.execSql,\n {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n message: \"Remote container create was rejected or unavailable\",\n stillCurrent: syncInput.isCurrent,\n },\n );\n return currentCreateResult(syncInput.isCurrent, \"failed\");\n }\n if (!state.containersById.has(intent.containerId)) {\n // A same-generation local delete wins; discard the remote orphan instead\n // of resurrecting the deleted local container.\n await discardOrphanedRemoteContainer({\n created,\n isCurrent: syncInput.isCurrent,\n state,\n });\n return currentCreateResult(syncInput.isCurrent, \"failed\");\n }\n\n const persistenceStatus = await persistCreatedRemoteContainerStateFromIntent({\n containerState,\n created,\n host,\n isCurrent: syncInput.isCurrent,\n intent,\n state,\n });\n if (persistenceStatus === \"abandoned\") {\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"abandoned\";\n }\n if (persistenceStatus === \"missing\") {\n await discardOrphanedRemoteContainer({\n created,\n isCurrent: syncInput.isCurrent,\n state,\n });\n return currentCreateResult(syncInput.isCurrent, \"failed\");\n }\n if (persistenceStatus === \"identity-superseded\") {\n state.runtime.util.log(\n `Container contents: deferred create intent for ${intent.containerId}; another writer persisted its remote identity.`,\n );\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"blocked\";\n }\n if (persistenceStatus === \"intent-superseded\") {\n state.runtime.util.log(\n `Container contents: deferred create intent for ${intent.containerId}; a newer local intent superseded this pass.`,\n );\n return \"blocked\";\n }\n state.runtime.util.log(\n `Container contents: synced local container create ${containerState.container.id}`,\n );\n return \"created\";\n}\n\nasync function createPendingRemoteContainer(input: {\n containerState: ContainerState;\n parentState: ContainerState;\n syncInput: ContainerCreateIntentSyncInput;\n}): Promise<CreateIntentSyncResult> {\n const { containerState, parentState, syncInput } = input;\n const { intent, state } = syncInput;\n let created: Awaited<ReturnType<typeof createRemoteContainer>>;\n try {\n created = await createRemoteContainer({\n systemSlot: containerState.container.systemSlot,\n containerId: containerState.container.id,\n parentContainerId: parentState.container.id,\n resolveProjectionUserKey: state.resolveProjectionUserKey,\n runtime: state.runtime,\n stillCurrent: syncInput.isCurrent,\n });\n } catch (error) {\n if (error instanceof ContainerPathTooDeepError)\n return recordRefusedTooDeepCreate(syncInput);\n return recordContainerCreateFailure({\n error,\n isCurrent: syncInput.isCurrent,\n intent,\n organizationId: parentState.container.organizationId,\n state,\n });\n }\n if (!syncInput.isCurrent()) {\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"abandoned\";\n }\n try {\n return await settleRemoteContainerCreate({\n containerState,\n created,\n syncInput,\n });\n } catch (error) {\n if (!(error instanceof IncompleteContainerCreateSettlementError))\n throw error;\n return recordContainerCreateFailure({\n error,\n isCurrent: syncInput.isCurrent,\n intent,\n organizationId: parentState.container.organizationId,\n state,\n });\n }\n}\n\nasync function trySyncPendingContainerContentsContainerCreateIntent(\n input: ContainerCreateIntentSyncInput,\n): Promise<CreateIntentSyncResult> {\n const { intent, state } = input;\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n const containerState = state.containersById.get(intent.containerId);\n const parentState = state.containersById.get(intent.parentContainerId);\n\n if (!containerState || !parentState) {\n const execSql = state.runtime.infra.execSql;\n await state.persistence.recordCreateIntentRevisionError(execSql, {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n message: \"Container create intent references a missing local container\",\n stillCurrent: input.isCurrent,\n });\n return currentCreateResult(input.isCurrent, \"failed\");\n }\n\n if (typeof state.persistence.markCreateIntentRevisionSynced !== \"function\") {\n await state.persistence.recordCreateIntentRevisionError(\n state.runtime.infra.execSql,\n {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n message: \"Container create replay requires revision-CAS persistence\",\n stillCurrent: input.isCurrent,\n },\n );\n return currentCreateResult(input.isCurrent, \"failed\");\n }\n\n if (input.isRemoteSyncBlocked(parentState.container.organizationId)) {\n return \"blocked\";\n }\n\n if (hasRemoteContainerMetadataState(containerState)) {\n return syncListedContainerCreate({\n containerState,\n parentState,\n syncInput: input,\n });\n }\n\n // A parent whose own create has not settled may carry a listed identity\n // adoption has not verified, or has refused; nothing is created under it.\n if (\n !hasRemoteContainerMetadataState(parentState) ||\n input.isCreatePending(parentState.container.id)\n ) {\n return \"blocked\";\n }\n\n if (await deferTooDeepCreate(input)) {\n return currentCreateResult(input.isCurrent, \"blocked\");\n }\n\n return createPendingRemoteContainer({\n containerState,\n parentState,\n syncInput: input,\n });\n}\n\nexport async function syncPendingContainerCreateIntents(input: {\n host: ContainerCreateIntentSyncHost;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerCreateIntentSyncState;\n}): Promise<number> {\n if (!input.isCurrent()) {\n return 0;\n }\n const { host } = input;\n const state = { ...input.state };\n const execSql = state.runtime.infra.execSql;\n const pendingIntents =\n await state.persistence.listPendingCreateIntents(execSql);\n if (!input.isCurrent()) {\n return 0;\n }\n const remainingContainerIds = new Set(\n pendingIntents.map((intent) => intent.containerId),\n );\n // Only a create that settles in this pass leaves the pending set; a failed\n // or parked one stays pending even though this pass stops retrying it.\n const unsettledContainerIds = new Set(remainingContainerIds);\n let createdCount = 0;\n let progressed = true;\n\n while (progressed && input.isCurrent()) {\n progressed = false;\n\n for (const intent of pendingIntents) {\n if (!remainingContainerIds.has(intent.containerId)) {\n continue;\n }\n\n const result = await trySyncPendingContainerContentsContainerCreateIntent(\n {\n host,\n isCreatePending: (containerId) =>\n unsettledContainerIds.has(containerId),\n isCurrent: input.isCurrent,\n isRemoteSyncBlocked: input.isRemoteSyncBlocked,\n intent,\n requestRemoteReconciliation: input.requestRemoteReconciliation,\n state,\n },\n );\n if (result === \"abandoned\") {\n return createdCount;\n }\n\n if (result === \"blocked\") {\n continue;\n }\n\n remainingContainerIds.delete(intent.containerId);\n progressed = result === \"created\" || progressed;\n if (result === \"created\") {\n createdCount += 1;\n unsettledContainerIds.delete(intent.containerId);\n }\n }\n }\n\n return createdCount;\n}\n"]}
1
+ {"version":3,"file":"createIntentSync.js","sourceRoot":"","sources":["createIntentSync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qDAAqD,CAAC;AAChG,OAAO,EAAE,uCAAuC,EAAE,MAAM,kDAAkD,CAAC;AAC3G,OAAO,EAAE,oCAAoC,EAAE,MAAM,yEAAyE,CAAC;AAC/H,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EACL,oCAAoC,EACpC,qCAAqC,GACtC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAQxE,MAAM,wCAAyC,SAAQ,KAAK;CAAG;AAI/D,SAAS,mBAAmB,CAE1B,SAAwB,EAAE,MAAc;IACxC,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,qCAAqC,CAAC,KAKpD;IACC,MAAM,uCAAuC,CAC3C,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAC/C;QACE,QAAQ,EAAE,KAAK,CAAC,WAAW;QAC3B,UAAU,EAAE,WAAW;QACvB,SAAS,EAAE,yBAAyB;QACpC,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,KAM3C;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,qCAAqC,CAAC;QAC1C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;QACrC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,+BAA+B,CAC3D,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EACjC;QACE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;QACrC,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACjC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;QACzC,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,YAAY,wCAAwC,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,gCAAgC,KAAK,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QACtL,YAAY,EAAE,KAAK,CAAC,SAAS;KAC9B,CACF,CAAC;IACF,OAAO,mBAAmB,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,4CAA4C,CAAC,KAO3D;IAOC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC/D,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,WAAW,CAAC;IAC3C,MAAM,oBAAoB,GACxB,MAAM,oCAAoC,CAAC,cAAc,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,WAAW,CAAC;IAC3C,oBAAoB,CAAC,SAAS,GAAG;QAC/B,GAAG,oBAAoB,CAAC,SAAS;QACjC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,eAAe,EAAE,OAAO,CAAC,SAAS;QAClC,eAAe,EAAE,OAAO,CAAC,SAAS;QAClC,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;IAEF,IAAI,iBAEH,CAAC;IACF,IAAI,CAAC;QACH,iBAAiB,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAClD,oBAAoB,EACpB;YACE,WAAW,EAAE,CAAC;YACd,eAAe,EAAE,OAAO,CAAC,kBAAkB;YAC3C,aAAa,EAAE,IAAI;YACnB,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,GAAG,OAAO,CAAC,sBAAsB;SAClC,EACD,KAAK,EACL;YACE,gBAAgB,EAAE;gBAChB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B;SACF,EACD;YACE,sBAAsB,EAAE;gBACtB,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,gBAAgB,EAAE,MAAM,CAAC,EAAE;gBAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;gBACnC,iBAAiB,EAAE,OAAO,CAAC,WAAW;gBACtC,6BAA6B,EAAE,OAAO,CAAC,kBAAkB;gBACzD,wBAAwB,EAAE,OAAO,CAAC,kBAAkB;gBACpD,8BAA8B,EAAE,OAAO,CAAC,QAAQ;aACjD;YACD,wBAAwB,EAAE,cAAc;YACxC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,mCAAmC,EAAE,IAAI;SAC1C,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,oCAAoC,EAAE,CAAC;YAC1D,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,iBAAiB,CAAC,MAAM,KAAK,kBAAkB,EAAE,CAAC;QAC1E,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,iBAAiB,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC;IAC9E,IAAI,iBAAiB,CAAC,mBAAmB,KAAK,IAAI,EAAE,CAAC;QACnD,MAAM,IAAI,wCAAwC,CAChD,gEAAgE,CACjE,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,iBAAiB,CAAC;IACjD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,WAAW,CAAC;IAC3C,MAAM,qBAAqB,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3E,IAAI,CAAC,qBAAqB;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,qBAAqB,KAAK,cAAc;QAAE,OAAO,qBAAqB,CAAC;IAE3E,qCAAqC,CAAC,cAAc,EAAE,oBAAoB,EAAE;QAC1E,eAAe,EAAE,UAAU;QAC3B,8BAA8B,EAAE,IAAI;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,SAAS,GAAG;QACzB,GAAG,cAAc,CAAC,SAAS;QAC3B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,QAAQ,EAAE,oBAAoB,CAAC,SAAS,CAAC,QAAQ;QACjD,eAAe,EAAE,OAAO,CAAC,SAAS;QAClC,eAAe,EAAE,OAAO,CAAC,SAAS;QAClC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;IACF,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,KAI7C;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,qBAAqB,CAAC;QACjD,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW;QACtC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,cAAc;QAC5C,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;KAC7B,CAAC,CAAC,IAAI,CACL,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gCAAgC,CAAC,EAChE,CAAC,KAAc,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CACxC,CAAC;IACF,IAAI,KAAK,CAAC,SAAS,EAAE,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QACjD,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAC1B,mEAAmE,KAAK,CAAC,OAAO,CAAC,WAAW,wBAAwB,cAAc,EAAE,CACrI,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,2BAA2B,CAAC,KAI1C;IACC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACrD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC1C,IAAI,OAAO,KAAK,2BAA2B,EAAE,CAAC;QAC5C,4EAA4E;QAC5E,uCAAuC;QACvC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,MAAM,CAAC,WAAW,6DAA6D,CAClI,CAAC;QACF,SAAS,CAAC,2BAA2B,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAChE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,KAAK,CAAC,WAAW,CAAC,+BAA+B,CACrD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B;YACE,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,OAAO,EAAE,qDAAqD;YAC9D,YAAY,EAAE,SAAS,CAAC,SAAS;SAClC,CACF,CAAC;QACF,OAAO,mBAAmB,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,yEAAyE;QACzE,+CAA+C;QAC/C,MAAM,8BAA8B,CAAC;YACnC,OAAO;YACP,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,KAAK;SACN,CAAC,CAAC;QACH,OAAO,mBAAmB,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,iBAAiB,GAAG,MAAM,4CAA4C,CAAC;QAC3E,cAAc;QACd,OAAO;QACP,IAAI;QACJ,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,MAAM;QACN,KAAK;KACN,CAAC,CAAC;IACH,IAAI,iBAAiB,KAAK,WAAW,EAAE,CAAC;QACtC,SAAS,CAAC,2BAA2B,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAChE,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,8BAA8B,CAAC;YACnC,OAAO;YACP,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,KAAK;SACN,CAAC,CAAC;QACH,OAAO,mBAAmB,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,iBAAiB,KAAK,qBAAqB,EAAE,CAAC;QAChD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,MAAM,CAAC,WAAW,iDAAiD,CACtH,CAAC;QACF,SAAS,CAAC,2BAA2B,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAChE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,iBAAiB,KAAK,mBAAmB,EAAE,CAAC;QAC9C,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,MAAM,CAAC,WAAW,8CAA8C,CACnH,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,qDAAqD,cAAc,CAAC,SAAS,CAAC,EAAE,EAAE,CACnF,CAAC;IACF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,KAI3C;IACC,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACzD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACpC,IAAI,OAA0D,CAAC;IAC/D,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,qBAAqB,CAAC;YACpC,UAAU,EAAE,cAAc,CAAC,SAAS,CAAC,UAAU;YAC/C,WAAW,EAAE,cAAc,CAAC,SAAS,CAAC,EAAE;YACxC,iBAAiB,EAAE,WAAW,CAAC,SAAS,CAAC,EAAE;YAC3C,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;YACxD,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,YAAY,EAAE,SAAS,CAAC,SAAS;SAClC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,yBAAyB;YAC5C,OAAO,0BAA0B,CAAC,SAAS,CAAC,CAAC;QAC/C,OAAO,4BAA4B,CAAC;YAClC,KAAK;YACL,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,MAAM;YACN,cAAc,EAAE,WAAW,CAAC,SAAS,CAAC,cAAc;YACpD,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC;QAC3B,SAAS,CAAC,2BAA2B,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAChE,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,2BAA2B,CAAC;YACvC,cAAc;YACd,OAAO;YACP,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,wCAAwC,CAAC;YAC9D,MAAM,KAAK,CAAC;QACd,OAAO,4BAA4B,CAAC;YAClC,KAAK;YACL,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,MAAM;YACN,cAAc,EAAE,WAAW,CAAC,SAAS,CAAC,cAAc;YACpD,KAAK;SACN,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oDAAoD,CACjE,KAAqC;IAErC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpE,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEvE,IAAI,CAAC,cAAc,IAAI,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;QAC5C,MAAM,KAAK,CAAC,WAAW,CAAC,+BAA+B,CAAC,OAAO,EAAE;YAC/D,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,OAAO,EAAE,8DAA8D;YACvE,YAAY,EAAE,KAAK,CAAC,SAAS;SAC9B,CAAC,CAAC;QACH,OAAO,mBAAmB,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,OAAO,KAAK,CAAC,WAAW,CAAC,8BAA8B,KAAK,UAAU,EAAE,CAAC;QAC3E,MAAM,KAAK,CAAC,WAAW,CAAC,+BAA+B,CACrD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B;YACE,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,iBAAiB,EAAE,MAAM,CAAC,SAAS;YACnC,OAAO,EAAE,2DAA2D;YACpE,YAAY,EAAE,KAAK,CAAC,SAAS;SAC9B,CACF,CAAC;QACF,OAAO,mBAAmB,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,KAAK,CAAC,mBAAmB,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,+BAA+B,CAAC,cAAc,CAAC,EAAE,CAAC;QACpD,OAAO,yBAAyB,CAAC;YAC/B,cAAc;YACd,WAAW;YACX,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,IACE,CAAC,+BAA+B,CAAC,WAAW,CAAC;QAC7C,KAAK,CAAC,eAAe,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,EAC/C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,mBAAmB,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,4BAA4B,CAAC;QAClC,cAAc;QACd,WAAW;QACX,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAMvD;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5C,MAAM,cAAc,GAClB,MAAM,KAAK,CAAC,WAAW,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,qBAAqB,GAAG,IAAI,GAAG,CACnC,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CACnD,CAAC;IACF,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAC7D,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,UAAU,GAAG,IAAI,CAAC;IAEtB,OAAO,UAAU,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvC,UAAU,GAAG,KAAK,CAAC;QAEnB,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;YACpC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;gBACnD,SAAS;YACX,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,oDAAoD,CACvE;gBACE,IAAI;gBACJ,eAAe,EAAE,CAAC,WAAW,EAAE,EAAE,CAC/B,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC;gBACxC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;gBAC9C,MAAM;gBACN,2BAA2B,EAAE,KAAK,CAAC,2BAA2B;gBAC9D,KAAK;aACN,CACF,CAAC;YACF,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC3B,OAAO,YAAY,CAAC;YACtB,CAAC;YAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YAED,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACjD,UAAU,GAAG,MAAM,KAAK,SAAS,IAAI,UAAU,CAAC;YAChD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,YAAY,IAAI,CAAC,CAAC;gBAClB,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["import { ContainerPathTooDeepError } from \"../../../data/containers/shared/containerPathLimits\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { ContainerCreateIntentSupersededError } from \"../../../data/persistence/container-contents/containerIntentPersistence\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"../metadata/metadataStateIsolation\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { hasRemoteContainerMetadataState } from \"../remoteHydration/reconciliation\";\nimport { syncListedContainerCreate } from \"./createAdoption\";\nimport {\n deferTooDeepCreate,\n recordRefusedTooDeepCreate,\n} from \"./createIntentDepth\";\nimport { CONTAINER_ALREADY_COMMITTED } from \"./createWithMetadata\";\nimport { createRemoteContainer, deleteRemoteContainer } from \"./remote\";\nimport type {\n ContainerCreateIntentSyncHost,\n ContainerCreateIntentSyncInput,\n ContainerCreateIntentSyncState,\n CreatedRemoteContainerState,\n} from \"./types\";\n\nclass IncompleteContainerCreateSettlementError extends Error {}\n\ntype CreateIntentSyncResult = \"abandoned\" | \"blocked\" | \"created\" | \"failed\";\n\nfunction currentCreateResult<\n Result extends Exclude<CreateIntentSyncResult, \"abandoned\">,\n>(isCurrent: () => boolean, result: Result): \"abandoned\" | Result {\n return isCurrent() ? result : \"abandoned\";\n}\n\nasync function reportContainerCreateIntegrityFailure(input: {\n readonly containerId: string;\n readonly error: unknown;\n readonly organizationId: string;\n readonly state: ContainerCreateIntentSyncState;\n}): Promise<void> {\n await reportAndRethrowKeyingVerificationError(\n input.error,\n input.state.runtime.util.reportSecurityIncident,\n {\n objectId: input.containerId,\n objectKind: \"container\",\n operation: \"container.create.replay\",\n organizationId: input.organizationId,\n },\n );\n}\n\nasync function recordContainerCreateFailure(input: {\n readonly error: unknown;\n readonly isCurrent: () => boolean;\n readonly intent: ContainerCreateIntentSyncInput[\"intent\"];\n readonly organizationId: string;\n readonly state: ContainerCreateIntentSyncState;\n}): Promise<\"abandoned\" | \"failed\"> {\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n await reportContainerCreateIntegrityFailure({\n containerId: input.intent.containerId,\n error: input.error,\n organizationId: input.organizationId,\n state: input.state,\n });\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n await input.state.persistence.recordCreateIntentRevisionError(\n input.state.runtime.infra.execSql,\n {\n containerId: input.intent.containerId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n message: `${input.error instanceof IncompleteContainerCreateSettlementError ? \"Container create persistence failed\" : \"Remote container create failed\"}: ${errorMessage(input.error)}`,\n stillCurrent: input.isCurrent,\n },\n );\n return currentCreateResult(input.isCurrent, \"failed\");\n}\n\nasync function persistCreatedRemoteContainerStateFromIntent(input: {\n containerState: ContainerState;\n created: CreatedRemoteContainerState;\n host: ContainerCreateIntentSyncHost;\n isCurrent: () => boolean;\n intent: ContainerCreateIntentSyncInput[\"intent\"];\n state: ContainerCreateIntentSyncState;\n}): Promise<\n | \"abandoned\"\n | \"identity-superseded\"\n | \"intent-superseded\"\n | \"missing\"\n | \"persisted\"\n> {\n const { containerState, created, host, intent, state } = input;\n if (!input.isCurrent()) return \"abandoned\";\n const persistenceCandidate =\n await createDetachedContainerMetadataState(containerState);\n if (!input.isCurrent()) return \"abandoned\";\n persistenceCandidate.container = {\n ...persistenceCandidate.container,\n createdAt: created.createdAt,\n serverCreatedAt: created.createdAt,\n serverUpdatedAt: created.updatedAt,\n updatedAt: created.updatedAt,\n };\n\n let persistenceResult: Awaited<\n ReturnType<ContainerCreateIntentSyncHost[\"persistContainerState\"]>\n >;\n try {\n persistenceResult = await host.persistContainerState(\n persistenceCandidate,\n {\n accessEpoch: 1,\n accessStateHash: created.accessManifestHash,\n lastCommitLsn: null,\n metadataDocumentId: created.metadataDocumentId,\n systemSlot: created.systemSlot,\n organizationId: created.organizationId,\n parentId: created.parentId,\n ...created.persistedMetadataState,\n },\n false,\n {\n serverTimestamps: {\n createdAt: created.createdAt,\n updatedAt: created.updatedAt,\n },\n },\n {\n createIntentSettlement: {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n remoteContainerId: created.containerId,\n remoteMetadataAccessStateHash: created.accessManifestHash,\n remoteMetadataDocumentId: created.metadataDocumentId,\n supersededMovePreviousParentId: created.parentId,\n },\n expectedStateWhenMissing: containerState,\n isCurrent: input.isCurrent,\n preserveDurableStructureWhenPending: true,\n },\n );\n } catch (error) {\n if (error instanceof ContainerCreateIntentSupersededError) {\n return \"intent-superseded\";\n }\n throw error;\n }\n if (!input.isCurrent() || persistenceResult.status === \"stale-generation\") {\n return \"abandoned\";\n }\n if (persistenceResult.status !== \"persisted\") return persistenceResult.status;\n if (persistenceResult.createIntentSettled !== true) {\n throw new IncompleteContainerCreateSettlementError(\n \"Container create persistence must settle the intent atomically\",\n );\n }\n const { record: nextRecord } = persistenceResult;\n if (!input.isCurrent()) return \"abandoned\";\n const currentContainerState = state.containersById.get(intent.containerId);\n if (!currentContainerState) return \"missing\";\n if (currentContainerState !== containerState) return \"identity-superseded\";\n\n installDetachedContainerMetadataState(containerState, persistenceCandidate, {\n candidateRecord: nextRecord,\n preserveConcurrentMetadataEdit: true,\n });\n containerState.container = {\n ...containerState.container,\n metadataDocumentId: created.metadataDocumentId,\n systemSlot: created.systemSlot,\n organizationId: created.organizationId,\n parentId: persistenceCandidate.container.parentId,\n serverCreatedAt: created.createdAt,\n serverUpdatedAt: created.updatedAt,\n createdAt: created.createdAt,\n updatedAt: created.updatedAt,\n };\n return \"persisted\";\n}\n\nasync function discardOrphanedRemoteContainer(input: {\n created: CreatedRemoteContainerState;\n isCurrent: () => boolean;\n state: ContainerCreateIntentSyncState;\n}): Promise<void> {\n if (!input.isCurrent()) {\n return;\n }\n const discardFailure = await deleteRemoteContainer({\n containerId: input.created.containerId,\n organizationId: input.created.organizationId,\n runtime: input.state.runtime,\n }).then(\n (deleted) => (deleted ? null : \"the server rejected the delete\"),\n (error: unknown) => errorMessage(error),\n );\n if (input.isCurrent() && discardFailure !== null) {\n input.state.runtime.util.log(\n `Container contents: failed to discard orphaned remote container ${input.created.containerId} after local delete: ${discardFailure}`,\n );\n }\n}\n\nasync function settleRemoteContainerCreate(input: {\n containerState: ContainerState;\n created: Awaited<ReturnType<typeof createRemoteContainer>>;\n syncInput: ContainerCreateIntentSyncInput;\n}): Promise<CreateIntentSyncResult> {\n const { containerState, created, syncInput } = input;\n const { host, intent, state } = syncInput;\n if (created === CONTAINER_ALREADY_COMMITTED) {\n // A lost create response leaves the intent pending until hydration installs\n // the committed remote metadata state.\n state.runtime.util.log(\n `Container contents: deferred create intent for ${intent.containerId}; container already committed remotely, awaiting hydration.`,\n );\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"blocked\";\n }\n if (!created) {\n await state.persistence.recordCreateIntentRevisionError(\n state.runtime.infra.execSql,\n {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n message: \"Remote container create was rejected or unavailable\",\n stillCurrent: syncInput.isCurrent,\n },\n );\n return currentCreateResult(syncInput.isCurrent, \"failed\");\n }\n if (!state.containersById.has(intent.containerId)) {\n // A same-generation local delete wins; discard the remote orphan instead\n // of resurrecting the deleted local container.\n await discardOrphanedRemoteContainer({\n created,\n isCurrent: syncInput.isCurrent,\n state,\n });\n return currentCreateResult(syncInput.isCurrent, \"failed\");\n }\n\n const persistenceStatus = await persistCreatedRemoteContainerStateFromIntent({\n containerState,\n created,\n host,\n isCurrent: syncInput.isCurrent,\n intent,\n state,\n });\n if (persistenceStatus === \"abandoned\") {\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"abandoned\";\n }\n if (persistenceStatus === \"missing\") {\n await discardOrphanedRemoteContainer({\n created,\n isCurrent: syncInput.isCurrent,\n state,\n });\n return currentCreateResult(syncInput.isCurrent, \"failed\");\n }\n if (persistenceStatus === \"identity-superseded\") {\n state.runtime.util.log(\n `Container contents: deferred create intent for ${intent.containerId}; another writer persisted its remote identity.`,\n );\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"blocked\";\n }\n if (persistenceStatus === \"intent-superseded\") {\n state.runtime.util.log(\n `Container contents: deferred create intent for ${intent.containerId}; a newer local intent superseded this pass.`,\n );\n return \"blocked\";\n }\n state.runtime.util.log(\n `Container contents: synced local container create ${containerState.container.id}`,\n );\n return \"created\";\n}\n\nasync function createPendingRemoteContainer(input: {\n containerState: ContainerState;\n parentState: ContainerState;\n syncInput: ContainerCreateIntentSyncInput;\n}): Promise<CreateIntentSyncResult> {\n const { containerState, parentState, syncInput } = input;\n const { intent, state } = syncInput;\n let created: Awaited<ReturnType<typeof createRemoteContainer>>;\n try {\n created = await createRemoteContainer({\n systemSlot: containerState.container.systemSlot,\n containerId: containerState.container.id,\n parentContainerId: parentState.container.id,\n resolveProjectionUserKey: state.resolveProjectionUserKey,\n runtime: state.runtime,\n stillCurrent: syncInput.isCurrent,\n });\n } catch (error) {\n if (error instanceof ContainerPathTooDeepError)\n return recordRefusedTooDeepCreate(syncInput);\n return recordContainerCreateFailure({\n error,\n isCurrent: syncInput.isCurrent,\n intent,\n organizationId: parentState.container.organizationId,\n state,\n });\n }\n if (!syncInput.isCurrent()) {\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"abandoned\";\n }\n try {\n return await settleRemoteContainerCreate({\n containerState,\n created,\n syncInput,\n });\n } catch (error) {\n if (!(error instanceof IncompleteContainerCreateSettlementError))\n throw error;\n return recordContainerCreateFailure({\n error,\n isCurrent: syncInput.isCurrent,\n intent,\n organizationId: parentState.container.organizationId,\n state,\n });\n }\n}\n\nasync function trySyncPendingContainerContentsContainerCreateIntent(\n input: ContainerCreateIntentSyncInput,\n): Promise<CreateIntentSyncResult> {\n const { intent, state } = input;\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n const containerState = state.containersById.get(intent.containerId);\n const parentState = state.containersById.get(intent.parentContainerId);\n\n if (!containerState || !parentState) {\n const execSql = state.runtime.infra.execSql;\n await state.persistence.recordCreateIntentRevisionError(execSql, {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n message: \"Container create intent references a missing local container\",\n stillCurrent: input.isCurrent,\n });\n return currentCreateResult(input.isCurrent, \"failed\");\n }\n\n if (typeof state.persistence.markCreateIntentRevisionSynced !== \"function\") {\n await state.persistence.recordCreateIntentRevisionError(\n state.runtime.infra.execSql,\n {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n message: \"Container create replay requires revision-CAS persistence\",\n stillCurrent: input.isCurrent,\n },\n );\n return currentCreateResult(input.isCurrent, \"failed\");\n }\n\n if (input.isRemoteSyncBlocked(parentState.container.organizationId)) {\n return \"blocked\";\n }\n\n if (hasRemoteContainerMetadataState(containerState)) {\n return syncListedContainerCreate({\n containerState,\n parentState,\n syncInput: input,\n });\n }\n\n // A parent whose own create has not settled may carry a listed identity\n // adoption has not verified, or has refused; nothing is created under it.\n if (\n !hasRemoteContainerMetadataState(parentState) ||\n input.isCreatePending(parentState.container.id)\n ) {\n return \"blocked\";\n }\n\n if (await deferTooDeepCreate(input)) {\n return currentCreateResult(input.isCurrent, \"blocked\");\n }\n\n return createPendingRemoteContainer({\n containerState,\n parentState,\n syncInput: input,\n });\n}\n\nexport async function syncPendingContainerCreateIntents(input: {\n host: ContainerCreateIntentSyncHost;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerCreateIntentSyncState;\n}): Promise<number> {\n if (!input.isCurrent()) {\n return 0;\n }\n const { host } = input;\n const state = { ...input.state };\n const execSql = state.runtime.infra.execSql;\n const pendingIntents =\n await state.persistence.listPendingCreateIntents(execSql);\n if (!input.isCurrent()) {\n return 0;\n }\n const remainingContainerIds = new Set(\n pendingIntents.map((intent) => intent.containerId),\n );\n // Only a create that settles in this pass leaves the pending set; a failed\n // or parked one stays pending even though this pass stops retrying it.\n const unsettledContainerIds = new Set(remainingContainerIds);\n let createdCount = 0;\n let progressed = true;\n\n while (progressed && input.isCurrent()) {\n progressed = false;\n\n for (const intent of pendingIntents) {\n if (!remainingContainerIds.has(intent.containerId)) {\n continue;\n }\n\n const result = await trySyncPendingContainerContentsContainerCreateIntent(\n {\n host,\n isCreatePending: (containerId) =>\n unsettledContainerIds.has(containerId),\n isCurrent: input.isCurrent,\n isRemoteSyncBlocked: input.isRemoteSyncBlocked,\n intent,\n requestRemoteReconciliation: input.requestRemoteReconciliation,\n state,\n },\n );\n if (result === \"abandoned\") {\n return createdCount;\n }\n\n if (result === \"blocked\") {\n continue;\n }\n\n remainingContainerIds.delete(intent.containerId);\n progressed = result === \"created\" || progressed;\n if (result === \"created\") {\n createdCount += 1;\n unsettledContainerIds.delete(intent.containerId);\n }\n }\n }\n\n return createdCount;\n}\n"]}
@@ -2,7 +2,7 @@ import { ContainerPathTooDeepError } from "../../../data/containers/shared/conta
2
2
  import { reportAndRethrowKeyingVerificationError } from "../../../data/keyingProjectionVerification/error.js";
3
3
  import { errorMessage } from "../../../data/shared/errorMessage.js";
4
4
  import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
5
- import { createDetachedContainerMetadataState, installDetachedContainerMetadataState, } from "../metadataStateIsolation.js";
5
+ import { createDetachedContainerMetadataState, installDetachedContainerMetadataState, } from "../metadata/metadataStateIsolation.js";
6
6
  import { hasRemoteContainerMetadataState } from "../remoteHydration/reconciliation.js";
7
7
  import { moveRemoteContainer } from "./remote.js";
8
8
  function currentMoveResult(isCurrent, result) {
@@ -1 +1 @@
1
- {"version":3,"file":"moveIntentSync.js","sourceRoot":"","sources":["moveIntentSync.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContainerPathTooDeepError } from \"../../../data/containers/shared/containerPathLimits\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"../metadataStateIsolation\";\nimport type { ContainerState, RemoteContainer } from \"../remoteHydration\";\nimport { hasRemoteContainerMetadataState } from \"../remoteHydration/reconciliation\";\nimport { moveRemoteContainer } from \"./remote\";\nimport type {\n ContainerMoveIntentSyncHost,\n ContainerMoveIntentSyncInput,\n ContainerMoveIntentSyncState,\n} from \"./types\";\n\ntype MoveIntentSyncResult = \"abandoned\" | \"blocked\" | \"failed\" | \"moved\";\n\nfunction currentMoveResult<\n Result extends Exclude<MoveIntentSyncResult, \"abandoned\">,\n>(isCurrent: () => boolean, result: Result): \"abandoned\" | Result {\n return isCurrent() ? result : \"abandoned\";\n}\n\nasync function recordPendingMoveIntentError(input: {\n blocked?: boolean | undefined;\n containerId: string;\n expectedIntentId: string;\n expectedUpdatedAt: string;\n isCurrent: () => boolean;\n message: string;\n state: ContainerMoveIntentSyncState;\n}): Promise<boolean> {\n if (!input.isCurrent()) {\n return false;\n }\n const execSql = input.state.runtime.infra.execSql;\n await input.state.persistence.recordMoveIntentError(execSql, {\n blocked: input.blocked,\n containerId: input.containerId,\n expectedIntentId: input.expectedIntentId,\n expectedUpdatedAt: input.expectedUpdatedAt,\n message: input.message,\n stillCurrent: input.isCurrent,\n });\n return input.isCurrent();\n}\n\nasync function resolveMoveIntentLocalUpdatedAt(input: {\n containerId: string;\n isCurrent: () => boolean;\n remoteUpdatedAt: string;\n state: ContainerMoveIntentSyncState;\n}): Promise<string | null> {\n if (!input.isCurrent()) {\n return null;\n }\n const previousLocalUpdatedAt =\n input.state.containersById.get(input.containerId)?.container\n .localUpdatedAt ?? null;\n if (\n !previousLocalUpdatedAt ||\n previousLocalUpdatedAt.localeCompare(input.remoteUpdatedAt) <= 0\n ) {\n return input.remoteUpdatedAt;\n }\n\n const execSql = input.state.runtime.infra.execSql;\n const containersWithPendingMetadataUpdates =\n await input.state.persistence.listContainerIdsWithPendingUpdates(execSql, [\n input.containerId,\n ]);\n if (!input.isCurrent()) {\n return null;\n }\n\n return containersWithPendingMetadataUpdates.includes(input.containerId)\n ? previousLocalUpdatedAt\n : input.remoteUpdatedAt;\n}\n\nexport async function persistAcceptedMoveIntent(input: {\n host: ContainerMoveIntentSyncHost;\n isCurrent: () => boolean;\n intent: ContainerMoveIntentSyncInput[\"intent\"];\n moved: RemoteContainer;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerMoveIntentSyncState;\n}): Promise<boolean> {\n const { host, intent, moved, state } = input;\n const abandon = () => {\n input.requestRemoteReconciliation(moved.parentId);\n return false;\n };\n if (!input.isCurrent()) return abandon();\n const containerState = state.containersById.get(intent.containerId);\n if (!containerState) {\n return false;\n }\n\n await createRuntimePrincipalPolicyWarmer(state.runtime)({\n organizationId: moved.organizationId,\n references: moved.metadataReferencedPrincipals,\n stillCurrent: input.isCurrent,\n });\n if (!input.isCurrent()) {\n return abandon();\n }\n const localUpdatedAt = await resolveMoveIntentLocalUpdatedAt({\n containerId: intent.containerId,\n isCurrent: input.isCurrent,\n remoteUpdatedAt: moved.updatedAt,\n state,\n });\n if (!input.isCurrent() || localUpdatedAt === null) {\n return abandon();\n }\n const persistenceCandidate =\n await createDetachedContainerMetadataState(containerState);\n if (!input.isCurrent()) {\n return abandon();\n }\n persistenceCandidate.container = {\n ...persistenceCandidate.container,\n createdAt: moved.createdAt,\n serverCreatedAt: moved.createdAt,\n serverUpdatedAt: moved.updatedAt,\n updatedAt: moved.updatedAt,\n };\n const persistenceResult = await host.persistContainerState(\n persistenceCandidate,\n {\n accessEpoch: moved.metadataAccessEpoch,\n accessStateHash: moved.metadataAccessStateHash,\n documentId: moved.metadataDocumentId,\n metadataDocumentId: moved.metadataDocumentId,\n organizationId: moved.organizationId,\n parentId: moved.parentId,\n systemSlot: moved.systemSlot ?? null,\n },\n false,\n {\n localUpdatedAt,\n serverTimestamps: {\n createdAt: moved.createdAt,\n updatedAt: moved.updatedAt,\n },\n },\n {\n expectedStateWhenMissing: containerState,\n isCurrent: input.isCurrent,\n moveIntentSettlement: {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n },\n },\n );\n if (!input.isCurrent() || persistenceResult.status !== \"persisted\") {\n return abandon();\n }\n if (persistenceResult.moveIntentSettled !== true) {\n throw new Error(\n \"Container move persistence must settle the intent atomically\",\n );\n }\n if (!input.isCurrent()) return abandon();\n const { record: nextRecord } = persistenceResult;\n installDetachedContainerMetadataState(containerState, persistenceCandidate, {\n candidateRecord: nextRecord,\n preserveConcurrentMetadataEdit: true,\n });\n containerState.container = {\n ...containerState.container,\n metadataDocumentId: moved.metadataDocumentId,\n organizationId: moved.organizationId,\n parentId: moved.parentId,\n };\n return true;\n}\n\n/**\n * A move refused for path length never succeeds; the queue-time check saw only\n * the descendants this device holds. Drop the queued move and restore the\n * previous parent together: the server row never changed, so no listing would\n * ever put the folder back.\n */\nasync function abandonTooDeepMove(\n syncInput: ContainerMoveIntentSyncInput,\n): Promise<MoveIntentSyncResult> {\n const { host, intent, state } = syncInput;\n const previousParentId = intent.previousParentContainerId;\n if (previousParentId === null) {\n throw new Error(\"A queued container move must name its previous parent\");\n }\n const abandoned = await state.persistence.abandonMoveIntentRevision(\n state.runtime.infra.execSql,\n {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n previousParentContainerId: previousParentId,\n stillCurrent: syncInput.isCurrent,\n },\n );\n if (!syncInput.isCurrent()) return \"abandoned\";\n // A newer local move superseded this revision; it replays on its own.\n if (!abandoned) return \"failed\";\n const containerState = state.containersById.get(intent.containerId);\n if (containerState) {\n containerState.container = {\n ...containerState.container,\n parentId: previousParentId,\n };\n }\n host.updateSnapshot();\n state.runtime.util.log(\n `Container contents: abandoned queued move of ${intent.containerId}; its path would exceed the maximum depth`,\n );\n return \"failed\";\n}\n\nasync function movePendingRemoteContainer(input: {\n parentState: ContainerState;\n syncInput: ContainerMoveIntentSyncInput;\n}): Promise<MoveIntentSyncResult> {\n const { parentState, syncInput } = input;\n const { host, intent, state } = syncInput;\n let remoteMoveApplied = false;\n let remoteParentId: string | null = intent.parentContainerId;\n const abandonAppliedMove = () => {\n if (remoteMoveApplied) {\n syncInput.requestRemoteReconciliation(remoteParentId);\n }\n return \"abandoned\" as const;\n };\n try {\n const moved = await moveRemoteContainer({\n containerId: intent.containerId,\n parentContainerId: intent.parentContainerId,\n resolveProjectionUserKey: state.resolveProjectionUserKey,\n runtime: state.runtime,\n stillCurrent: syncInput.isCurrent,\n });\n if (!moved) {\n if (!syncInput.isCurrent()) {\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"abandoned\";\n }\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: syncInput.isCurrent,\n message: \"Remote container move was rejected or unavailable\",\n state,\n });\n return currentMoveResult(syncInput.isCurrent, \"failed\");\n }\n remoteMoveApplied = true;\n remoteParentId = moved.parentId;\n if (!syncInput.isCurrent()) return abandonAppliedMove();\n\n const persisted = await persistAcceptedMoveIntent({\n host,\n isCurrent: syncInput.isCurrent,\n intent,\n moved,\n requestRemoteReconciliation: syncInput.requestRemoteReconciliation,\n state,\n });\n if (!persisted) {\n return currentMoveResult(syncInput.isCurrent, \"failed\");\n }\n state.runtime.util.log(\n `Container contents: synced queued container move ${intent.containerId}`,\n );\n return \"moved\";\n } catch (error: unknown) {\n if (!syncInput.isCurrent()) {\n return abandonAppliedMove();\n }\n if (error instanceof ContainerPathTooDeepError)\n return abandonTooDeepMove(syncInput);\n await reportAndRethrowKeyingVerificationError(\n error,\n state.runtime.util.reportSecurityIncident,\n {\n objectId: intent.containerId,\n objectKind: \"container\",\n operation: \"container.move.replay\",\n organizationId: parentState.container.organizationId,\n },\n );\n if (!syncInput.isCurrent()) {\n return abandonAppliedMove();\n }\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: syncInput.isCurrent,\n message: `Failed to sync container move: ${errorMessage(error)}`,\n state,\n });\n return currentMoveResult(syncInput.isCurrent, \"failed\");\n }\n}\n\nasync function trySyncPendingContainerMoveIntent(\n input: ContainerMoveIntentSyncInput,\n): Promise<MoveIntentSyncResult> {\n const { intent, state } = input;\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n const containerState = state.containersById.get(intent.containerId);\n const parentState = state.containersById.get(intent.parentContainerId);\n\n if (!containerState) {\n await recordPendingMoveIntentError({\n blocked: true,\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Container move intent references a missing local container\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"failed\");\n }\n if (!parentState) {\n await recordPendingMoveIntentError({\n blocked: true,\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message:\n \"Container move intent references a missing destination parent container\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"failed\");\n }\n if (input.isRemoteSyncBlocked(containerState.container.organizationId)) {\n return \"blocked\";\n }\n if (\n !hasRemoteContainerMetadataState(containerState) ||\n input.isCreatePending(intent.containerId)\n ) {\n // Source not synced yet is TRANSIENT, exactly like the destination case\n // below: the source's own create intent syncs first (createIntentSync runs\n // before moveIntentSync in a pass), but if that create fails on this pass\n // the source still lacks remote metadata here. Keep the intent 'pending'\n // (not 'blocked') so the queue reports a retryable failure rather than a\n // missing-dependency block; either way listUnsyncedMoveIntents replays it\n // once the create lands.\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Container move source is not synced yet\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"blocked\");\n }\n if (\n !hasRemoteContainerMetadataState(parentState) ||\n input.isCreatePending(intent.parentContainerId)\n ) {\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Container move destination parent is not synced yet\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"blocked\");\n }\n\n return movePendingRemoteContainer({ parentState, syncInput: input });\n}\n\nexport async function syncPendingContainerMoveIntents(input: {\n host: ContainerMoveIntentSyncHost;\n isCreatePending: (containerId: string) => boolean;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerMoveIntentSyncState;\n}): Promise<number> {\n if (!input.isCurrent()) {\n return 0;\n }\n const { host } = input;\n const state = { ...input.state };\n const execSql = state.runtime.infra.execSql;\n const pendingIntents =\n await state.persistence.listUnsyncedMoveIntents(execSql);\n if (!input.isCurrent()) {\n return 0;\n }\n let movedCount = 0;\n\n for (const intent of pendingIntents) {\n if (!input.isCurrent()) {\n return movedCount;\n }\n const result = await trySyncPendingContainerMoveIntent({\n host,\n isCurrent: input.isCurrent,\n isCreatePending: input.isCreatePending,\n isRemoteSyncBlocked: input.isRemoteSyncBlocked,\n intent,\n requestRemoteReconciliation: input.requestRemoteReconciliation,\n state,\n });\n if (result === \"abandoned\") {\n return movedCount;\n }\n\n if (result === \"moved\") {\n movedCount += 1;\n }\n }\n\n return movedCount;\n}\n"]}
1
+ {"version":3,"file":"moveIntentSync.js","sourceRoot":"","sources":["moveIntentSync.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContainerPathTooDeepError } from \"../../../data/containers/shared/containerPathLimits\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"../metadata/metadataStateIsolation\";\nimport type { ContainerState, RemoteContainer } from \"../remoteHydration\";\nimport { hasRemoteContainerMetadataState } from \"../remoteHydration/reconciliation\";\nimport { moveRemoteContainer } from \"./remote\";\nimport type {\n ContainerMoveIntentSyncHost,\n ContainerMoveIntentSyncInput,\n ContainerMoveIntentSyncState,\n} from \"./types\";\n\ntype MoveIntentSyncResult = \"abandoned\" | \"blocked\" | \"failed\" | \"moved\";\n\nfunction currentMoveResult<\n Result extends Exclude<MoveIntentSyncResult, \"abandoned\">,\n>(isCurrent: () => boolean, result: Result): \"abandoned\" | Result {\n return isCurrent() ? result : \"abandoned\";\n}\n\nasync function recordPendingMoveIntentError(input: {\n blocked?: boolean | undefined;\n containerId: string;\n expectedIntentId: string;\n expectedUpdatedAt: string;\n isCurrent: () => boolean;\n message: string;\n state: ContainerMoveIntentSyncState;\n}): Promise<boolean> {\n if (!input.isCurrent()) {\n return false;\n }\n const execSql = input.state.runtime.infra.execSql;\n await input.state.persistence.recordMoveIntentError(execSql, {\n blocked: input.blocked,\n containerId: input.containerId,\n expectedIntentId: input.expectedIntentId,\n expectedUpdatedAt: input.expectedUpdatedAt,\n message: input.message,\n stillCurrent: input.isCurrent,\n });\n return input.isCurrent();\n}\n\nasync function resolveMoveIntentLocalUpdatedAt(input: {\n containerId: string;\n isCurrent: () => boolean;\n remoteUpdatedAt: string;\n state: ContainerMoveIntentSyncState;\n}): Promise<string | null> {\n if (!input.isCurrent()) {\n return null;\n }\n const previousLocalUpdatedAt =\n input.state.containersById.get(input.containerId)?.container\n .localUpdatedAt ?? null;\n if (\n !previousLocalUpdatedAt ||\n previousLocalUpdatedAt.localeCompare(input.remoteUpdatedAt) <= 0\n ) {\n return input.remoteUpdatedAt;\n }\n\n const execSql = input.state.runtime.infra.execSql;\n const containersWithPendingMetadataUpdates =\n await input.state.persistence.listContainerIdsWithPendingUpdates(execSql, [\n input.containerId,\n ]);\n if (!input.isCurrent()) {\n return null;\n }\n\n return containersWithPendingMetadataUpdates.includes(input.containerId)\n ? previousLocalUpdatedAt\n : input.remoteUpdatedAt;\n}\n\nexport async function persistAcceptedMoveIntent(input: {\n host: ContainerMoveIntentSyncHost;\n isCurrent: () => boolean;\n intent: ContainerMoveIntentSyncInput[\"intent\"];\n moved: RemoteContainer;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerMoveIntentSyncState;\n}): Promise<boolean> {\n const { host, intent, moved, state } = input;\n const abandon = () => {\n input.requestRemoteReconciliation(moved.parentId);\n return false;\n };\n if (!input.isCurrent()) return abandon();\n const containerState = state.containersById.get(intent.containerId);\n if (!containerState) {\n return false;\n }\n\n await createRuntimePrincipalPolicyWarmer(state.runtime)({\n organizationId: moved.organizationId,\n references: moved.metadataReferencedPrincipals,\n stillCurrent: input.isCurrent,\n });\n if (!input.isCurrent()) {\n return abandon();\n }\n const localUpdatedAt = await resolveMoveIntentLocalUpdatedAt({\n containerId: intent.containerId,\n isCurrent: input.isCurrent,\n remoteUpdatedAt: moved.updatedAt,\n state,\n });\n if (!input.isCurrent() || localUpdatedAt === null) {\n return abandon();\n }\n const persistenceCandidate =\n await createDetachedContainerMetadataState(containerState);\n if (!input.isCurrent()) {\n return abandon();\n }\n persistenceCandidate.container = {\n ...persistenceCandidate.container,\n createdAt: moved.createdAt,\n serverCreatedAt: moved.createdAt,\n serverUpdatedAt: moved.updatedAt,\n updatedAt: moved.updatedAt,\n };\n const persistenceResult = await host.persistContainerState(\n persistenceCandidate,\n {\n accessEpoch: moved.metadataAccessEpoch,\n accessStateHash: moved.metadataAccessStateHash,\n documentId: moved.metadataDocumentId,\n metadataDocumentId: moved.metadataDocumentId,\n organizationId: moved.organizationId,\n parentId: moved.parentId,\n systemSlot: moved.systemSlot ?? null,\n },\n false,\n {\n localUpdatedAt,\n serverTimestamps: {\n createdAt: moved.createdAt,\n updatedAt: moved.updatedAt,\n },\n },\n {\n expectedStateWhenMissing: containerState,\n isCurrent: input.isCurrent,\n moveIntentSettlement: {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n },\n },\n );\n if (!input.isCurrent() || persistenceResult.status !== \"persisted\") {\n return abandon();\n }\n if (persistenceResult.moveIntentSettled !== true) {\n throw new Error(\n \"Container move persistence must settle the intent atomically\",\n );\n }\n if (!input.isCurrent()) return abandon();\n const { record: nextRecord } = persistenceResult;\n installDetachedContainerMetadataState(containerState, persistenceCandidate, {\n candidateRecord: nextRecord,\n preserveConcurrentMetadataEdit: true,\n });\n containerState.container = {\n ...containerState.container,\n metadataDocumentId: moved.metadataDocumentId,\n organizationId: moved.organizationId,\n parentId: moved.parentId,\n };\n return true;\n}\n\n/**\n * A move refused for path length never succeeds; the queue-time check saw only\n * the descendants this device holds. Drop the queued move and restore the\n * previous parent together: the server row never changed, so no listing would\n * ever put the folder back.\n */\nasync function abandonTooDeepMove(\n syncInput: ContainerMoveIntentSyncInput,\n): Promise<MoveIntentSyncResult> {\n const { host, intent, state } = syncInput;\n const previousParentId = intent.previousParentContainerId;\n if (previousParentId === null) {\n throw new Error(\"A queued container move must name its previous parent\");\n }\n const abandoned = await state.persistence.abandonMoveIntentRevision(\n state.runtime.infra.execSql,\n {\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n previousParentContainerId: previousParentId,\n stillCurrent: syncInput.isCurrent,\n },\n );\n if (!syncInput.isCurrent()) return \"abandoned\";\n // A newer local move superseded this revision; it replays on its own.\n if (!abandoned) return \"failed\";\n const containerState = state.containersById.get(intent.containerId);\n if (containerState) {\n containerState.container = {\n ...containerState.container,\n parentId: previousParentId,\n };\n }\n host.updateSnapshot();\n state.runtime.util.log(\n `Container contents: abandoned queued move of ${intent.containerId}; its path would exceed the maximum depth`,\n );\n return \"failed\";\n}\n\nasync function movePendingRemoteContainer(input: {\n parentState: ContainerState;\n syncInput: ContainerMoveIntentSyncInput;\n}): Promise<MoveIntentSyncResult> {\n const { parentState, syncInput } = input;\n const { host, intent, state } = syncInput;\n let remoteMoveApplied = false;\n let remoteParentId: string | null = intent.parentContainerId;\n const abandonAppliedMove = () => {\n if (remoteMoveApplied) {\n syncInput.requestRemoteReconciliation(remoteParentId);\n }\n return \"abandoned\" as const;\n };\n try {\n const moved = await moveRemoteContainer({\n containerId: intent.containerId,\n parentContainerId: intent.parentContainerId,\n resolveProjectionUserKey: state.resolveProjectionUserKey,\n runtime: state.runtime,\n stillCurrent: syncInput.isCurrent,\n });\n if (!moved) {\n if (!syncInput.isCurrent()) {\n syncInput.requestRemoteReconciliation(intent.parentContainerId);\n return \"abandoned\";\n }\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: syncInput.isCurrent,\n message: \"Remote container move was rejected or unavailable\",\n state,\n });\n return currentMoveResult(syncInput.isCurrent, \"failed\");\n }\n remoteMoveApplied = true;\n remoteParentId = moved.parentId;\n if (!syncInput.isCurrent()) return abandonAppliedMove();\n\n const persisted = await persistAcceptedMoveIntent({\n host,\n isCurrent: syncInput.isCurrent,\n intent,\n moved,\n requestRemoteReconciliation: syncInput.requestRemoteReconciliation,\n state,\n });\n if (!persisted) {\n return currentMoveResult(syncInput.isCurrent, \"failed\");\n }\n state.runtime.util.log(\n `Container contents: synced queued container move ${intent.containerId}`,\n );\n return \"moved\";\n } catch (error: unknown) {\n if (!syncInput.isCurrent()) {\n return abandonAppliedMove();\n }\n if (error instanceof ContainerPathTooDeepError)\n return abandonTooDeepMove(syncInput);\n await reportAndRethrowKeyingVerificationError(\n error,\n state.runtime.util.reportSecurityIncident,\n {\n objectId: intent.containerId,\n objectKind: \"container\",\n operation: \"container.move.replay\",\n organizationId: parentState.container.organizationId,\n },\n );\n if (!syncInput.isCurrent()) {\n return abandonAppliedMove();\n }\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: syncInput.isCurrent,\n message: `Failed to sync container move: ${errorMessage(error)}`,\n state,\n });\n return currentMoveResult(syncInput.isCurrent, \"failed\");\n }\n}\n\nasync function trySyncPendingContainerMoveIntent(\n input: ContainerMoveIntentSyncInput,\n): Promise<MoveIntentSyncResult> {\n const { intent, state } = input;\n if (!input.isCurrent()) {\n return \"abandoned\";\n }\n const containerState = state.containersById.get(intent.containerId);\n const parentState = state.containersById.get(intent.parentContainerId);\n\n if (!containerState) {\n await recordPendingMoveIntentError({\n blocked: true,\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Container move intent references a missing local container\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"failed\");\n }\n if (!parentState) {\n await recordPendingMoveIntentError({\n blocked: true,\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message:\n \"Container move intent references a missing destination parent container\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"failed\");\n }\n if (input.isRemoteSyncBlocked(containerState.container.organizationId)) {\n return \"blocked\";\n }\n if (\n !hasRemoteContainerMetadataState(containerState) ||\n input.isCreatePending(intent.containerId)\n ) {\n // Source not synced yet is TRANSIENT, exactly like the destination case\n // below: the source's own create intent syncs first (createIntentSync runs\n // before moveIntentSync in a pass), but if that create fails on this pass\n // the source still lacks remote metadata here. Keep the intent 'pending'\n // (not 'blocked') so the queue reports a retryable failure rather than a\n // missing-dependency block; either way listUnsyncedMoveIntents replays it\n // once the create lands.\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Container move source is not synced yet\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"blocked\");\n }\n if (\n !hasRemoteContainerMetadataState(parentState) ||\n input.isCreatePending(intent.parentContainerId)\n ) {\n await recordPendingMoveIntentError({\n containerId: intent.containerId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Container move destination parent is not synced yet\",\n state,\n });\n return currentMoveResult(input.isCurrent, \"blocked\");\n }\n\n return movePendingRemoteContainer({ parentState, syncInput: input });\n}\n\nexport async function syncPendingContainerMoveIntents(input: {\n host: ContainerMoveIntentSyncHost;\n isCreatePending: (containerId: string) => boolean;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerMoveIntentSyncState;\n}): Promise<number> {\n if (!input.isCurrent()) {\n return 0;\n }\n const { host } = input;\n const state = { ...input.state };\n const execSql = state.runtime.infra.execSql;\n const pendingIntents =\n await state.persistence.listUnsyncedMoveIntents(execSql);\n if (!input.isCurrent()) {\n return 0;\n }\n let movedCount = 0;\n\n for (const intent of pendingIntents) {\n if (!input.isCurrent()) {\n return movedCount;\n }\n const result = await trySyncPendingContainerMoveIntent({\n host,\n isCurrent: input.isCurrent,\n isCreatePending: input.isCreatePending,\n isRemoteSyncBlocked: input.isRemoteSyncBlocked,\n intent,\n requestRemoteReconciliation: input.requestRemoteReconciliation,\n state,\n });\n if (result === \"abandoned\") {\n return movedCount;\n }\n\n if (result === \"moved\") {\n movedCount += 1;\n }\n }\n\n return movedCount;\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { DEFAULT_DOCUMENT_KIND } from "../../../data/documents/documentConstants.js";
2
2
  import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
3
3
  import { listDocumentsByContainerIdsOrDocumentIds } from "../../../data/persistence/documents/documentsPersistence.js";
4
- import { unlinkRemoteContainerDocument } from "../documentLinks.js";
5
- import { purgeLocalContainerDocument, purgeRemoteContainerDocument, } from "../documentPurge.js";
4
+ import { unlinkRemoteContainerDocument } from "../documentLinks/index.js";
5
+ import { purgeLocalContainerDocument, purgeRemoteContainerDocument, } from "../tombstones/documentPurge.js";
6
6
  import { collectSubtreeLeafFirst, snapshotContainerStates, } from "./purgeTreeCollection.js";
7
7
  import { deleteSubtreeContainers } from "./purgeTreeContainerDeletion.js";
8
8
  import { createSubtreePurgeScope } from "./purgeTreeScope.js";
@@ -1 +1 @@
1
- {"version":3,"file":"purgeTree.js","sourceRoot":"","sources":["purgeTree.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { listDocumentsByContainerIdsOrDocumentIds } from \"../../../data/persistence/documents/documentsPersistence\";\nimport type { SubtreePurgeRoot } from \"../../documents/subtreePurgeScope\";\nimport type { ContainerContentsPersistence } from \"../containerPersistence\";\nimport { unlinkRemoteContainerDocument } from \"../documentLinks\";\nimport {\n purgeLocalContainerDocument,\n purgeRemoteContainerDocument,\n} from \"../documentPurge\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\nimport type { PurgeProgress } from \"./purgeProgress\";\nimport {\n collectSubtreeLeafFirst,\n snapshotContainerStates,\n} from \"./purgeTreeCollection\";\nimport { deleteSubtreeContainers } from \"./purgeTreeContainerDeletion\";\nimport { createSubtreePurgeScope } from \"./purgeTreeScope\";\n\nexport { collectSubtreeLeafFirst } from \"./purgeTreeCollection\";\n\n// The store runtime satisfies the per-document purge/unlink workflows, so the\n// cascade reuses it verbatim.\ntype PurgeContainerTreeRuntime = ContainerContentsWorkflowRuntime;\n\ninterface PurgeContainerTreeInput {\n readonly containersById: ReadonlyMap<string, ContainerState>;\n readonly documentOperations?: SubtreeDocumentOperations | undefined;\n // When true, tear down everything UNDER the root (its documents plus every\n // descendant container) but never delete the root container itself. This is\n // how \"Empty Trash\" reuses the same engine: the Trash bin is a protected system\n // container that must survive while its whole contents are destroyed.\n readonly keepRootContainer?: boolean;\n readonly onProgress?: ((progress: PurgeProgress) => void) | undefined;\n readonly persistence: ContainerContentsPersistence;\n readonly prepareDocumentRotationSnapshot: (\n document: DocumentSummary,\n ) => Promise<Uint8Array | null>;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly rootContainerId: string;\n readonly runtime: PurgeContainerTreeRuntime;\n /** Stops a stale store generation between complete destructive units. */\n readonly stillCurrent?: (() => boolean) | undefined;\n // Checked at each unit boundary (between whole documents / whole containers),\n // never mid-remote-call, so a cancelled run stops on a consistent prefix.\n readonly signal?: AbortSignal | undefined;\n}\n\ninterface PurgeContainerTreeResult {\n readonly aborted: boolean;\n readonly completedCount: number;\n readonly failedCount: number;\n readonly purgedContainerIds: readonly string[];\n readonly remoteDeletedContainerIds: readonly string[];\n readonly totalCount: number;\n}\n\ninterface SubtreeDocumentPlan {\n // Synced documents whose every link falls inside the subtree: reduce them to\n // one retained link, as required by the purge endpoint, then destroy them.\n readonly purge: readonly {\n document: DocumentSummary;\n unlinkContainerIds: readonly string[];\n }[];\n // Synced documents also linked outside the subtree: keep them, but unlink\n // from each in-subtree container so the containers can be deleted.\n readonly unlinkByDocument: ReadonlyMap<\n string,\n { document: DocumentSummary; containerIds: readonly string[] }\n >;\n // Never-synced documents (no remote id): destroy locally only.\n readonly purgeLocal: readonly DocumentSummary[];\n}\n\ntype SubtreeDocumentDisposition =\n | { kind: \"purge\"; unlinkContainerIds: readonly string[] }\n | { kind: \"purge-local\" }\n | { kind: \"unlink\"; containerIds: readonly string[] };\n\n// Destroy local-only documents locally. Destroy synced documents only when all\n// links are in the subtree; preserve documents with an external link. The purge\n// plan reduces owned documents to the server-required sole link first.\nexport function classifySubtreeDocument(input: {\n readonly documentId: string | null;\n readonly linkedContainerIds: readonly string[];\n readonly preferredContainerId?: string | null | undefined;\n readonly subtreeContainerIds: ReadonlySet<string>;\n}): SubtreeDocumentDisposition {\n if (!input.documentId) {\n return { kind: \"purge-local\" };\n }\n const hasExternalLink = input.linkedContainerIds.some(\n (containerId) => !input.subtreeContainerIds.has(containerId),\n );\n if (!hasExternalLink) {\n const linkedContainerIds = Array.from(\n new Set(\n input.linkedContainerIds.filter((containerId) =>\n input.subtreeContainerIds.has(containerId),\n ),\n ),\n );\n const retainedContainerId =\n input.preferredContainerId &&\n linkedContainerIds.includes(input.preferredContainerId)\n ? input.preferredContainerId\n : linkedContainerIds[0];\n return {\n kind: \"purge\",\n unlinkContainerIds: linkedContainerIds.filter(\n (containerId) => containerId !== retainedContainerId,\n ),\n };\n }\n return {\n kind: \"unlink\",\n containerIds: input.linkedContainerIds.filter((containerId) =>\n input.subtreeContainerIds.has(containerId),\n ),\n };\n}\n\nasync function planSubtreeDocuments(input: {\n readonly execSql: PurgeContainerTreeRuntime[\"infra\"][\"execSql\"];\n readonly subtreeContainerIds: ReadonlySet<string>;\n}): Promise<SubtreeDocumentPlan> {\n const documents = await listDocumentsByContainerIdsOrDocumentIds(\n input.execSql,\n {\n containerIds: [...input.subtreeContainerIds],\n documentIds: [],\n },\n );\n const remoteDocumentIds = documents.flatMap((document) =>\n document.documentId ? [document.documentId] : [],\n );\n const linkedContainerIdsByDocumentId =\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n input.execSql,\n remoteDocumentIds,\n );\n\n const purge: Array<{\n document: DocumentSummary;\n unlinkContainerIds: readonly string[];\n }> = [];\n const purgeLocal: DocumentSummary[] = [];\n const unlinkByDocument = new Map<\n string,\n { document: DocumentSummary; containerIds: readonly string[] }\n >();\n for (const document of documents) {\n const disposition = classifySubtreeDocument({\n documentId: document.documentId ?? null,\n linkedContainerIds: document.documentId\n ? (linkedContainerIdsByDocumentId.get(document.documentId) ?? [])\n : [],\n preferredContainerId: document.containerId,\n subtreeContainerIds: input.subtreeContainerIds,\n });\n if (disposition.kind === \"purge-local\") {\n purgeLocal.push(document);\n } else if (disposition.kind === \"purge\") {\n purge.push({\n document,\n unlinkContainerIds: disposition.unlinkContainerIds,\n });\n } else if (document.documentId) {\n unlinkByDocument.set(document.documentId, {\n document,\n containerIds: disposition.containerIds,\n });\n }\n }\n\n return { purge, purgeLocal, unlinkByDocument };\n}\n\nasync function unlinkSubtreeDocument(input: {\n /** Rechecks the document and this exact unlink target before dispatch. */\n readonly beforeSubmit: (targetContainerId: string) => Promise<boolean>;\n readonly expectedSubtreeRoot: SubtreePurgeRoot;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly containerIds: readonly string[];\n readonly document: DocumentSummary;\n readonly prepareDocumentRotationSnapshot: PurgeContainerTreeInput[\"prepareDocumentRotationSnapshot\"];\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly runtime: PurgeContainerTreeRuntime;\n}): Promise<boolean> {\n const documentId = input.document.documentId;\n if (!documentId) {\n return true;\n }\n let rotationSnapshot: Uint8Array | null;\n try {\n rotationSnapshot = await input.prepareDocumentRotationSnapshot(\n input.document,\n );\n } catch {\n return false;\n }\n if (!rotationSnapshot) {\n return false;\n }\n for (const containerId of input.containerIds) {\n const result = await unlinkRemoteContainerDocument({\n beforeSubmit: () => input.beforeSubmit(containerId),\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n isCurrent: input.stillCurrent,\n noteId: input.document.id,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n rotationSnapshot,\n runtime: input.runtime,\n targetContainerId: containerId,\n });\n if (result === null) {\n return false;\n }\n }\n return true;\n}\n\ninterface SubtreeDocumentOperations {\n readonly purgeLocal: (document: DocumentSummary) => Promise<boolean>;\n readonly purgeRemote: (document: DocumentSummary) => Promise<boolean>;\n readonly unlink: (\n document: DocumentSummary,\n containerIds: readonly string[],\n ) => Promise<boolean>;\n}\n\nfunction resolveSubtreeDocumentOperations(\n input: PurgeContainerTreeInput,\n scope: ReturnType<typeof createSubtreePurgeScope>,\n): SubtreeDocumentOperations {\n const expectedSubtreeRoot = selectedSubtreeRoot(input);\n const operations: SubtreeDocumentOperations = input.documentOperations ?? {\n purgeLocal: async (document) =>\n (await purgeLocalContainerDocument({\n beforeDeleteInTransaction: (execSql) =>\n scope.assertLocalScopeInTransaction(\n execSql,\n document.containerId,\n document.id,\n ),\n noteId: document.id,\n expectedContainerId: document.containerId,\n runtime: input.runtime,\n })) !== null,\n purgeRemote: async (document) =>\n Boolean(\n document.documentId &&\n (await purgeRemoteContainerDocument({\n beforeSubmit: () => scope.allowsDocument(document),\n documentId: document.documentId,\n expectedSubtreeRoot,\n stillCurrent: input.stillCurrent,\n documentKind: document.documentKind ?? DEFAULT_DOCUMENT_KIND,\n noteId: document.id,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n })),\n ),\n unlink: (document, containerIds) =>\n unlinkSubtreeDocument({\n // Target preparation and signing can outlast the upfront checks.\n beforeSubmit: async (containerId) =>\n (await scope.allowsDocument(document)) &&\n (await scope.allowsContainer(containerId)),\n containerIds,\n document,\n expectedSubtreeRoot,\n stillCurrent: input.stillCurrent,\n prepareDocumentRotationSnapshot: input.prepareDocumentRotationSnapshot,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n }),\n };\n return {\n purgeLocal: async (document) =>\n (await scope.allowsDocument(document)) &&\n (await operations.purgeLocal(document)),\n purgeRemote: async (document) =>\n (await scope.allowsDocument(document)) &&\n (await operations.purgeRemote(document)),\n unlink: async (document, containerIds) => {\n if (!(await scope.allowsDocument(document))) return false;\n for (const containerId of containerIds) {\n if (!(await scope.allowsContainer(containerId))) return false;\n }\n return operations.unlink(document, containerIds);\n },\n };\n}\n\ninterface SubtreeTeardownResult {\n readonly aborted: boolean;\n}\n\n// Signed request paths must keep the root under the parent it was selected\n// from; a settled restore elsewhere preserves the root's own documents too.\nfunction selectedSubtreeRoot(\n input: Pick<PurgeContainerTreeInput, \"containersById\" | \"rootContainerId\">,\n): SubtreePurgeRoot {\n return {\n id: input.rootContainerId,\n parentId:\n input.containersById.get(input.rootContainerId)?.container.parentId ??\n null,\n };\n}\n\nfunction purgeWasCancelled(input: {\n readonly signal?: AbortSignal | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): boolean {\n return input.signal?.aborted === true || input.stillCurrent?.() === false;\n}\n\n// Tear down one whole document per progress step. A failed document is skipped,\n// leaving its container undeletable while the remaining subtree work continues.\n// Cancellation is honored only between complete document operations.\nasync function teardownSubtreeDocuments(input: {\n readonly documentOperations: SubtreeDocumentOperations;\n readonly plan: SubtreeDocumentPlan;\n readonly reportStep: (ok: boolean) => void;\n readonly signal?: AbortSignal | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<SubtreeTeardownResult> {\n for (const {\n document,\n containerIds,\n } of input.plan.unlinkByDocument.values()) {\n if (purgeWasCancelled(input)) {\n return { aborted: true };\n }\n const unlinked = await input.documentOperations.unlink(\n document,\n containerIds,\n );\n input.reportStep(unlinked);\n }\n for (const { document, unlinkContainerIds } of input.plan.purge) {\n if (purgeWasCancelled(input)) {\n return { aborted: true };\n }\n if (\n unlinkContainerIds.length > 0 &&\n !(await input.documentOperations.unlink(document, unlinkContainerIds))\n ) {\n input.reportStep(false);\n continue;\n }\n input.reportStep(await input.documentOperations.purgeRemote(document));\n }\n for (const document of input.plan.purgeLocal) {\n if (purgeWasCancelled(input)) {\n return { aborted: true };\n }\n input.reportStep(await input.documentOperations.purgeLocal(document));\n }\n return { aborted: false };\n}\n\n// Permanently destroy a folder that lives inside Trash, including everything\n// under it (or, with keepRootContainer, everything under the Trash bin while\n// leaving the bin in place — this is \"Empty Trash\"). Documents are destroyed only\n// when the subtree holds their last link; multi-folder documents are unlinked\n// from the subtree and preserved. Containers are deleted leaf-first so each\n// delete obeys the leaf-only constraint the store and server enforce. Every step\n// is remote-first then local (the per-document and per-container workflows handle\n// that internally), so a cancel between steps leaves local state reflecting\n// exactly the completed remote work.\n//\n// Progress is determinate: the plan (a pure read) completes before any\n// destructive step, so onProgress reports completed/failed against a total known\n// up front. A failed item is skipped rather than aborting the run, so the result\n// reports whatever prefix was actually destroyed alongside completed/failed\n// counts and whether a cancellation cut it short. Returns null only when the\n// target container is absent from the snapshot.\nexport async function purgeContainerTree(\n request: PurgeContainerTreeInput,\n): Promise<PurgeContainerTreeResult | null> {\n if (purgeWasCancelled(request)) {\n return null;\n }\n const input = {\n ...request,\n containersById: snapshotContainerStates(request.containersById),\n };\n const subtreeStates = collectSubtreeLeafFirst(\n input.containersById,\n input.rootContainerId,\n );\n if (subtreeStates.length === 0) {\n return null;\n }\n const subtreeContainerIds = new Set(\n subtreeStates.map((containerState) => containerState.container.id),\n );\n\n const plan = await planSubtreeDocuments({\n execSql: input.runtime.infra.execSql,\n subtreeContainerIds,\n });\n if (purgeWasCancelled(input)) {\n return null;\n }\n\n // Empty Trash keeps the Trash bin itself: tear down everything it holds, but\n // exclude the root from the container deletions (deleting a system container\n // would be rejected anyway).\n const containerStatesToDelete = input.keepRootContainer\n ? subtreeStates.filter(\n (containerState) =>\n containerState.container.id !== input.rootContainerId,\n )\n : subtreeStates;\n\n // The total is fully known here — planning is a pure read that completes before\n // any destructive step. Unlink work is counted per document (not per container\n // link) so completed can never exceed total even when a document has several\n // in-subtree links.\n const totalCount =\n plan.unlinkByDocument.size +\n plan.purge.length +\n plan.purgeLocal.length +\n containerStatesToDelete.length;\n\n let completedCount = 0;\n let failedCount = 0;\n const emitProgress = () => {\n input.onProgress?.({ completedCount, failedCount, totalCount });\n };\n const reportStep = (ok: boolean) => {\n if (ok) {\n completedCount += 1;\n } else {\n failedCount += 1;\n }\n emitProgress();\n };\n // Emit the initial 0/total so a determinate bar renders immediately, before the\n // first (potentially slow) remote call.\n emitProgress();\n\n const scope = createSubtreePurgeScope(input);\n const teardown = await teardownSubtreeDocuments({\n documentOperations: resolveSubtreeDocumentOperations(input, scope),\n plan,\n reportStep,\n signal: input.signal,\n stillCurrent: input.stillCurrent,\n });\n\n let purgedContainerIds: readonly string[] = [];\n let remoteDeletedContainerIds: readonly string[] = [];\n let aborted = teardown.aborted;\n if (!teardown.aborted) {\n const deletion = await deleteSubtreeContainers({\n allowsContainer: scope.allowsContainer,\n allowsLocalScopeInTransaction: scope.allowsLocalScopeInTransaction,\n root: selectedSubtreeRoot(input),\n persistence: input.persistence,\n reportStep,\n runtime: input.runtime,\n signal: input.signal,\n stillCurrent: input.stillCurrent,\n subtreeStates: containerStatesToDelete,\n });\n purgedContainerIds = deletion.purgedContainerIds;\n remoteDeletedContainerIds = deletion.remoteDeletedContainerIds;\n aborted = deletion.aborted;\n }\n\n return {\n aborted,\n completedCount,\n failedCount,\n purgedContainerIds,\n remoteDeletedContainerIds,\n totalCount,\n };\n}\n"]}
1
+ {"version":3,"file":"purgeTree.js","sourceRoot":"","sources":["purgeTree.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { listDocumentsByContainerIdsOrDocumentIds } from \"../../../data/persistence/documents/documentsPersistence\";\nimport type { SubtreePurgeRoot } from \"../../documents/subtreePurgeScope\";\nimport type { ContainerContentsPersistence } from \"../containerPersistence\";\nimport { unlinkRemoteContainerDocument } from \"../documentLinks\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\nimport {\n purgeLocalContainerDocument,\n purgeRemoteContainerDocument,\n} from \"../tombstones/documentPurge\";\nimport type { PurgeProgress } from \"./purgeProgress\";\nimport {\n collectSubtreeLeafFirst,\n snapshotContainerStates,\n} from \"./purgeTreeCollection\";\nimport { deleteSubtreeContainers } from \"./purgeTreeContainerDeletion\";\nimport { createSubtreePurgeScope } from \"./purgeTreeScope\";\n\nexport { collectSubtreeLeafFirst } from \"./purgeTreeCollection\";\n\n// The store runtime satisfies the per-document purge/unlink workflows, so the\n// cascade reuses it verbatim.\ntype PurgeContainerTreeRuntime = ContainerContentsWorkflowRuntime;\n\ninterface PurgeContainerTreeInput {\n readonly containersById: ReadonlyMap<string, ContainerState>;\n readonly documentOperations?: SubtreeDocumentOperations | undefined;\n // When true, tear down everything UNDER the root (its documents plus every\n // descendant container) but never delete the root container itself. This is\n // how \"Empty Trash\" reuses the same engine: the Trash bin is a protected system\n // container that must survive while its whole contents are destroyed.\n readonly keepRootContainer?: boolean;\n readonly onProgress?: ((progress: PurgeProgress) => void) | undefined;\n readonly persistence: ContainerContentsPersistence;\n readonly prepareDocumentRotationSnapshot: (\n document: DocumentSummary,\n ) => Promise<Uint8Array | null>;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly rootContainerId: string;\n readonly runtime: PurgeContainerTreeRuntime;\n /** Stops a stale store generation between complete destructive units. */\n readonly stillCurrent?: (() => boolean) | undefined;\n // Checked at each unit boundary (between whole documents / whole containers),\n // never mid-remote-call, so a cancelled run stops on a consistent prefix.\n readonly signal?: AbortSignal | undefined;\n}\n\ninterface PurgeContainerTreeResult {\n readonly aborted: boolean;\n readonly completedCount: number;\n readonly failedCount: number;\n readonly purgedContainerIds: readonly string[];\n readonly remoteDeletedContainerIds: readonly string[];\n readonly totalCount: number;\n}\n\ninterface SubtreeDocumentPlan {\n // Synced documents whose every link falls inside the subtree: reduce them to\n // one retained link, as required by the purge endpoint, then destroy them.\n readonly purge: readonly {\n document: DocumentSummary;\n unlinkContainerIds: readonly string[];\n }[];\n // Synced documents also linked outside the subtree: keep them, but unlink\n // from each in-subtree container so the containers can be deleted.\n readonly unlinkByDocument: ReadonlyMap<\n string,\n { document: DocumentSummary; containerIds: readonly string[] }\n >;\n // Never-synced documents (no remote id): destroy locally only.\n readonly purgeLocal: readonly DocumentSummary[];\n}\n\ntype SubtreeDocumentDisposition =\n | { kind: \"purge\"; unlinkContainerIds: readonly string[] }\n | { kind: \"purge-local\" }\n | { kind: \"unlink\"; containerIds: readonly string[] };\n\n// Destroy local-only documents locally. Destroy synced documents only when all\n// links are in the subtree; preserve documents with an external link. The purge\n// plan reduces owned documents to the server-required sole link first.\nexport function classifySubtreeDocument(input: {\n readonly documentId: string | null;\n readonly linkedContainerIds: readonly string[];\n readonly preferredContainerId?: string | null | undefined;\n readonly subtreeContainerIds: ReadonlySet<string>;\n}): SubtreeDocumentDisposition {\n if (!input.documentId) {\n return { kind: \"purge-local\" };\n }\n const hasExternalLink = input.linkedContainerIds.some(\n (containerId) => !input.subtreeContainerIds.has(containerId),\n );\n if (!hasExternalLink) {\n const linkedContainerIds = Array.from(\n new Set(\n input.linkedContainerIds.filter((containerId) =>\n input.subtreeContainerIds.has(containerId),\n ),\n ),\n );\n const retainedContainerId =\n input.preferredContainerId &&\n linkedContainerIds.includes(input.preferredContainerId)\n ? input.preferredContainerId\n : linkedContainerIds[0];\n return {\n kind: \"purge\",\n unlinkContainerIds: linkedContainerIds.filter(\n (containerId) => containerId !== retainedContainerId,\n ),\n };\n }\n return {\n kind: \"unlink\",\n containerIds: input.linkedContainerIds.filter((containerId) =>\n input.subtreeContainerIds.has(containerId),\n ),\n };\n}\n\nasync function planSubtreeDocuments(input: {\n readonly execSql: PurgeContainerTreeRuntime[\"infra\"][\"execSql\"];\n readonly subtreeContainerIds: ReadonlySet<string>;\n}): Promise<SubtreeDocumentPlan> {\n const documents = await listDocumentsByContainerIdsOrDocumentIds(\n input.execSql,\n {\n containerIds: [...input.subtreeContainerIds],\n documentIds: [],\n },\n );\n const remoteDocumentIds = documents.flatMap((document) =>\n document.documentId ? [document.documentId] : [],\n );\n const linkedContainerIdsByDocumentId =\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n input.execSql,\n remoteDocumentIds,\n );\n\n const purge: Array<{\n document: DocumentSummary;\n unlinkContainerIds: readonly string[];\n }> = [];\n const purgeLocal: DocumentSummary[] = [];\n const unlinkByDocument = new Map<\n string,\n { document: DocumentSummary; containerIds: readonly string[] }\n >();\n for (const document of documents) {\n const disposition = classifySubtreeDocument({\n documentId: document.documentId ?? null,\n linkedContainerIds: document.documentId\n ? (linkedContainerIdsByDocumentId.get(document.documentId) ?? [])\n : [],\n preferredContainerId: document.containerId,\n subtreeContainerIds: input.subtreeContainerIds,\n });\n if (disposition.kind === \"purge-local\") {\n purgeLocal.push(document);\n } else if (disposition.kind === \"purge\") {\n purge.push({\n document,\n unlinkContainerIds: disposition.unlinkContainerIds,\n });\n } else if (document.documentId) {\n unlinkByDocument.set(document.documentId, {\n document,\n containerIds: disposition.containerIds,\n });\n }\n }\n\n return { purge, purgeLocal, unlinkByDocument };\n}\n\nasync function unlinkSubtreeDocument(input: {\n /** Rechecks the document and this exact unlink target before dispatch. */\n readonly beforeSubmit: (targetContainerId: string) => Promise<boolean>;\n readonly expectedSubtreeRoot: SubtreePurgeRoot;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly containerIds: readonly string[];\n readonly document: DocumentSummary;\n readonly prepareDocumentRotationSnapshot: PurgeContainerTreeInput[\"prepareDocumentRotationSnapshot\"];\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly runtime: PurgeContainerTreeRuntime;\n}): Promise<boolean> {\n const documentId = input.document.documentId;\n if (!documentId) {\n return true;\n }\n let rotationSnapshot: Uint8Array | null;\n try {\n rotationSnapshot = await input.prepareDocumentRotationSnapshot(\n input.document,\n );\n } catch {\n return false;\n }\n if (!rotationSnapshot) {\n return false;\n }\n for (const containerId of input.containerIds) {\n const result = await unlinkRemoteContainerDocument({\n beforeSubmit: () => input.beforeSubmit(containerId),\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n isCurrent: input.stillCurrent,\n noteId: input.document.id,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n rotationSnapshot,\n runtime: input.runtime,\n targetContainerId: containerId,\n });\n if (result === null) {\n return false;\n }\n }\n return true;\n}\n\ninterface SubtreeDocumentOperations {\n readonly purgeLocal: (document: DocumentSummary) => Promise<boolean>;\n readonly purgeRemote: (document: DocumentSummary) => Promise<boolean>;\n readonly unlink: (\n document: DocumentSummary,\n containerIds: readonly string[],\n ) => Promise<boolean>;\n}\n\nfunction resolveSubtreeDocumentOperations(\n input: PurgeContainerTreeInput,\n scope: ReturnType<typeof createSubtreePurgeScope>,\n): SubtreeDocumentOperations {\n const expectedSubtreeRoot = selectedSubtreeRoot(input);\n const operations: SubtreeDocumentOperations = input.documentOperations ?? {\n purgeLocal: async (document) =>\n (await purgeLocalContainerDocument({\n beforeDeleteInTransaction: (execSql) =>\n scope.assertLocalScopeInTransaction(\n execSql,\n document.containerId,\n document.id,\n ),\n noteId: document.id,\n expectedContainerId: document.containerId,\n runtime: input.runtime,\n })) !== null,\n purgeRemote: async (document) =>\n Boolean(\n document.documentId &&\n (await purgeRemoteContainerDocument({\n beforeSubmit: () => scope.allowsDocument(document),\n documentId: document.documentId,\n expectedSubtreeRoot,\n stillCurrent: input.stillCurrent,\n documentKind: document.documentKind ?? DEFAULT_DOCUMENT_KIND,\n noteId: document.id,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n })),\n ),\n unlink: (document, containerIds) =>\n unlinkSubtreeDocument({\n // Target preparation and signing can outlast the upfront checks.\n beforeSubmit: async (containerId) =>\n (await scope.allowsDocument(document)) &&\n (await scope.allowsContainer(containerId)),\n containerIds,\n document,\n expectedSubtreeRoot,\n stillCurrent: input.stillCurrent,\n prepareDocumentRotationSnapshot: input.prepareDocumentRotationSnapshot,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n }),\n };\n return {\n purgeLocal: async (document) =>\n (await scope.allowsDocument(document)) &&\n (await operations.purgeLocal(document)),\n purgeRemote: async (document) =>\n (await scope.allowsDocument(document)) &&\n (await operations.purgeRemote(document)),\n unlink: async (document, containerIds) => {\n if (!(await scope.allowsDocument(document))) return false;\n for (const containerId of containerIds) {\n if (!(await scope.allowsContainer(containerId))) return false;\n }\n return operations.unlink(document, containerIds);\n },\n };\n}\n\ninterface SubtreeTeardownResult {\n readonly aborted: boolean;\n}\n\n// Signed request paths must keep the root under the parent it was selected\n// from; a settled restore elsewhere preserves the root's own documents too.\nfunction selectedSubtreeRoot(\n input: Pick<PurgeContainerTreeInput, \"containersById\" | \"rootContainerId\">,\n): SubtreePurgeRoot {\n return {\n id: input.rootContainerId,\n parentId:\n input.containersById.get(input.rootContainerId)?.container.parentId ??\n null,\n };\n}\n\nfunction purgeWasCancelled(input: {\n readonly signal?: AbortSignal | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): boolean {\n return input.signal?.aborted === true || input.stillCurrent?.() === false;\n}\n\n// Tear down one whole document per progress step. A failed document is skipped,\n// leaving its container undeletable while the remaining subtree work continues.\n// Cancellation is honored only between complete document operations.\nasync function teardownSubtreeDocuments(input: {\n readonly documentOperations: SubtreeDocumentOperations;\n readonly plan: SubtreeDocumentPlan;\n readonly reportStep: (ok: boolean) => void;\n readonly signal?: AbortSignal | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<SubtreeTeardownResult> {\n for (const {\n document,\n containerIds,\n } of input.plan.unlinkByDocument.values()) {\n if (purgeWasCancelled(input)) {\n return { aborted: true };\n }\n const unlinked = await input.documentOperations.unlink(\n document,\n containerIds,\n );\n input.reportStep(unlinked);\n }\n for (const { document, unlinkContainerIds } of input.plan.purge) {\n if (purgeWasCancelled(input)) {\n return { aborted: true };\n }\n if (\n unlinkContainerIds.length > 0 &&\n !(await input.documentOperations.unlink(document, unlinkContainerIds))\n ) {\n input.reportStep(false);\n continue;\n }\n input.reportStep(await input.documentOperations.purgeRemote(document));\n }\n for (const document of input.plan.purgeLocal) {\n if (purgeWasCancelled(input)) {\n return { aborted: true };\n }\n input.reportStep(await input.documentOperations.purgeLocal(document));\n }\n return { aborted: false };\n}\n\n// Permanently destroy a folder that lives inside Trash, including everything\n// under it (or, with keepRootContainer, everything under the Trash bin while\n// leaving the bin in place — this is \"Empty Trash\"). Documents are destroyed only\n// when the subtree holds their last link; multi-folder documents are unlinked\n// from the subtree and preserved. Containers are deleted leaf-first so each\n// delete obeys the leaf-only constraint the store and server enforce. Every step\n// is remote-first then local (the per-document and per-container workflows handle\n// that internally), so a cancel between steps leaves local state reflecting\n// exactly the completed remote work.\n//\n// Progress is determinate: the plan (a pure read) completes before any\n// destructive step, so onProgress reports completed/failed against a total known\n// up front. A failed item is skipped rather than aborting the run, so the result\n// reports whatever prefix was actually destroyed alongside completed/failed\n// counts and whether a cancellation cut it short. Returns null only when the\n// target container is absent from the snapshot.\nexport async function purgeContainerTree(\n request: PurgeContainerTreeInput,\n): Promise<PurgeContainerTreeResult | null> {\n if (purgeWasCancelled(request)) {\n return null;\n }\n const input = {\n ...request,\n containersById: snapshotContainerStates(request.containersById),\n };\n const subtreeStates = collectSubtreeLeafFirst(\n input.containersById,\n input.rootContainerId,\n );\n if (subtreeStates.length === 0) {\n return null;\n }\n const subtreeContainerIds = new Set(\n subtreeStates.map((containerState) => containerState.container.id),\n );\n\n const plan = await planSubtreeDocuments({\n execSql: input.runtime.infra.execSql,\n subtreeContainerIds,\n });\n if (purgeWasCancelled(input)) {\n return null;\n }\n\n // Empty Trash keeps the Trash bin itself: tear down everything it holds, but\n // exclude the root from the container deletions (deleting a system container\n // would be rejected anyway).\n const containerStatesToDelete = input.keepRootContainer\n ? subtreeStates.filter(\n (containerState) =>\n containerState.container.id !== input.rootContainerId,\n )\n : subtreeStates;\n\n // The total is fully known here — planning is a pure read that completes before\n // any destructive step. Unlink work is counted per document (not per container\n // link) so completed can never exceed total even when a document has several\n // in-subtree links.\n const totalCount =\n plan.unlinkByDocument.size +\n plan.purge.length +\n plan.purgeLocal.length +\n containerStatesToDelete.length;\n\n let completedCount = 0;\n let failedCount = 0;\n const emitProgress = () => {\n input.onProgress?.({ completedCount, failedCount, totalCount });\n };\n const reportStep = (ok: boolean) => {\n if (ok) {\n completedCount += 1;\n } else {\n failedCount += 1;\n }\n emitProgress();\n };\n // Emit the initial 0/total so a determinate bar renders immediately, before the\n // first (potentially slow) remote call.\n emitProgress();\n\n const scope = createSubtreePurgeScope(input);\n const teardown = await teardownSubtreeDocuments({\n documentOperations: resolveSubtreeDocumentOperations(input, scope),\n plan,\n reportStep,\n signal: input.signal,\n stillCurrent: input.stillCurrent,\n });\n\n let purgedContainerIds: readonly string[] = [];\n let remoteDeletedContainerIds: readonly string[] = [];\n let aborted = teardown.aborted;\n if (!teardown.aborted) {\n const deletion = await deleteSubtreeContainers({\n allowsContainer: scope.allowsContainer,\n allowsLocalScopeInTransaction: scope.allowsLocalScopeInTransaction,\n root: selectedSubtreeRoot(input),\n persistence: input.persistence,\n reportStep,\n runtime: input.runtime,\n signal: input.signal,\n stillCurrent: input.stillCurrent,\n subtreeStates: containerStatesToDelete,\n });\n purgedContainerIds = deletion.purgedContainerIds;\n remoteDeletedContainerIds = deletion.remoteDeletedContainerIds;\n aborted = deletion.aborted;\n }\n\n return {\n aborted,\n completedCount,\n failedCount,\n purgedContainerIds,\n remoteDeletedContainerIds,\n totalCount,\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { persistContainerMetadataStateFromRuntime, } from "../metadata.js";
2
- import { createDetachedContainerMetadataState, installDetachedContainerMetadataState, } from "../metadataStateIsolation.js";
1
+ import { persistContainerMetadataStateFromRuntime, } from "../metadata/index.js";
2
+ import { createDetachedContainerMetadataState, installDetachedContainerMetadataState, } from "../metadata/metadataStateIsolation.js";
3
3
  import { installContainerWriterProjection } from "./projectionCache.js";
4
4
  // These helpers run only after the remote grant is verified. A skipped local
5
5
  // install does not undo that acknowledgement; reconciliation installs it later.
@@ -1 +1 @@
1
- {"version":3,"file":"sharePersistence.js","sourceRoot":"","sources":["sharePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type { ContainerContentsPersistence } from \"../containerPersistence\";\nimport {\n type ContainerMetadataPatch,\n persistContainerMetadataStateFromRuntime,\n} from \"../metadata\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"../metadataStateIsolation\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { installContainerWriterProjection } from \"./projectionCache\";\nimport type {\n ContainerWorkflowRuntime,\n SharedContainerStateResult,\n SharedRemoteContainerState,\n} from \"./types\";\n\nexport interface MatchingRemoteContainerGrant {\n accessEpoch: number;\n accessStateHash: string;\n createdAt: string | null;\n metadataDocumentId: string;\n referencedPrincipalHeads: ReadonlyArray<ReferencedPrincipalStateResponse>;\n updatedAt: string | null;\n}\n\n// These helpers run only after the remote grant is verified. A skipped local\n// install does not undo that acknowledgement; reconciliation installs it later.\nexport async function persistSharedContainerState(input: {\n containerState: ContainerState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerWorkflowRuntime;\n shared: SharedRemoteContainerState;\n stillCurrent?: (() => boolean) | undefined;\n /** `writerProjectionGeneration` captured before the share flow began. */\n writerProjectionGeneration: number;\n}): Promise<SharedContainerStateResult | null> {\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n const candidateState = await createDetachedContainerMetadataState(\n input.containerState,\n { writerProjectionGeneration: input.writerProjectionGeneration },\n );\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n candidateState.container = {\n ...input.containerState.container,\n createdAt: input.shared.createdAt,\n serverCreatedAt: input.shared.createdAt,\n serverUpdatedAt: input.shared.updatedAt,\n updatedAt: input.shared.updatedAt,\n };\n\n const persisted = await persistContainerMetadataStateFromRuntime({\n metadataState: candidateState,\n patch: {\n accessEpoch: input.shared.accessEpoch,\n accessStateHash: input.shared.accessManifestHash,\n documentId: input.shared.metadataDocumentId,\n metadataDocumentId: input.shared.metadataDocumentId,\n contentKeyBundle: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n },\n persistence: input.persistence,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n saveOptions: {\n serverTimestamps: {\n createdAt: input.shared.createdAt,\n updatedAt: input.shared.updatedAt,\n },\n },\n });\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n if (!persisted) return { status: \"missing\" };\n candidateState.container = persisted.container;\n installDetachedContainerMetadataState(input.containerState, candidateState, {\n candidateRecord: persisted.record,\n preserveConcurrentMetadataEdit: true,\n });\n if (persisted.mutationSuperseded || persisted.syncIdentitySuperseded) {\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"identity-superseded\",\n };\n }\n installContainerWriterProjection(\n input.containerState,\n input.shared.writerProjection,\n input.writerProjectionGeneration,\n );\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"persisted\",\n };\n}\n\nexport async function persistDuplicateContainerShare(input: {\n containerState: ContainerState;\n grant: MatchingRemoteContainerGrant;\n persistence: ContainerContentsPersistence;\n projection: ContainerWriterProjectionResponse;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n /** `writerProjectionGeneration` captured before the share flow began. */\n writerProjectionGeneration: number;\n}): Promise<SharedContainerStateResult | null> {\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n const candidateState = await createDetachedContainerMetadataState(\n input.containerState,\n { writerProjectionGeneration: input.writerProjectionGeneration },\n );\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n candidateState.container = {\n ...input.containerState.container,\n ...(input.grant.createdAt\n ? {\n createdAt: input.grant.createdAt,\n serverCreatedAt: input.grant.createdAt,\n }\n : {}),\n ...(input.grant.updatedAt\n ? {\n serverUpdatedAt: input.grant.updatedAt,\n updatedAt: input.grant.updatedAt,\n }\n : {}),\n };\n const securityContextChanged =\n candidateState.record.documentId !== input.grant.metadataDocumentId ||\n candidateState.record.accessEpoch !== input.grant.accessEpoch ||\n candidateState.record.accessStateHash !== input.grant.accessStateHash;\n const patch: Partial<ContainerMetadataPatch> = {\n accessEpoch: input.grant.accessEpoch,\n accessStateHash: input.grant.accessStateHash,\n documentId: input.grant.metadataDocumentId,\n metadataDocumentId: input.grant.metadataDocumentId,\n ...(securityContextChanged\n ? {\n contentKeyBundle: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n }\n : {}),\n };\n const persisted = await persistContainerMetadataStateFromRuntime({\n metadataState: candidateState,\n patch,\n persistence: input.persistence,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n saveOptions: {\n serverTimestamps: {\n createdAt: input.grant.createdAt,\n updatedAt: input.grant.updatedAt,\n },\n },\n });\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n if (!persisted) return { status: \"missing\" };\n candidateState.container = persisted.container;\n installDetachedContainerMetadataState(input.containerState, candidateState, {\n candidateRecord: persisted.record,\n preserveConcurrentMetadataEdit: true,\n });\n if (persisted.mutationSuperseded || persisted.syncIdentitySuperseded) {\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"identity-superseded\",\n };\n }\n installContainerWriterProjection(\n input.containerState,\n input.projection,\n input.writerProjectionGeneration,\n );\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"persisted\",\n };\n}\n"]}
1
+ {"version":3,"file":"sharePersistence.js","sourceRoot":"","sources":["sharePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type { ContainerContentsPersistence } from \"../containerPersistence\";\nimport {\n type ContainerMetadataPatch,\n persistContainerMetadataStateFromRuntime,\n} from \"../metadata\";\nimport {\n createDetachedContainerMetadataState,\n installDetachedContainerMetadataState,\n} from \"../metadata/metadataStateIsolation\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { installContainerWriterProjection } from \"./projectionCache\";\nimport type {\n ContainerWorkflowRuntime,\n SharedContainerStateResult,\n SharedRemoteContainerState,\n} from \"./types\";\n\nexport interface MatchingRemoteContainerGrant {\n accessEpoch: number;\n accessStateHash: string;\n createdAt: string | null;\n metadataDocumentId: string;\n referencedPrincipalHeads: ReadonlyArray<ReferencedPrincipalStateResponse>;\n updatedAt: string | null;\n}\n\n// These helpers run only after the remote grant is verified. A skipped local\n// install does not undo that acknowledgement; reconciliation installs it later.\nexport async function persistSharedContainerState(input: {\n containerState: ContainerState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerWorkflowRuntime;\n shared: SharedRemoteContainerState;\n stillCurrent?: (() => boolean) | undefined;\n /** `writerProjectionGeneration` captured before the share flow began. */\n writerProjectionGeneration: number;\n}): Promise<SharedContainerStateResult | null> {\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n const candidateState = await createDetachedContainerMetadataState(\n input.containerState,\n { writerProjectionGeneration: input.writerProjectionGeneration },\n );\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n candidateState.container = {\n ...input.containerState.container,\n createdAt: input.shared.createdAt,\n serverCreatedAt: input.shared.createdAt,\n serverUpdatedAt: input.shared.updatedAt,\n updatedAt: input.shared.updatedAt,\n };\n\n const persisted = await persistContainerMetadataStateFromRuntime({\n metadataState: candidateState,\n patch: {\n accessEpoch: input.shared.accessEpoch,\n accessStateHash: input.shared.accessManifestHash,\n documentId: input.shared.metadataDocumentId,\n metadataDocumentId: input.shared.metadataDocumentId,\n contentKeyBundle: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n },\n persistence: input.persistence,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n saveOptions: {\n serverTimestamps: {\n createdAt: input.shared.createdAt,\n updatedAt: input.shared.updatedAt,\n },\n },\n });\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n if (!persisted) return { status: \"missing\" };\n candidateState.container = persisted.container;\n installDetachedContainerMetadataState(input.containerState, candidateState, {\n candidateRecord: persisted.record,\n preserveConcurrentMetadataEdit: true,\n });\n if (persisted.mutationSuperseded || persisted.syncIdentitySuperseded) {\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"identity-superseded\",\n };\n }\n installContainerWriterProjection(\n input.containerState,\n input.shared.writerProjection,\n input.writerProjectionGeneration,\n );\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"persisted\",\n };\n}\n\nexport async function persistDuplicateContainerShare(input: {\n containerState: ContainerState;\n grant: MatchingRemoteContainerGrant;\n persistence: ContainerContentsPersistence;\n projection: ContainerWriterProjectionResponse;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n /** `writerProjectionGeneration` captured before the share flow began. */\n writerProjectionGeneration: number;\n}): Promise<SharedContainerStateResult | null> {\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n const candidateState = await createDetachedContainerMetadataState(\n input.containerState,\n { writerProjectionGeneration: input.writerProjectionGeneration },\n );\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n candidateState.container = {\n ...input.containerState.container,\n ...(input.grant.createdAt\n ? {\n createdAt: input.grant.createdAt,\n serverCreatedAt: input.grant.createdAt,\n }\n : {}),\n ...(input.grant.updatedAt\n ? {\n serverUpdatedAt: input.grant.updatedAt,\n updatedAt: input.grant.updatedAt,\n }\n : {}),\n };\n const securityContextChanged =\n candidateState.record.documentId !== input.grant.metadataDocumentId ||\n candidateState.record.accessEpoch !== input.grant.accessEpoch ||\n candidateState.record.accessStateHash !== input.grant.accessStateHash;\n const patch: Partial<ContainerMetadataPatch> = {\n accessEpoch: input.grant.accessEpoch,\n accessStateHash: input.grant.accessStateHash,\n documentId: input.grant.metadataDocumentId,\n metadataDocumentId: input.grant.metadataDocumentId,\n ...(securityContextChanged\n ? {\n contentKeyBundle: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n }\n : {}),\n };\n const persisted = await persistContainerMetadataStateFromRuntime({\n metadataState: candidateState,\n patch,\n persistence: input.persistence,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n saveOptions: {\n serverTimestamps: {\n createdAt: input.grant.createdAt,\n updatedAt: input.grant.updatedAt,\n },\n },\n });\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n if (!persisted) return { status: \"missing\" };\n candidateState.container = persisted.container;\n installDetachedContainerMetadataState(input.containerState, candidateState, {\n candidateRecord: persisted.record,\n preserveConcurrentMetadataEdit: true,\n });\n if (persisted.mutationSuperseded || persisted.syncIdentitySuperseded) {\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"identity-superseded\",\n };\n }\n installContainerWriterProjection(\n input.containerState,\n input.projection,\n input.writerProjectionGeneration,\n );\n return {\n container: input.containerState.container,\n record: input.containerState.record,\n status: \"persisted\",\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { DEFAULT_CONTAINER_DOCUMENT_LANE_PAGE_LIMIT, MAX_CONTAINER_DOCUMENT_LANE_PAGE_TOTAL, MAX_CONTAINER_DOCUMENT_LANES, } from "../../internal/validators/request/index.js";
1
+ import { DEFAULT_CONTAINER_DOCUMENT_LANE_PAGE_LIMIT, MAX_CONTAINER_DOCUMENT_LANE_PAGE_TOTAL, MAX_CONTAINER_DOCUMENT_LANES, } from "../../../internal/validators/request/index.js";
2
2
  /**
3
3
  * Rows each lane may return so a full batch stays within the single-page
4
4
  * maximum; a lone lane keeps the ordinary page size.
@@ -1,7 +1,7 @@
1
- import { dedupeReferencedPrincipalStates } from "../../data/keyingProjectionVerification/principalPolicyCache.js";
2
- import { withoutDeferredDocumentLinks } from "./deferredDocumentLinks.js";
1
+ import { dedupeReferencedPrincipalStates } from "../../../data/keyingProjectionVerification/principalPolicyCache.js";
2
+ import { withoutDeferredDocumentLinks } from "../documentLinks/deferredDocumentLinks.js";
3
+ import { settleContainerDocumentTombstones } from "../tombstones/documentTombstoneGate.js";
3
4
  import { getApplicableDocumentTombstones } from "./documentDiscoveryInputs.js";
4
- import { settleContainerDocumentTombstones } from "./documentTombstoneGate.js";
5
5
  export async function saveAppliedContainerDocumentWatermark(input) {
6
6
  const { containerId, listedDocuments, saveContainerDocumentWatermark } = input;
7
7
  if (!listedDocuments.nextWatermark) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentDiscoveryApply.js","sourceRoot":"","sources":["documentDiscoveryApply.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { dedupeReferencedPrincipalStates } from \"../../../data/keyingProjectionVerification/principalPolicyCache\";\nimport { withoutDeferredDocumentLinks } from \"../documentLinks/deferredDocumentLinks\";\nimport { settleContainerDocumentTombstones } from \"../tombstones/documentTombstoneGate\";\nimport { getApplicableDocumentTombstones } from \"./documentDiscoveryInputs\";\nimport type {\n DiscoverContainerDocumentsOptions,\n ListedContainerDocuments,\n} from \"./documentDiscoveryTypes\";\n\n/** A discovery lane's local stores; the listing itself is supplied by the caller. */\nexport type ContainerDocumentDiscoveryLane = Omit<\n DiscoverContainerDocumentsOptions,\n | \"beginDocumentDiscovery\"\n | \"listContainerDocumentLanes\"\n | \"loadContainerDocumentWatermark\"\n>;\n\nexport async function saveAppliedContainerDocumentWatermark(input: {\n containerId: string;\n listedDocuments: ListedContainerDocuments;\n saveContainerDocumentWatermark: DiscoverContainerDocumentsOptions[\"saveContainerDocumentWatermark\"];\n}) {\n const { containerId, listedDocuments, saveContainerDocumentWatermark } =\n input;\n if (!listedDocuments.nextWatermark) {\n return;\n }\n\n await saveContainerDocumentWatermark(\n containerId,\n listedDocuments.nextWatermark,\n );\n}\n\n/**\n * Verifies and applies one container's completed listing under a discovery\n * generation captured before the listing request, then advances its\n * watermark. Returns `null` when nothing was applied.\n */\nexport async function applyListedContainerDocuments(\n options: ContainerDocumentDiscoveryLane,\n generation: number,\n listedDocuments: ListedContainerDocuments,\n): Promise<ReadonlyArray<DocumentSummary> | null> {\n const { containerId, upsertDiscoveredDocuments } = options;\n await options.cacheReferencedPrincipalPolicies?.(\n dedupeReferencedPrincipalStates(\n listedDocuments.items.flatMap(\n (document) => document.referencedPrincipals,\n ),\n ),\n );\n\n const verification = await options.verifyDiscoveredDocuments(\n listedDocuments.items.map((document) => ({\n accessEpoch: document.currentAccessEpoch,\n accessStateHash: document.currentAccessStateHash,\n containerId,\n listedContainerIds: [containerId],\n createdAt: document.createdAt,\n documentId: document.id,\n effectiveAccessLevel: document.effectiveAccessLevel,\n linkedContainerIds: document.linkedContainerIds,\n })),\n [containerId],\n generation,\n getApplicableDocumentTombstones(listedDocuments),\n );\n if (!(await verification.isCurrent())) return null;\n const verifiedInputs = verification.inputs;\n const discoveredDocuments = verifiedInputs.length\n ? await upsertDiscoveredDocuments(verifiedInputs)\n : [];\n\n if (verifiedInputs.length)\n await options.replaceDocumentLinksBatch(\n await withoutDeferredDocumentLinks(\n verifiedInputs.map((document) => ({\n documentId: document.documentId,\n accessEpoch: document.accessEpoch,\n containerIds: document.linkedContainerIds,\n })),\n discoveredDocuments,\n ),\n );\n\n const tombstoneDocumentSummaries = await settleContainerDocumentTombstones({\n containerIds: [containerId],\n store: options,\n tombstones: getApplicableDocumentTombstones(listedDocuments),\n });\n\n const complete = await verification.commit();\n if (!(await verification.isCurrent())) return null;\n await saveAppliedContainerDocumentWatermark({\n containerId,\n listedDocuments,\n saveContainerDocumentWatermark: options.saveContainerDocumentWatermark,\n });\n\n if (listedDocuments.isFullListing) {\n // Initial probes consume ids as discovery hints and verify their own heads.\n options.onFullListing?.(\n listedDocuments.items.map((document) => document.id),\n );\n }\n\n return !complete &&\n discoveredDocuments.length === 0 &&\n tombstoneDocumentSummaries.length === 0\n ? null\n : [...discoveredDocuments, ...tombstoneDocumentSummaries];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"documentDiscoveryCandidates.js","sourceRoot":"","sources":["documentDiscoveryCandidates.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,+BAA+B,CAC7C,UAAkD;IAElD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyC,CAAC;IACpE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3C,IAAI,CAAC,IAAI,CACP,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;YAC7B,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;gBAC5B,CAAC,CAAC,CAAC,CAAC;gBACJ,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;oBAC7B,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,CAAC,CAAC,CACX,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QAC/D,OAAO;YACL,IAAI;YACJ,KAAK,EAAE;gBACL,GAAG,KAAK;gBACR,kBAAkB,EAAE;oBAClB,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;iBAC1D,CAAC,IAAI,EAAE;aACT;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { DiscoveredDocumentCandidate } from \"../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\n\nexport function groupPendingDocumentDiscoveries(\n candidates: readonly DiscoveredDocumentCandidate[],\n) {\n const byDocument = new Map<string, DiscoveredDocumentCandidate[]>();\n for (const candidate of candidates) {\n const group = byDocument.get(candidate.documentId) ?? [];\n group.push(candidate);\n byDocument.set(candidate.documentId, group);\n }\n return [...byDocument.values()].map((rows) => {\n rows.sort(\n (a, b) =>\n b.accessEpoch - a.accessEpoch ||\n (a.containerId < b.containerId\n ? -1\n : a.containerId > b.containerId\n ? 1\n : 0),\n );\n const first = rows[0];\n if (!first) throw new Error(\"Empty discovery candidate group\");\n return {\n rows,\n input: {\n ...first,\n listedContainerIds: [\n ...new Set(rows.flatMap((row) => row.listedContainerIds)),\n ].sort(),\n },\n };\n });\n}\n"]}
1
+ {"version":3,"file":"documentDiscoveryCandidates.js","sourceRoot":"","sources":["documentDiscoveryCandidates.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,+BAA+B,CAC7C,UAAkD;IAElD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyC,CAAC;IACpE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3C,IAAI,CAAC,IAAI,CACP,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;YAC7B,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;gBAC5B,CAAC,CAAC,CAAC,CAAC;gBACJ,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;oBAC7B,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,CAAC,CAAC,CACX,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QAC/D,OAAO;YACL,IAAI;YACJ,KAAK,EAAE;gBACL,GAAG,KAAK;gBACR,kBAAkB,EAAE;oBAClB,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;iBAC1D,CAAC,IAAI,EAAE;aACT;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { DiscoveredDocumentCandidate } from \"../../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\n\nexport function groupPendingDocumentDiscoveries(\n candidates: readonly DiscoveredDocumentCandidate[],\n) {\n const byDocument = new Map<string, DiscoveredDocumentCandidate[]>();\n for (const candidate of candidates) {\n const group = byDocument.get(candidate.documentId) ?? [];\n group.push(candidate);\n byDocument.set(candidate.documentId, group);\n }\n return [...byDocument.values()].map((rows) => {\n rows.sort(\n (a, b) =>\n b.accessEpoch - a.accessEpoch ||\n (a.containerId < b.containerId\n ? -1\n : a.containerId > b.containerId\n ? 1\n : 0),\n );\n const first = rows[0];\n if (!first) throw new Error(\"Empty discovery candidate group\");\n return {\n rows,\n input: {\n ...first,\n listedContainerIds: [\n ...new Set(rows.flatMap((row) => row.listedContainerIds)),\n ].sort(),\n },\n };\n });\n}\n"]}
@@ -1,6 +1,6 @@
1
+ import { HEAD_LINK_SET_LOAD_CONCURRENCY, HEAD_LINK_SET_LOADS_PER_RUN, } from "../tombstones/documentTombstoneEvidence.js";
1
2
  import { groupPendingDocumentDiscoveries } from "./documentDiscoveryCandidates.js";
2
3
  import { documentHeadMatchesOrganization } from "./documentHeadScope.js";
3
- import { HEAD_LINK_SET_LOAD_CONCURRENCY, HEAD_LINK_SET_LOADS_PER_RUN, } from "./documentTombstoneEvidence.js";
4
4
  async function verifyInput(input, loadHead, loadLocalEpoch, store, generation, organizationId) {
5
5
  const localEpoch = await loadLocalEpoch(input.documentId).catch(() => Number.MAX_SAFE_INTEGER);
6
6
  const cached = await store.loadHead(input.documentId, input.accessStateHash);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentDiscoveryEvidence.js","sourceRoot":"","sources":["documentDiscoveryEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DiscoveredDocumentInput } from \"../../../data/documents/documentSummary\";\nimport type {\n DiscoveredDocumentCandidate,\n DocumentDiscoveryEvidenceStore,\n} from \"../../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport type {\n DocumentHeadLinkSetLoader,\n LocalDocumentAccessEpochLoader,\n} from \"../tombstones/documentTombstoneEvidence\";\nimport {\n HEAD_LINK_SET_LOAD_CONCURRENCY,\n HEAD_LINK_SET_LOADS_PER_RUN,\n} from \"../tombstones/documentTombstoneEvidence\";\nimport { groupPendingDocumentDiscoveries } from \"./documentDiscoveryCandidates\";\nimport type { DiscoverContainerDocumentsOptions } from \"./documentDiscoveryTypes\";\nimport { documentHeadMatchesOrganization } from \"./documentHeadScope\";\n\nasync function verifyInput(\n input: DiscoveredDocumentCandidate,\n loadHead: DocumentHeadLinkSetLoader,\n loadLocalEpoch: LocalDocumentAccessEpochLoader,\n store: DocumentDiscoveryEvidenceStore,\n generation: number,\n organizationId: string | undefined,\n): Promise<DiscoveredDocumentInput | null | \"unavailable\"> {\n const localEpoch = await loadLocalEpoch(input.documentId).catch(\n () => Number.MAX_SAFE_INTEGER,\n );\n const cached = await store.loadHead(input.documentId, input.accessStateHash);\n const minimumEpoch = Math.max(localEpoch, input.accessEpoch);\n const head =\n cached && cached.accessEpoch >= minimumEpoch\n ? cached\n : await loadHead(\n input.documentId,\n input.accessEpoch >= localEpoch\n ? (input.accessStateHash ?? undefined)\n : undefined,\n );\n if (head === \"not-found\") return null;\n if (!head || head.accessEpoch < Math.max(localEpoch, input.accessEpoch))\n return \"unavailable\";\n if (!documentHeadMatchesOrganization(head, organizationId))\n return \"unavailable\";\n // A stale first lane must not hide a document present in another listed lane.\n const containerId = input.listedContainerIds.find((id) =>\n head.linkedContainerIds.includes(id),\n );\n if (!containerId) {\n // A same-epoch head can predate a link addition. Only the named head or\n // terminal signed purge evidence can settle a candidate without a retry.\n return head.accessEpoch > input.accessEpoch ||\n head.accessStateHash === input.accessStateHash ||\n (!head.accessStateHash && head.accessEpoch === Number.MAX_SAFE_INTEGER)\n ? null\n : \"unavailable\";\n }\n if (!head.accessStateHash) return \"unavailable\";\n if (!(await store.saveHead(input.documentId, head, generation)))\n return \"unavailable\";\n const { listedContainerIds: _listedContainerIds, ...document } = input;\n return {\n ...document,\n containerId,\n accessEpoch: head.accessEpoch,\n accessStateHash: head.accessStateHash,\n linkedContainerIds: head.linkedContainerIds,\n };\n}\n\n/**\n * Persist untrusted candidates before advancing listing watermarks. Each pass\n * checks a bounded batch; unavailable heads back off independently while verified\n * siblings and tombstones still settle. Acknowledgement follows local apply so\n * a crash cannot lose a candidate behind an already advanced listing watermark.\n */\nexport function createDiscoveredDocumentVerifier(\n organizationId: string | undefined,\n loadHead: DocumentHeadLinkSetLoader,\n loadLocalEpoch: LocalDocumentAccessEpochLoader,\n store: DocumentDiscoveryEvidenceStore,\n onPendingDiscovery?: ((delayMs: number) => void) | undefined,\n): DiscoverContainerDocumentsOptions[\"verifyDiscoveredDocuments\"] {\n return async (inputs, containerIds, generation, tombstones = []) => {\n const isCurrent = () => store.isCurrent(generation);\n const lanes = new Set(containerIds);\n const removed = tombstones.filter((row) => lanes.has(row.containerId));\n if (!(await store.stage(inputs, generation, removed)))\n return { inputs: [], isCurrent, commit: async () => true };\n const candidates = groupPendingDocumentDiscoveries(\n await store.pending(containerIds, HEAD_LINK_SET_LOADS_PER_RUN),\n );\n const verified = new Map<string, DiscoveredDocumentInput>();\n const settled: DiscoveredDocumentCandidate[] = [];\n let next = 0;\n const worker = async () => {\n while (next < candidates.length) {\n const group = candidates[next++];\n if (!group) break;\n const { input, rows } = group;\n const result = await verifyInput(\n input,\n loadHead,\n loadLocalEpoch,\n store,\n generation,\n organizationId,\n );\n if (result === \"unavailable\") {\n await Promise.all(rows.map((row) => store.defer(row, generation)));\n } else {\n if (result) verified.set(result.documentId, result);\n settled.push(...rows);\n }\n }\n };\n await Promise.all(\n Array.from(\n { length: Math.min(HEAD_LINK_SET_LOAD_CONCURRENCY, candidates.length) },\n worker,\n ),\n );\n return {\n inputs: [...verified.values()],\n isCurrent,\n commit: async () => {\n await store.acknowledge(settled, generation);\n const retryDelay = await store.retryDelay(containerIds);\n if (retryDelay !== null) onPendingDiscovery?.(retryDelay);\n return retryDelay === null;\n },\n };\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { uniqueSortedStrings } from "../../data/documents/shared/readers.js";
2
- import { maxEffectiveAccessLevel, normalizeEffectiveAccessLevel, } from "../../data/keying/accessLevel.js";
1
+ import { uniqueSortedStrings } from "../../../data/documents/shared/readers.js";
2
+ import { maxEffectiveAccessLevel, normalizeEffectiveAccessLevel, } from "../../../data/keying/accessLevel.js";
3
3
  function mergeDiscoveredDocumentInputs(current, next) {
4
4
  // A lane page carries a complete link set for its epoch. Combining an old
5
5
  // root page with a newer trash page must not manufacture a newer root link.