@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.
- package/client/containerContents/documentDiscovery.js +5 -5
- package/client/containerContents/documentDiscovery.js.map +1 -1
- package/client/containerContents/index.d.ts +7 -7
- package/client/containerContents/index.js +7 -7
- package/client/containerContents/index.js.map +1 -1
- package/client/containerContents/types.d.ts +6 -6
- package/client/containerContents/types.js.map +1 -1
- package/client/deviceFirst/index.js +2 -2
- package/client/deviceFirst/index.js.map +1 -1
- package/package.json +1 -1
- package/stores/container-contents/containerStatePersistence.js +1 -1
- package/stores/container-contents/documentRecovery.js +2 -2
- package/stores/container-contents/documentRecovery.js.map +1 -1
- package/stores/container-contents/documentWork.js.map +1 -1
- package/stores/container-contents/localRefresh.js +2 -2
- package/stores/container-contents/localRefresh.js.map +1 -1
- package/stores/container-contents/operations.js +2 -2
- package/stores/container-contents/operations.js.map +1 -1
- package/stores/container-contents/remoteContainerIngestion.js +1 -1
- package/stores/container-contents/remoteEventSync.js +1 -1
- package/stores/container-contents/remoteHydrationRequest.js +1 -1
- package/stores/container-contents/setContainerIconOperation.js +2 -2
- package/stores/container-contents/setContainerIconOperation.js.map +1 -1
- package/stores/container-contents/shareOperations.js +1 -1
- package/stores/container-contents/startupHydration.js +1 -1
- package/stores/container-contents/syncAgent.d.ts +2 -2
- package/stores/container-contents/syncAgentTypes.d.ts +1 -1
- package/stores/container-contents/syncLaneIteration.js +2 -2
- package/stores/container-contents/syncLaneIteration.js.map +1 -1
- package/stores/container-contents/systemContainerIcon.js +1 -1
- package/stores/container-contents/systemContainerIcon.js.map +1 -1
- package/workflows/container-contents/{documentAttributionRanges.d.ts → attribution/documentAttributionRanges.d.ts} +1 -1
- package/workflows/container-contents/{documentCharacterBlame.js → attribution/documentCharacterBlame.js} +3 -3
- package/workflows/container-contents/attribution/documentCharacterBlame.js.map +1 -0
- package/workflows/container-contents/{documentFieldBlame.js → attribution/documentFieldBlame.js} +4 -4
- package/workflows/container-contents/attribution/documentFieldBlame.js.map +1 -0
- package/workflows/container-contents/container-state/createIntentSync.js +1 -1
- package/workflows/container-contents/container-state/createIntentSync.js.map +1 -1
- package/workflows/container-contents/container-state/moveIntentSync.js +1 -1
- package/workflows/container-contents/container-state/moveIntentSync.js.map +1 -1
- package/workflows/container-contents/container-state/purgeTree.js +2 -2
- package/workflows/container-contents/container-state/purgeTree.js.map +1 -1
- package/workflows/container-contents/container-state/sharePersistence.js +2 -2
- package/workflows/container-contents/container-state/sharePersistence.js.map +1 -1
- package/workflows/container-contents/{containerDocumentListing.js → documentDiscovery/containerDocumentListing.js} +1 -1
- package/workflows/container-contents/{documentDiscoveryApply.js → documentDiscovery/documentDiscoveryApply.js} +3 -3
- package/workflows/container-contents/documentDiscovery/documentDiscoveryApply.js.map +1 -0
- package/workflows/container-contents/{documentDiscoveryCandidates.js.map → documentDiscovery/documentDiscoveryCandidates.js.map} +1 -1
- package/workflows/container-contents/{documentDiscoveryEvidence.js → documentDiscovery/documentDiscoveryEvidence.js} +1 -1
- package/workflows/container-contents/documentDiscovery/documentDiscoveryEvidence.js.map +1 -0
- package/workflows/container-contents/{documentDiscoveryInputs.js → documentDiscovery/documentDiscoveryInputs.js} +2 -2
- package/workflows/container-contents/documentDiscovery/documentDiscoveryInputs.js.map +1 -0
- package/workflows/container-contents/documentDiscovery/documentDiscoveryLanes.js.map +1 -0
- package/workflows/container-contents/{documentDiscoveryTypes.d.ts → documentDiscovery/documentDiscoveryTypes.d.ts} +4 -4
- package/workflows/container-contents/documentDiscovery/documentDiscoveryTypes.js.map +1 -0
- package/workflows/container-contents/{documentDiscovery.d.ts → documentDiscovery/index.d.ts} +1 -1
- package/workflows/container-contents/{documentDiscovery.js → documentDiscovery/index.js} +5 -5
- package/workflows/container-contents/documentDiscovery/index.js.map +1 -0
- package/workflows/container-contents/{availableDocumentLinkIntent.js → documentLinks/availableDocumentLinkIntent.js} +1 -1
- package/workflows/container-contents/documentLinks/availableDocumentLinkIntent.js.map +1 -0
- package/workflows/container-contents/{deferredDocumentLinks.js → documentLinks/deferredDocumentLinks.js} +1 -1
- package/workflows/container-contents/documentLinks/deferredDocumentLinks.js.map +1 -0
- package/workflows/container-contents/{documentLinkIntent.js → documentLinks/documentLinkIntent.js} +4 -4
- package/workflows/container-contents/documentLinks/documentLinkIntent.js.map +1 -0
- package/workflows/container-contents/documentLinks/documentLocalRelink.js.map +1 -0
- package/workflows/container-contents/{documentLinks.d.ts → documentLinks/index.d.ts} +5 -5
- package/workflows/container-contents/{documentLinks.js → documentLinks/index.js} +10 -10
- package/workflows/container-contents/documentLinks/index.js.map +1 -0
- package/workflows/container-contents/documentMove/documentMoveDeniedReplay.js.map +1 -0
- package/workflows/container-contents/{documentMoveFailure.js → documentMove/documentMoveFailure.js} +1 -1
- package/workflows/container-contents/documentMove/documentMoveFailure.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntent.js → documentMove/documentMoveIntent.js} +7 -7
- package/workflows/container-contents/documentMove/documentMoveIntent.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntentErrors.js → documentMove/documentMoveIntentErrors.js} +1 -1
- package/workflows/container-contents/documentMove/documentMoveIntentErrors.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntentSettlement.js → documentMove/documentMoveIntentSettlement.js} +4 -4
- package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntentSync.js → documentMove/documentMoveIntentSync.js} +7 -7
- package/workflows/container-contents/documentMove/documentMoveIntentSync.js.map +1 -0
- package/workflows/container-contents/{documentMoveVanishedRefresh.js → documentMove/documentMoveVanishedRefresh.js} +3 -3
- package/workflows/container-contents/documentMove/documentMoveVanishedRefresh.js.map +1 -0
- package/workflows/container-contents/{documentHydrationProbe.js → documentPriming/documentHydrationProbe.js} +4 -4
- package/workflows/container-contents/documentPriming/documentHydrationProbe.js.map +1 -0
- package/workflows/container-contents/documentPriming/documentRuntimeTargetSync.js.map +1 -0
- package/workflows/container-contents/{documentPriming.js → documentPriming/index.js} +5 -5
- package/workflows/container-contents/documentPriming/index.js.map +1 -0
- package/workflows/container-contents/{documentStructure.d.ts → documentQueries/documentStructure.d.ts} +1 -1
- package/workflows/container-contents/{documentStructure.js → documentQueries/documentStructure.js} +4 -4
- package/workflows/container-contents/documentQueries/documentStructure.js.map +1 -0
- package/workflows/container-contents/{documentStructureTypes.d.ts → documentQueries/documentStructureTypes.d.ts} +4 -4
- package/workflows/container-contents/documentQueries/documentStructureTypes.js.map +1 -0
- package/workflows/container-contents/{documentSubtreeQueries.js → documentQueries/documentSubtreeQueries.js} +5 -5
- package/workflows/container-contents/documentQueries/documentSubtreeQueries.js.map +1 -0
- package/workflows/container-contents/{documentQueries.d.ts → documentQueries/index.d.ts} +8 -8
- package/workflows/container-contents/{documentQueries.js → documentQueries/index.js} +13 -13
- package/workflows/container-contents/documentQueries/index.js.map +1 -0
- package/workflows/container-contents/{orphanedDocumentSql.js → documentQueries/orphanedDocumentSql.js} +1 -1
- package/workflows/container-contents/documentQueries/orphanedDocumentSql.js.map +1 -0
- package/workflows/container-contents/{pendingDownloads.d.ts → documentQueries/pendingDownloads.d.ts} +1 -1
- package/workflows/container-contents/{pendingDownloads.js → documentQueries/pendingDownloads.js} +3 -3
- package/workflows/container-contents/documentQueries/pendingDownloads.js.map +1 -0
- package/workflows/container-contents/documentQueries/sql.js +1 -1
- package/workflows/container-contents/documentQueries/sql.js.map +1 -1
- package/workflows/container-contents/index.d.ts +13 -13
- package/workflows/container-contents/index.js +11 -11
- package/workflows/container-contents/index.js.map +1 -1
- package/workflows/container-contents/{blobInfo.d.ts → info/blobInfo.d.ts} +1 -1
- package/workflows/container-contents/{blobInfo.js → info/blobInfo.js} +4 -4
- package/workflows/container-contents/info/blobInfo.js.map +1 -0
- package/workflows/container-contents/{blobInfoTypes.d.ts → info/blobInfoTypes.d.ts} +1 -1
- package/workflows/container-contents/info/blobInfoTypes.js.map +1 -0
- package/workflows/container-contents/{containerInfo.d.ts → info/containerInfo.d.ts} +4 -4
- package/workflows/container-contents/{containerInfo.js → info/containerInfo.js} +5 -5
- package/workflows/container-contents/info/containerInfo.js.map +1 -0
- package/workflows/container-contents/{documentInfo.d.ts → info/documentInfo.d.ts} +3 -3
- package/workflows/container-contents/{documentInfo.js → info/documentInfo.js} +11 -11
- package/workflows/container-contents/info/documentInfo.js.map +1 -0
- package/workflows/container-contents/{documentInfoTypes.d.ts → info/documentInfoTypes.d.ts} +3 -3
- package/workflows/container-contents/info/documentInfoTypes.js.map +1 -0
- package/workflows/container-contents/{metadata.d.ts → metadata/index.d.ts} +2 -2
- package/workflows/container-contents/{metadata.js → metadata/index.js} +5 -5
- package/workflows/container-contents/metadata/index.js.map +1 -0
- package/workflows/container-contents/{metadataEvents.d.ts → metadata/metadataEvents.d.ts} +1 -1
- package/workflows/container-contents/{metadataEvents.js → metadata/metadataEvents.js} +1 -1
- package/workflows/container-contents/metadata/metadataEvents.js.map +1 -0
- package/workflows/container-contents/{metadataIncomingUpdateIsolation.js → metadata/metadataIncomingUpdateIsolation.js} +5 -5
- package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -0
- package/workflows/container-contents/{metadataMutationPreparation.d.ts → metadata/metadataMutationPreparation.d.ts} +7 -7
- package/workflows/container-contents/{metadataMutationPreparation.js → metadata/metadataMutationPreparation.js} +5 -5
- package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -0
- package/workflows/container-contents/{metadataPersistence.d.ts → metadata/metadataPersistence.d.ts} +2 -2
- package/workflows/container-contents/{metadataPersistence.js → metadata/metadataPersistence.js} +4 -4
- package/workflows/container-contents/metadata/metadataPersistence.js.map +1 -0
- package/workflows/container-contents/{metadataPullContinuationInvalidation.js → metadata/metadataPullContinuationInvalidation.js} +4 -4
- package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js.map +1 -0
- package/workflows/container-contents/{metadataReadState.d.ts → metadata/metadataReadState.d.ts} +1 -1
- package/workflows/container-contents/metadata/metadataReadState.js.map +1 -0
- package/workflows/container-contents/{metadataRecord.js → metadata/metadataRecord.js} +2 -2
- package/workflows/container-contents/metadata/metadataRecord.js.map +1 -0
- package/workflows/container-contents/{metadataRemoteSync.d.ts → metadata/metadataRemoteSync.d.ts} +5 -5
- package/workflows/container-contents/{metadataRemoteSync.js → metadata/metadataRemoteSync.js} +3 -3
- package/workflows/container-contents/metadata/metadataRemoteSync.js.map +1 -0
- package/workflows/container-contents/{metadataStateInstallation.d.ts → metadata/metadataStateInstallation.d.ts} +1 -1
- package/workflows/container-contents/metadata/metadataStateInstallation.js.map +1 -0
- package/workflows/container-contents/{metadataStateIsolation.js → metadata/metadataStateIsolation.js} +3 -3
- package/workflows/container-contents/metadata/metadataStateIsolation.js.map +1 -0
- package/workflows/container-contents/{metadataSyncErrors.js → metadata/metadataSyncErrors.js} +3 -3
- package/workflows/container-contents/metadata/metadataSyncErrors.js.map +1 -0
- package/workflows/container-contents/{metadataSyncSettlement.d.ts → metadata/metadataSyncSettlement.d.ts} +2 -2
- package/workflows/container-contents/{metadataSyncSettlement.js → metadata/metadataSyncSettlement.js} +3 -3
- package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -0
- package/workflows/container-contents/{metadataTypes.d.ts → metadata/metadataTypes.d.ts} +5 -5
- package/workflows/container-contents/metadata/metadataTypes.js.map +1 -0
- package/workflows/container-contents/pendingWrites/aggregation.js.map +1 -1
- package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
- package/workflows/container-contents/{pendingWrites.d.ts → pendingWrites/index.d.ts} +1 -1
- package/workflows/container-contents/{pendingWrites.js → pendingWrites/index.js} +12 -12
- package/workflows/container-contents/pendingWrites/index.js.map +1 -0
- package/workflows/container-contents/projectionGeneration.js.map +1 -1
- package/workflows/container-contents/projectionView.js +1 -1
- package/workflows/container-contents/projectionView.js.map +1 -1
- package/workflows/container-contents/{folderRecovery.d.ts → recovery/folderRecovery.d.ts} +1 -1
- package/workflows/container-contents/{folderRecovery.js → recovery/folderRecovery.js} +4 -4
- package/workflows/container-contents/recovery/folderRecovery.js.map +1 -0
- package/workflows/container-contents/{staleRootRecovery.js → recovery/staleRootRecovery.js} +1 -1
- package/workflows/container-contents/recovery/staleRootRecovery.js.map +1 -0
- package/workflows/container-contents/remoteHydration/completeHydration.js +1 -1
- package/workflows/container-contents/remoteHydration/completeHydration.js.map +1 -1
- package/workflows/container-contents/remoteHydration/heldContainerRebind.js +1 -1
- package/workflows/container-contents/remoteHydration/heldContainerRebind.js.map +1 -1
- package/workflows/container-contents/{remoteHydration.d.ts → remoteHydration/index.d.ts} +2 -2
- package/workflows/container-contents/{remoteHydration.js → remoteHydration/index.js} +6 -6
- package/workflows/container-contents/remoteHydration/index.js.map +1 -0
- package/workflows/container-contents/{remoteContainerPageHydration.js → remoteHydration/remoteContainerPageHydration.js} +8 -8
- package/workflows/container-contents/remoteHydration/remoteContainerPageHydration.js.map +1 -0
- package/workflows/container-contents/{remoteContainerState.js → remoteHydration/remoteContainerState.js} +11 -11
- package/workflows/container-contents/remoteHydration/remoteContainerState.js.map +1 -0
- package/workflows/container-contents/remoteHydration/types.d.ts +1 -1
- package/workflows/container-contents/{documentPurge.d.ts → tombstones/documentPurge.d.ts} +6 -6
- package/workflows/container-contents/{documentPurge.js → tombstones/documentPurge.js} +6 -6
- package/workflows/container-contents/tombstones/documentPurge.js.map +1 -0
- package/workflows/container-contents/{documentTombstoneEvidence.js → tombstones/documentTombstoneEvidence.js} +9 -9
- package/workflows/container-contents/tombstones/documentTombstoneEvidence.js.map +1 -0
- package/workflows/container-contents/{documentTombstoneGate.js → tombstones/documentTombstoneGate.js} +1 -1
- package/workflows/container-contents/tombstones/documentTombstoneGate.js.map +1 -0
- package/workflows/container-contents/availableDocumentLinkIntent.js.map +0 -1
- package/workflows/container-contents/blobInfo.js.map +0 -1
- package/workflows/container-contents/blobInfoTypes.js.map +0 -1
- package/workflows/container-contents/containerInfo.js.map +0 -1
- package/workflows/container-contents/deferredDocumentLinks.js.map +0 -1
- package/workflows/container-contents/documentCharacterBlame.js.map +0 -1
- package/workflows/container-contents/documentDiscovery.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryApply.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryEvidence.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryInputs.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryLanes.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryTypes.js.map +0 -1
- package/workflows/container-contents/documentFieldBlame.js.map +0 -1
- package/workflows/container-contents/documentHydrationProbe.js.map +0 -1
- package/workflows/container-contents/documentInfo.js.map +0 -1
- package/workflows/container-contents/documentInfoTypes.js.map +0 -1
- package/workflows/container-contents/documentLinkIntent.js.map +0 -1
- package/workflows/container-contents/documentLinks.js.map +0 -1
- package/workflows/container-contents/documentLocalRelink.js.map +0 -1
- package/workflows/container-contents/documentMoveDeniedReplay.js.map +0 -1
- package/workflows/container-contents/documentMoveFailure.js.map +0 -1
- package/workflows/container-contents/documentMoveIntent.js.map +0 -1
- package/workflows/container-contents/documentMoveIntentErrors.js.map +0 -1
- package/workflows/container-contents/documentMoveIntentSettlement.js.map +0 -1
- package/workflows/container-contents/documentMoveIntentSync.js.map +0 -1
- package/workflows/container-contents/documentMoveVanishedRefresh.js.map +0 -1
- package/workflows/container-contents/documentPriming.js.map +0 -1
- package/workflows/container-contents/documentPurge.js.map +0 -1
- package/workflows/container-contents/documentQueries.js.map +0 -1
- package/workflows/container-contents/documentRuntimeTargetSync.js.map +0 -1
- package/workflows/container-contents/documentStructure.js.map +0 -1
- package/workflows/container-contents/documentStructureTypes.js.map +0 -1
- package/workflows/container-contents/documentSubtreeQueries.js.map +0 -1
- package/workflows/container-contents/documentTombstoneEvidence.js.map +0 -1
- package/workflows/container-contents/documentTombstoneGate.js.map +0 -1
- package/workflows/container-contents/folderRecovery.js.map +0 -1
- package/workflows/container-contents/metadata.js.map +0 -1
- package/workflows/container-contents/metadataEvents.js.map +0 -1
- package/workflows/container-contents/metadataIncomingUpdateIsolation.js.map +0 -1
- package/workflows/container-contents/metadataMutationPreparation.js.map +0 -1
- package/workflows/container-contents/metadataPersistence.js.map +0 -1
- package/workflows/container-contents/metadataPullContinuationInvalidation.js.map +0 -1
- package/workflows/container-contents/metadataReadState.js.map +0 -1
- package/workflows/container-contents/metadataRecord.js.map +0 -1
- package/workflows/container-contents/metadataRemoteSync.js.map +0 -1
- package/workflows/container-contents/metadataStateInstallation.js.map +0 -1
- package/workflows/container-contents/metadataStateIsolation.js.map +0 -1
- package/workflows/container-contents/metadataSyncErrors.js.map +0 -1
- package/workflows/container-contents/metadataSyncSettlement.js.map +0 -1
- package/workflows/container-contents/metadataTypes.js.map +0 -1
- package/workflows/container-contents/orphanedDocumentSql.js.map +0 -1
- package/workflows/container-contents/pendingDownloads.js.map +0 -1
- package/workflows/container-contents/pendingWrites.js.map +0 -1
- package/workflows/container-contents/remoteContainerPageHydration.js.map +0 -1
- package/workflows/container-contents/remoteContainerState.js.map +0 -1
- package/workflows/container-contents/remoteHydration.js.map +0 -1
- package/workflows/container-contents/staleRootRecovery.js.map +0 -1
- /package/workflows/container-contents/{documentAttributionRanges.js → attribution/documentAttributionRanges.js} +0 -0
- /package/workflows/container-contents/{documentAttributionRanges.js.map → attribution/documentAttributionRanges.js.map} +0 -0
- /package/workflows/container-contents/{containerDocumentListing.js.map → documentDiscovery/containerDocumentListing.js.map} +0 -0
- /package/workflows/container-contents/{documentDiscoveryCandidates.js → documentDiscovery/documentDiscoveryCandidates.js} +0 -0
- /package/workflows/container-contents/{documentDiscoveryLanes.js → documentDiscovery/documentDiscoveryLanes.js} +0 -0
- /package/workflows/container-contents/{documentDiscoveryTypes.js → documentDiscovery/documentDiscoveryTypes.js} +0 -0
- /package/workflows/container-contents/{documentHeadScope.js → documentDiscovery/documentHeadScope.js} +0 -0
- /package/workflows/container-contents/{documentHeadScope.js.map → documentDiscovery/documentHeadScope.js.map} +0 -0
- /package/workflows/container-contents/{documentLocalRelink.js → documentLinks/documentLocalRelink.js} +0 -0
- /package/workflows/container-contents/{documentMoveDeniedReplay.js → documentMove/documentMoveDeniedReplay.js} +0 -0
- /package/workflows/container-contents/{documentMoveUnlinkIds.js → documentMove/documentMoveUnlinkIds.js} +0 -0
- /package/workflows/container-contents/{documentMoveUnlinkIds.js.map → documentMove/documentMoveUnlinkIds.js.map} +0 -0
- /package/workflows/container-contents/{documentRuntimeTargetSync.js → documentPriming/documentRuntimeTargetSync.js} +0 -0
- /package/workflows/container-contents/{documentStructureTypes.js → documentQueries/documentStructureTypes.js} +0 -0
- /package/workflows/container-contents/{blobInfoRows.js → info/blobInfoRows.js} +0 -0
- /package/workflows/container-contents/{blobInfoRows.js.map → info/blobInfoRows.js.map} +0 -0
- /package/workflows/container-contents/{blobInfoTypes.js → info/blobInfoTypes.js} +0 -0
- /package/workflows/container-contents/{documentInfoTypes.js → info/documentInfoTypes.js} +0 -0
- /package/workflows/container-contents/{metadataReadState.js → metadata/metadataReadState.js} +0 -0
- /package/workflows/container-contents/{metadataStateInstallation.js → metadata/metadataStateInstallation.js} +0 -0
- /package/workflows/container-contents/{metadataSyncFollowup.js → metadata/metadataSyncFollowup.js} +0 -0
- /package/workflows/container-contents/{metadataSyncFollowup.js.map → metadata/metadataSyncFollowup.js.map} +0 -0
- /package/workflows/container-contents/{metadataSyncRegistrations.d.ts → metadata/metadataSyncRegistrations.d.ts} +0 -0
- /package/workflows/container-contents/{metadataSyncRegistrations.js → metadata/metadataSyncRegistrations.js} +0 -0
- /package/workflows/container-contents/{metadataSyncRegistrations.js.map → metadata/metadataSyncRegistrations.js.map} +0 -0
- /package/workflows/container-contents/{metadataTypes.js → metadata/metadataTypes.js} +0 -0
- /package/workflows/container-contents/{pendingWritesTypes.d.ts → pendingWrites/pendingWritesTypes.d.ts} +0 -0
- /package/workflows/container-contents/{pendingWritesTypes.js → pendingWrites/pendingWritesTypes.js} +0 -0
- /package/workflows/container-contents/{pendingWritesTypes.js.map → pendingWrites/pendingWritesTypes.js.map} +0 -0
- /package/workflows/container-contents/{remoteHydrationLog.js → remoteHydration/remoteHydrationLog.js} +0 -0
- /package/workflows/container-contents/{remoteHydrationLog.js.map → remoteHydration/remoteHydrationLog.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentDiscoveryInputs.js","sourceRoot":"","sources":["documentDiscoveryInputs.ts"],"names":[],"mappings":"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","sourcesContent":["import { uniqueSortedStrings } from \"../../../data/documents/shared/readers\";\nimport {\n maxEffectiveAccessLevel,\n normalizeEffectiveAccessLevel,\n} from \"../../../data/keying/accessLevel\";\nimport type { DiscoveredDocumentCandidate } from \"../../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport type {\n ContainerDocumentTombstone,\n ListedContainerDocument,\n ListedContainerDocuments,\n ListedContainerDocumentsLane,\n} from \"./documentDiscoveryTypes\";\n\nfunction mergeDiscoveredDocumentInputs(\n current: DiscoveredDocumentCandidate,\n next: DiscoveredDocumentCandidate,\n): DiscoveredDocumentCandidate {\n // A lane page carries a complete link set for its epoch. Combining an old\n // root page with a newer trash page must not manufacture a newer root link.\n if (next.accessEpoch !== current.accessEpoch) {\n return {\n ...(next.accessEpoch > current.accessEpoch ? next : current),\n listedContainerIds: uniqueSortedStrings([\n ...current.listedContainerIds,\n ...next.listedContainerIds,\n ]),\n };\n }\n const accessStateHash =\n next.accessEpoch >= current.accessEpoch\n ? next.accessStateHash\n : current.accessStateHash;\n\n return {\n accessEpoch: Math.max(current.accessEpoch, next.accessEpoch),\n ...(accessStateHash === undefined ? {} : { accessStateHash }),\n containerId: current.containerId,\n listedContainerIds: uniqueSortedStrings([\n ...current.listedContainerIds,\n ...next.listedContainerIds,\n ]),\n createdAt:\n current.createdAt.localeCompare(next.createdAt) <= 0\n ? current.createdAt\n : next.createdAt,\n documentId: current.documentId,\n effectiveAccessLevel: maxEffectiveAccessLevel(\n normalizeEffectiveAccessLevel(current.effectiveAccessLevel),\n normalizeEffectiveAccessLevel(next.effectiveAccessLevel),\n ),\n linkedContainerIds: uniqueSortedStrings([\n current.containerId,\n next.containerId,\n ...current.linkedContainerIds,\n ...next.linkedContainerIds,\n ]),\n };\n}\n\nexport function collectDiscoveredDocumentInputs(\n listedDocumentsByContainer: ReadonlyArray<ListedContainerDocumentsLane>,\n): DiscoveredDocumentCandidate[] {\n const discoveredDocumentInputsByDocumentId = new Map<\n string,\n DiscoveredDocumentCandidate\n >();\n\n for (const { containerId, listedDocuments } of listedDocumentsByContainer) {\n if (!listedDocuments) {\n continue;\n }\n\n for (const document of listedDocuments.items) {\n const discoveredDocumentInput: DiscoveredDocumentCandidate = {\n accessEpoch: document.currentAccessEpoch,\n accessStateHash: document.currentAccessStateHash,\n containerId,\n listedContainerIds: [containerId],\n createdAt: document.createdAt,\n documentId: document.id,\n effectiveAccessLevel: normalizeEffectiveAccessLevel(\n document.effectiveAccessLevel,\n ),\n linkedContainerIds: uniqueSortedStrings([\n containerId,\n ...document.linkedContainerIds,\n ]),\n };\n const currentDiscoveredDocumentCandidate =\n discoveredDocumentInputsByDocumentId.get(document.id);\n discoveredDocumentInputsByDocumentId.set(\n document.id,\n currentDiscoveredDocumentCandidate\n ? mergeDiscoveredDocumentInputs(\n currentDiscoveredDocumentCandidate,\n discoveredDocumentInput,\n )\n : discoveredDocumentInput,\n );\n }\n }\n\n return Array.from(discoveredDocumentInputsByDocumentId.values());\n}\n\nexport function getApplicableDocumentTombstones(\n listedDocuments: ListedContainerDocuments,\n): ContainerDocumentTombstone[] {\n const latestItemsByDocumentId = new Map<string, ListedContainerDocument>();\n for (const document of listedDocuments.items) {\n const existingDocument = latestItemsByDocumentId.get(document.id);\n if (\n !existingDocument ||\n existingDocument.updatedAt.localeCompare(document.updatedAt) < 0\n ) {\n latestItemsByDocumentId.set(document.id, document);\n }\n }\n\n return listedDocuments.tombstones.filter((tombstone) => {\n const item = latestItemsByDocumentId.get(tombstone.documentId);\n return (\n !item?.linkedContainerIds.includes(tombstone.containerId) ||\n item.updatedAt.localeCompare(tombstone.updatedAt) < 0\n );\n });\n}\n\nexport function collectApplicableDocumentTombstones(\n lanes: ReadonlyArray<ListedContainerDocumentsLane>,\n): ContainerDocumentTombstone[] {\n return lanes.flatMap(({ listedDocuments }) =>\n listedDocuments ? getApplicableDocumentTombstones(listedDocuments) : [],\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentDiscoveryLanes.js","sourceRoot":"","sources":["documentDiscoveryLanes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oCAAoC,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EACL,6BAA6B,GAE9B,MAAM,0BAA0B,CAAC;AA2BlC,KAAK,UAAU,eAAe,CAC5B,IAAoC,EACpC,UAAkB,EAClB,eAAgD;IAEhD,IAAI,CAAC;QACH,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,eAAe;gBACpB,CAAC,CAAC,MAAM,6BAA6B,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,CAAC;gBACxE,CAAC,CAAC,IAAI;SACT,CAAC;IACJ,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACvE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,KAOpD;IACC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,IAAI,MAAwE,CAAC;IAC7E,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,oCAAoC,CAAC;YAClD,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;YACzD,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;YAC5D,8BAA8B,EAAE,KAAK,CAAC,8BAA8B;SACrE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAC9B,CAAC,EAAE,WAAW,EAAE,EAAqC,EAAE,CAAC,CAAC;YACvD,WAAW;YACX,MAAM;YACN,MAAM,EAAE,UAAU;SACnB,CAAC,CACH,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,QAAQ;YAAE,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;QACjE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAwC,EAAE,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC,IAAI,EACJ,KAAK,CAAC,UAAU,EAChB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,CACrC,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { listContainerDocumentsFromWatermarks } from \"./containerDocumentListing\";\nimport {\n applyListedContainerDocuments,\n type ContainerDocumentDiscoveryLane,\n} from \"./documentDiscoveryApply\";\nimport type {\n ContainerDocumentLaneLister,\n DiscoverContainerDocumentsOptions,\n ListedContainerDocuments,\n} from \"./documentDiscoveryTypes\";\n\nexport type { ContainerDocumentDiscoveryLane } from \"./documentDiscoveryApply\";\n\nexport type ContainerDocumentDiscoveryOutcome =\n | {\n readonly containerId: string;\n readonly status: \"fulfilled\";\n /** `null` when the lane was not fully listed or nothing applied. */\n readonly value: ReadonlyArray<DocumentSummary> | null;\n }\n | {\n readonly containerId: string;\n readonly reason: unknown;\n readonly status: \"rejected\";\n };\n\n/** Lets a caller act on each lane before later lanes apply. */\nexport type ContainerDocumentDiscoveryOutcomeHandler = (\n outcome: ContainerDocumentDiscoveryOutcome,\n) => Promise<void>;\n\nasync function applyListedLane(\n lane: ContainerDocumentDiscoveryLane,\n generation: number,\n listedDocuments: ListedContainerDocuments | null,\n): Promise<ContainerDocumentDiscoveryOutcome> {\n try {\n return {\n containerId: lane.containerId,\n status: \"fulfilled\",\n value: listedDocuments\n ? await applyListedContainerDocuments(lane, generation, listedDocuments)\n : null,\n };\n } catch (reason) {\n return { containerId: lane.containerId, reason, status: \"rejected\" };\n }\n}\n\n/**\n * Discovers several containers with one batched listing, then verifies and\n * applies each lane on its own, in order. The generation must be captured\n * before any lane's scope was read, exactly as for a single discovery: every\n * listing in the batch starts after it, so a reset in between still cancels\n * the batch. One lane's failure never blocks applying the others.\n */\nexport async function discoverContainerDocumentLanes(input: {\n readonly generation: number;\n readonly lanes: ReadonlyArray<ContainerDocumentDiscoveryLane>;\n readonly listContainerDocumentLanes: ContainerDocumentLaneLister;\n readonly loadContainerDocumentWatermark: DiscoverContainerDocumentsOptions[\"loadContainerDocumentWatermark\"];\n /** Awaited after each lane settles, before the next lane applies. */\n readonly onOutcome?: ContainerDocumentDiscoveryOutcomeHandler | undefined;\n}): Promise<ReadonlyArray<ContainerDocumentDiscoveryOutcome>> {\n if (input.lanes.length === 0) return [];\n let listed: Awaited<ReturnType<typeof listContainerDocumentsFromWatermarks>>;\n try {\n listed = await listContainerDocumentsFromWatermarks({\n containerIds: input.lanes.map((lane) => lane.containerId),\n listContainerDocumentLanes: input.listContainerDocumentLanes,\n loadContainerDocumentWatermark: input.loadContainerDocumentWatermark,\n });\n } catch (reason) {\n const rejected = input.lanes.map(\n ({ containerId }): ContainerDocumentDiscoveryOutcome => ({\n containerId,\n reason,\n status: \"rejected\",\n }),\n );\n for (const outcome of rejected) await input.onOutcome?.(outcome);\n return rejected;\n }\n\n const outcomes: ContainerDocumentDiscoveryOutcome[] = [];\n for (const lane of input.lanes) {\n const outcome = await applyListedLane(\n lane,\n input.generation,\n listed.get(lane.containerId) ?? null,\n );\n outcomes.push(outcome);\n await input.onOutcome?.(outcome);\n }\n return outcomes;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ListContainerDocumentLanesRequest, ListContainerParentLanesRequest } from "
|
|
2
|
-
import type { EffectiveAccessLevel, ReferencedPrincipalStateResponse, SyncWatermark } from "
|
|
3
|
-
import type { DiscoveredDocumentInput, DocumentSummary } from "
|
|
4
|
-
import type { DiscoveredDocumentCandidate } from "
|
|
1
|
+
import type { ListContainerDocumentLanesRequest, ListContainerParentLanesRequest } from "../../../internal/validators/request/index.js";
|
|
2
|
+
import type { EffectiveAccessLevel, ReferencedPrincipalStateResponse, SyncWatermark } from "../../../internal/validators/response/index.js";
|
|
3
|
+
import type { DiscoveredDocumentInput, DocumentSummary } from "../../../data/documents/documentSummary.js";
|
|
4
|
+
import type { DiscoveredDocumentCandidate } from "../../../data/persistence/documents/documentDiscoveryEvidencePersistence.js";
|
|
5
5
|
export interface ListedContainerDocument {
|
|
6
6
|
createdAt: string;
|
|
7
7
|
currentAccessEpoch: number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentDiscoveryTypes.js","sourceRoot":"","sources":["documentDiscoveryTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ListContainerDocumentLanesRequest,\n ListContainerParentLanesRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n EffectiveAccessLevel,\n ReferencedPrincipalStateResponse,\n SyncWatermark,\n} from \"@tearleads/validators/response\";\nimport type {\n DiscoveredDocumentInput,\n DocumentSummary,\n} from \"../../../data/documents/documentSummary\";\nimport type { DiscoveredDocumentCandidate } from \"../../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\n\nexport interface ListedContainerDocument {\n createdAt: string;\n currentAccessEpoch: number;\n currentAccessStateHash: string;\n effectiveAccessLevel?: EffectiveAccessLevel | undefined;\n id: string;\n linkedContainerIds: string[];\n referencedPrincipals: ReferencedPrincipalStateResponse[];\n updatedAt: string;\n}\n\nexport interface ListContainerDocumentsResponse {\n hasMore: boolean;\n items: ListedContainerDocument[];\n nextWatermark: SyncWatermark | null;\n tombstones: ReadonlyArray<{\n containerId: string;\n documentId: string;\n updatedAt: string;\n }>;\n}\n\nexport interface ListedContainer {\n id: string;\n}\n\nexport interface ListContainersResponse {\n hasMore: boolean;\n items: ListedContainer[];\n nextWatermark: SyncWatermark | null;\n}\n\nexport interface ListContainerParentLanesResponse {\n results: ReadonlyArray<{\n laneId: string;\n page: ListContainersResponse;\n }>;\n}\n\nexport type ContainerDocumentLaneResult =\n | { readonly laneId: string; readonly page: ListContainerDocumentsResponse }\n | {\n readonly failure: { readonly code?: string | undefined };\n readonly laneId: string;\n };\n\nexport interface ContainerDocumentDiscoveryApi {\n readonly listContainerDocumentLanes: (\n input: ListContainerDocumentLanesRequest,\n options?: { readonly reportErrors?: boolean | undefined },\n ) => Promise<{\n readonly results: ReadonlyArray<ContainerDocumentLaneResult>;\n } | null>;\n readonly listContainerParentLanes: (\n input: ListContainerParentLanesRequest,\n ) => Promise<ListContainerParentLanesResponse | null>;\n}\n\n/**\n * One page per lane, aligned with the requested lanes: `null` for a lane the\n * server rejected, or `null` overall when the request itself failed.\n */\nexport type ContainerDocumentLaneLister = (\n lanes: ReadonlyArray<{\n readonly containerId: string;\n readonly watermark: SyncWatermark | null;\n }>,\n) => Promise<ReadonlyArray<ListContainerDocumentsResponse | null> | null>;\n\nexport interface DocumentLinkInput {\n accessEpoch?: number | undefined;\n containerIds: ReadonlyArray<string>;\n documentId: string;\n}\n\nexport type ContainerDocumentTombstone =\n ListContainerDocumentsResponse[\"tombstones\"][number];\n\nexport interface VerifiedContainerDocumentTombstone\n extends ContainerDocumentTombstone {\n /** The verified head's link-set epoch, not below the local document epoch. */\n readonly accessEpoch: number;\n /** The verified head link set; it omits `containerId`. */\n readonly linkedContainerIds: ReadonlyArray<string>;\n}\n\n/**\n * What the document's signed head says about a listing tombstone.\n * - `verified`: the verified head link set omits the container; apply.\n * - `refuted`: the verified head still links the container; keep visible and retry.\n * - `unverified`: no verified head is available; hold, hide, retry later.\n * - `deferred`: not attempted this run (the per-run head-load cap); hold\n * without counting an attempt, so the retry backoff does not grow.\n */\nexport type ContainerDocumentTombstoneVerdict =\n | {\n readonly kind: \"verified\";\n readonly tombstone: VerifiedContainerDocumentTombstone;\n }\n | {\n readonly kind: \"refuted\";\n /** The verified head link set, which contains the container. */\n readonly linkedContainerIds: ReadonlyArray<string>;\n readonly tombstone: ContainerDocumentTombstone;\n }\n | {\n readonly kind: \"unverified\";\n readonly tombstone: ContainerDocumentTombstone;\n }\n | {\n readonly kind: \"deferred\";\n readonly tombstone: ContainerDocumentTombstone;\n };\n\nexport interface HeldContainerDocumentTombstoneInput\n extends ContainerDocumentTombstone {\n /** Held without a verification attempt; the backoff does not advance. */\n readonly deferred?: boolean | undefined;\n /** A verified head still links it; retry the tombstone while keeping it visible. */\n readonly refuted?: boolean | undefined;\n}\n\nexport type ContainerDocumentTombstoneVerifier = (\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n) => Promise<ReadonlyArray<ContainerDocumentTombstoneVerdict>>;\n\nexport type ContainerDocumentPlacement = Pick<\n ContainerDocumentTombstone,\n \"containerId\" | \"documentId\"\n>;\n\nexport interface ContainerDocumentTombstoneHoldStore {\n holdContainerDocumentTombstones: (\n tombstones: ReadonlyArray<HeldContainerDocumentTombstoneInput>,\n ) => Promise<void>;\n /** Held tombstones on these containers that are due for another attempt. */\n listHeldContainerDocumentTombstones: (\n containerIds: ReadonlyArray<string>,\n ) => Promise<ReadonlyArray<ContainerDocumentTombstone>>;\n /** The subset of placements that exist locally (link row or primary). */\n listKnownContainerDocumentPlacements: (\n placements: ReadonlyArray<ContainerDocumentPlacement>,\n ) => Promise<ReadonlyArray<ContainerDocumentPlacement>>;\n refuteContainerDocumentTombstoneHolds: (\n placements: ReadonlyArray<ContainerDocumentPlacement>,\n ) => Promise<void>;\n}\n\nexport interface DiscoverContainerDocumentsOptions\n extends ContainerDocumentTombstoneHoldStore {\n applyContainerDocumentTombstones: (\n tombstones: ReadonlyArray<VerifiedContainerDocumentTombstone>,\n ) => Promise<ReadonlyArray<DocumentSummary>>;\n verifyContainerDocumentTombstones: ContainerDocumentTombstoneVerifier;\n /** Allocate durable local order before fetching a listing. */\n beginDocumentDiscovery: () => Promise<number>;\n /** Persist pending candidates and return only signed placements. */\n verifyDiscoveredDocuments: (\n inputs: ReadonlyArray<DiscoveredDocumentCandidate>,\n containerIds: ReadonlyArray<string>,\n generation: number,\n tombstones?: ReadonlyArray<ContainerDocumentTombstone>,\n ) => Promise<{\n inputs: ReadonlyArray<DiscoveredDocumentInput>;\n /** False once a remote trust reset cancels this listing pass. */\n isCurrent: () => Promise<boolean>;\n /** Acknowledge only after local apply; true means no pending candidates remain. */\n commit: () => Promise<boolean>;\n }>;\n cacheReferencedPrincipalPolicies?: (\n references: ReadonlyArray<ReferencedPrincipalStateResponse>,\n ) => Promise<void>;\n containerId: string;\n /** Completed unwatermarked listing, published only after local apply succeeds. */\n onFullListing?: ((documentIds: ReadonlyArray<string>) => void) | undefined;\n loadContainerDocumentWatermark: (\n containerId: string,\n ) => Promise<SyncWatermark | null>;\n listContainerDocumentLanes: ContainerDocumentLaneLister;\n replaceDocumentLinksBatch: (\n inputs: ReadonlyArray<DocumentLinkInput>,\n ) => Promise<void>;\n saveContainerDocumentWatermark: (\n containerId: string,\n watermark: SyncWatermark,\n ) => Promise<void>;\n upsertDiscoveredDocuments: (\n inputs: ReadonlyArray<DiscoveredDocumentInput>,\n ) => Promise<ReadonlyArray<DocumentSummary>>;\n}\n\nexport interface ListedContainerDocuments {\n isFullListing: boolean;\n items: ListedContainerDocument[];\n nextWatermark: SyncWatermark | null;\n tombstones: ContainerDocumentTombstone[];\n}\n\nexport interface ContainerParentDiscoveryLane {\n parentId: string | null;\n watermark: SyncWatermark | null;\n}\n\nexport interface ListedContainerDocumentsLane {\n containerId: string;\n listedDocuments: ListedContainerDocuments | null;\n}\n\nexport interface DiscoverAllContainerDocumentsOptions\n extends Omit<DiscoverContainerDocumentsOptions, \"containerId\"> {\n containerIds: ReadonlyArray<string>;\n}\n\nexport interface RefreshAllContainerDocumentsOptions\n extends Omit<DiscoverAllContainerDocumentsOptions, \"containerIds\"> {\n listContainerParentLanes: ContainerDocumentDiscoveryApi[\"listContainerParentLanes\"];\n}\n\nexport interface RefreshAllContainerDocumentsFromApiOptions\n extends Omit<\n RefreshAllContainerDocumentsOptions,\n \"listContainerDocumentLanes\" | \"listContainerParentLanes\"\n > {\n readonly apiClient: Pick<\n ContainerDocumentDiscoveryApi,\n \"listContainerDocumentLanes\" | \"listContainerParentLanes\"\n >;\n}\n"]}
|
package/workflows/container-contents/{documentDiscovery.d.ts → documentDiscovery/index.d.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DocumentSummary } from "
|
|
1
|
+
import type { DocumentSummary } from "../../../data/documents/documentSummary.js";
|
|
2
2
|
import type { ContainerDocumentDiscoveryApi, DiscoverAllContainerDocumentsOptions, DiscoverContainerDocumentsOptions, RefreshAllContainerDocumentsFromApiOptions } from "./documentDiscoveryTypes.js";
|
|
3
3
|
export type { RefreshAllContainerDocumentsFromApiOptions } from "./documentDiscoveryTypes.js";
|
|
4
4
|
export declare function hasUndiscoveredDocumentUpdateEvent(events: ReadonlyArray<unknown>, knownDocumentIds: ReadonlySet<string>): boolean;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { isDocumentUpdateCreatedEvent } from "
|
|
2
|
-
import { dedupeReferencedPrincipalStates } from "
|
|
1
|
+
import { isDocumentUpdateCreatedEvent } from "../../../data/documents/documentSync.js";
|
|
2
|
+
import { dedupeReferencedPrincipalStates } from "../../../data/keyingProjectionVerification/principalPolicyCache.js";
|
|
3
|
+
import { withoutDeferredDocumentLinks } from "../documentLinks/deferredDocumentLinks.js";
|
|
4
|
+
import { settleContainerDocumentTombstones } from "../tombstones/documentTombstoneGate.js";
|
|
3
5
|
import { listContainerDocumentLanesFromApi, listContainerDocumentsFromWatermarks, } from "./containerDocumentListing.js";
|
|
4
|
-
import { withoutDeferredDocumentLinks } from "./deferredDocumentLinks.js";
|
|
5
6
|
import { saveAppliedContainerDocumentWatermark } from "./documentDiscoveryApply.js";
|
|
6
7
|
import { collectApplicableDocumentTombstones, collectDiscoveredDocumentInputs, } from "./documentDiscoveryInputs.js";
|
|
7
8
|
import { discoverContainerDocumentLanes } from "./documentDiscoveryLanes.js";
|
|
8
|
-
import { settleContainerDocumentTombstones } from "./documentTombstoneGate.js";
|
|
9
9
|
const CONTAINER_PARENT_DISCOVERY_BATCH_SIZE = 4;
|
|
10
10
|
async function listContainerParentLaneBatch(listContainerParentLanes, requestedLanes) {
|
|
11
11
|
const response = await listContainerParentLanes({
|
|
@@ -180,4 +180,4 @@ export function refreshAllContainerDocumentsFromApi({ apiClient, ...input }) {
|
|
|
180
180
|
listContainerParentLanes: (input) => apiClient.listContainerParentLanes(input),
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
|
-
//# sourceMappingURL=
|
|
183
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { isDocumentUpdateCreatedEvent } from \"../../../data/documents/documentSync\";\nimport { dedupeReferencedPrincipalStates } from \"../../../data/keyingProjectionVerification/principalPolicyCache\";\nimport { withoutDeferredDocumentLinks } from \"../documentLinks/deferredDocumentLinks\";\nimport { settleContainerDocumentTombstones } from \"../tombstones/documentTombstoneGate\";\nimport {\n listContainerDocumentLanesFromApi,\n listContainerDocumentsFromWatermarks,\n} from \"./containerDocumentListing\";\nimport { saveAppliedContainerDocumentWatermark } from \"./documentDiscoveryApply\";\nimport {\n collectApplicableDocumentTombstones,\n collectDiscoveredDocumentInputs,\n} from \"./documentDiscoveryInputs\";\nimport { discoverContainerDocumentLanes } from \"./documentDiscoveryLanes\";\nimport type {\n ContainerDocumentDiscoveryApi,\n ContainerParentDiscoveryLane,\n DiscoverAllContainerDocumentsOptions,\n DiscoverContainerDocumentsOptions,\n ListedContainerDocumentsLane,\n RefreshAllContainerDocumentsFromApiOptions,\n RefreshAllContainerDocumentsOptions,\n} from \"./documentDiscoveryTypes\";\n\nexport type { RefreshAllContainerDocumentsFromApiOptions } from \"./documentDiscoveryTypes\";\n\nconst CONTAINER_PARENT_DISCOVERY_BATCH_SIZE = 4;\n\ntype ContainerParentLaneRequest = Parameters<\n ContainerDocumentDiscoveryApi[\"listContainerParentLanes\"]\n>[0][\"lanes\"][number];\n\ninterface RequestedContainerParentLane {\n lane: ContainerParentDiscoveryLane;\n request: ContainerParentLaneRequest;\n}\n\nasync function listContainerParentLaneBatch(\n listContainerParentLanes: ContainerDocumentDiscoveryApi[\"listContainerParentLanes\"],\n requestedLanes: ReadonlyArray<RequestedContainerParentLane>,\n) {\n const response = await listContainerParentLanes({\n lanes: requestedLanes.map(({ request }) => request),\n });\n if (!response || response.results.length !== requestedLanes.length) {\n return null;\n }\n\n const requestedLaneIds = new Set(\n requestedLanes.map(({ request }) => request.laneId),\n );\n const pagesByLaneId = new Map<\n string,\n (typeof response.results)[number][\"page\"]\n >();\n for (const result of response.results) {\n if (\n !requestedLaneIds.has(result.laneId) ||\n pagesByLaneId.has(result.laneId)\n ) {\n return null;\n }\n pagesByLaneId.set(result.laneId, result.page);\n }\n\n return requestedLanes.map(({ lane, request }) => ({\n lane,\n response: pagesByLaneId.get(request.laneId),\n }));\n}\n\nfunction collectRemoteContainerIds(\n items: ReadonlyArray<{ id: string }>,\n seenContainerIds: Set<string>,\n containerIds: string[],\n): ReadonlyArray<string> {\n for (const { id } of items) {\n if (!seenContainerIds.has(id)) {\n seenContainerIds.add(id);\n containerIds.push(id);\n }\n }\n\n return items.map(({ id }) => id);\n}\n\nexport function hasUndiscoveredDocumentUpdateEvent(\n events: ReadonlyArray<unknown>,\n knownDocumentIds: ReadonlySet<string>,\n): boolean {\n return events.some(\n (event) =>\n isDocumentUpdateCreatedEvent(event) &&\n !knownDocumentIds.has(event.documentId),\n );\n}\n\nexport async function listAllRemoteContainerIds(\n listContainerParentLanes: ContainerDocumentDiscoveryApi[\"listContainerParentLanes\"],\n): Promise<ReadonlyArray<string> | null> {\n const containerIds: string[] = [];\n const queuedParentIds = new Set<string | null>();\n const seenContainerIds = new Set<string>();\n const lanes: ContainerParentDiscoveryLane[] = [];\n let nextLaneId = 0;\n const queueParentLane = (parentId: string | null) => {\n if (queuedParentIds.has(parentId)) {\n return;\n }\n\n queuedParentIds.add(parentId);\n lanes.push({ parentId, watermark: null });\n };\n\n queueParentLane(null);\n\n while (lanes.length > 0) {\n const laneBatch = lanes.splice(0, CONTAINER_PARENT_DISCOVERY_BATCH_SIZE);\n const requestedLanes = laneBatch.map((lane) => ({\n lane,\n request: {\n laneId: `container-parent-${nextLaneId++}`,\n parentId: lane.parentId,\n watermark: lane.watermark,\n },\n }));\n const listedLanes = await listContainerParentLaneBatch(\n listContainerParentLanes,\n requestedLanes,\n );\n if (!listedLanes) {\n return null;\n }\n const continuationLanes: ContainerParentDiscoveryLane[] = [];\n\n for (const { lane, response } of listedLanes) {\n if (!response) {\n return null;\n }\n\n for (const containerId of collectRemoteContainerIds(\n response.items,\n seenContainerIds,\n containerIds,\n )) {\n queueParentLane(containerId);\n }\n\n if (response.hasMore) {\n if (!response.nextWatermark) {\n return null;\n }\n continuationLanes.push({\n parentId: lane.parentId,\n watermark: response.nextWatermark,\n });\n }\n }\n\n lanes.unshift(...continuationLanes);\n }\n\n return containerIds;\n}\n\nexport function listAllRemoteContainerIdsFromApi(\n apiClient: Pick<ContainerDocumentDiscoveryApi, \"listContainerParentLanes\">,\n): Promise<ReadonlyArray<string> | null> {\n return listAllRemoteContainerIds((input) =>\n apiClient.listContainerParentLanes(input),\n );\n}\n\nexport async function discoverContainerDocuments({\n beginDocumentDiscovery,\n listContainerDocumentLanes,\n loadContainerDocumentWatermark,\n ...lane\n}: DiscoverContainerDocumentsOptions): Promise<ReadonlyArray<DocumentSummary> | null> {\n const [outcome] = await discoverContainerDocumentLanes({\n generation: await beginDocumentDiscovery(),\n lanes: [lane],\n listContainerDocumentLanes,\n loadContainerDocumentWatermark,\n });\n if (outcome?.status === \"rejected\") throw outcome.reason;\n return outcome?.value ?? null;\n}\n\nexport function discoverContainerDocumentsFromApi({\n apiClient,\n ...input\n}: Omit<DiscoverContainerDocumentsOptions, \"listContainerDocumentLanes\"> & {\n readonly apiClient: Pick<\n ContainerDocumentDiscoveryApi,\n \"listContainerDocumentLanes\"\n >;\n}): Promise<ReadonlyArray<DocumentSummary> | null> {\n return discoverContainerDocuments({\n ...input,\n listContainerDocumentLanes: (lanes) =>\n listContainerDocumentLanesFromApi(apiClient, lanes),\n });\n}\n\nasync function listDiscoveryLanes(\n input: Parameters<typeof listContainerDocumentsFromWatermarks>[0],\n): Promise<ListedContainerDocumentsLane[]> {\n const listed = await listContainerDocumentsFromWatermarks(input);\n return input.containerIds.map((containerId) => ({\n containerId,\n listedDocuments: listed.get(containerId) ?? null,\n }));\n}\n\nexport async function discoverAllContainerDocuments(\n options: DiscoverAllContainerDocumentsOptions,\n): Promise<ReadonlyArray<DocumentSummary> | null> {\n const {\n cacheReferencedPrincipalPolicies,\n containerIds,\n loadContainerDocumentWatermark,\n listContainerDocumentLanes,\n replaceDocumentLinksBatch,\n saveContainerDocumentWatermark,\n upsertDiscoveredDocuments,\n } = options;\n const uniqueContainerIds = Array.from(new Set(containerIds)).filter(\n (containerId): containerId is string =>\n typeof containerId === \"string\" && containerId.length > 0,\n );\n const generation = await options.beginDocumentDiscovery();\n const listedDocumentsByContainer = await listDiscoveryLanes({\n containerIds: uniqueContainerIds,\n listContainerDocumentLanes,\n loadContainerDocumentWatermark,\n });\n await cacheReferencedPrincipalPolicies?.(\n dedupeReferencedPrincipalStates(\n listedDocumentsByContainer.flatMap(\n ({ listedDocuments }) =>\n listedDocuments?.items.flatMap(\n (document) => document.referencedPrincipals,\n ) ?? [],\n ),\n ),\n );\n const verification = await options.verifyDiscoveredDocuments(\n collectDiscoveredDocumentInputs(listedDocumentsByContainer),\n uniqueContainerIds,\n generation,\n collectApplicableDocumentTombstones(listedDocumentsByContainer),\n );\n if (!(await verification.isCurrent())) return null;\n const discoveredDocumentInputs = verification.inputs;\n const discoveredDocuments =\n discoveredDocumentInputs.length === 0\n ? []\n : await upsertDiscoveredDocuments(discoveredDocumentInputs);\n\n if (discoveredDocumentInputs.length > 0) {\n await replaceDocumentLinksBatch(\n await withoutDeferredDocumentLinks(\n discoveredDocumentInputs.map((input) => ({\n documentId: input.documentId,\n accessEpoch: input.accessEpoch,\n containerIds: input.linkedContainerIds,\n })),\n discoveredDocuments,\n ),\n );\n }\n\n const tombstoneDocumentSummaries = await settleContainerDocumentTombstones({\n containerIds: listedDocumentsByContainer.flatMap(\n ({ containerId, listedDocuments }) =>\n listedDocuments ? [containerId] : [],\n ),\n store: options,\n tombstones: collectApplicableDocumentTombstones(listedDocumentsByContainer),\n });\n\n const complete = await verification.commit();\n if (!(await verification.isCurrent())) return null;\n\n await Promise.all(\n listedDocumentsByContainer.map(({ containerId, listedDocuments }) =>\n listedDocuments\n ? saveAppliedContainerDocumentWatermark({\n containerId,\n listedDocuments,\n saveContainerDocumentWatermark,\n })\n : undefined,\n ),\n );\n\n return !complete &&\n discoveredDocuments.length === 0 &&\n tombstoneDocumentSummaries.length === 0\n ? null\n : [...discoveredDocuments, ...tombstoneDocumentSummaries];\n}\n\nasync function refreshAllContainerDocuments({\n listContainerParentLanes,\n ...input\n}: RefreshAllContainerDocumentsOptions): Promise<ReadonlyArray<DocumentSummary> | null> {\n const containerIds = await listAllRemoteContainerIds(\n listContainerParentLanes,\n );\n if (!containerIds) {\n return null;\n }\n\n return discoverAllContainerDocuments({\n ...input,\n containerIds,\n });\n}\n\nexport function refreshAllContainerDocumentsFromApi({\n apiClient,\n ...input\n}: RefreshAllContainerDocumentsFromApiOptions): Promise<ReadonlyArray<DocumentSummary> | null> {\n return refreshAllContainerDocuments({\n ...input,\n listContainerDocumentLanes: (lanes) =>\n listContainerDocumentLanesFromApi(apiClient, lanes),\n listContainerParentLanes: (input) =>\n apiClient.listContainerParentLanes(input),\n });\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DOCUMENT_LINK_INTENT_TYPE, } from "
|
|
1
|
+
import { DOCUMENT_LINK_INTENT_TYPE, } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
2
2
|
/** Plan available additions without forgetting any part of the durable intent. */
|
|
3
3
|
export function availableDocumentLinkIntent(intent, hasContainer) {
|
|
4
4
|
if (intent.intentType !== DOCUMENT_LINK_INTENT_TYPE)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availableDocumentLinkIntent.js","sourceRoot":"","sources":["availableDocumentLinkIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAE1B,MAAM,4EAA4E,CAAC;AAEpF,kFAAkF;AAClF,MAAM,UAAU,2BAA2B,CACzC,MAAgC,EAChC,YAAqC;IAErC,IAAI,MAAM,CAAC,UAAU,KAAK,yBAAyB;QACjD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACrC,+EAA+E;IAC/E,4DAA4D;IAC5D,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC;IACvD,MAAM,iBAAiB,GAAG,YAAY,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAC9D,CAAC,CAAC,MAAM,CAAC,iBAAiB;QAC1B,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YACb,CAAC,MAAM,CAAC,iBAAiB,IAAI,YAAY,CAAC,MAAM,CAAC,iBAAiB,CAAC;gBACjE,CAAC,CAAC,MAAM,CAAC,iBAAiB;gBAC1B,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACpB,IACE,CAAC,iBAAiB;QAClB,CAAC,CAAC,QAAQ,IAAI,iBAAiB,KAAK,MAAM,CAAC,iBAAiB,CAAC;QAE7D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,OAAO;QACL,QAAQ;QACR,MAAM,EAAE;YACN,GAAG,MAAM;YACT,iBAAiB;YACjB,0BAA0B,EAAE,SAAS;YACrC,GAAG,CAAC,QAAQ;gBACV,CAAC,CAAC,EAAE,uBAAuB,EAAE,EAAE,EAAE,uBAAuB,EAAE,KAAK,EAAE;gBACjE,CAAC,CAAC,EAAE,CAAC;SACR;KACF,CAAC;AACJ,CAAC","sourcesContent":["import {\n DOCUMENT_LINK_INTENT_TYPE,\n type DocumentMoveIntentRecord,\n} from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\n\n/** Plan available additions without forgetting any part of the durable intent. */\nexport function availableDocumentLinkIntent(\n intent: DocumentMoveIntentRecord,\n hasContainer: (id: string) => boolean,\n): { intent: DocumentMoveIntentRecord; deferred: boolean } {\n if (intent.intentType !== DOCUMENT_LINK_INTENT_TYPE)\n return { intent, deferred: false };\n // For link intents the primary target is a routing hint, often the old source.\n // Only explicit additions can defer the requested removals.\n const requested = [...new Set(intent.additionalLinkContainerIds ?? [])];\n const available = requested.filter(hasContainer);\n const deferred = available.length !== requested.length;\n const targetContainerId = hasContainer(intent.targetContainerId)\n ? intent.targetContainerId\n : (available[0] ??\n (intent.sourceContainerId && hasContainer(intent.sourceContainerId)\n ? intent.sourceContainerId\n : undefined));\n if (\n !targetContainerId ||\n (!deferred && targetContainerId === intent.targetContainerId)\n )\n return { intent, deferred };\n return {\n deferred,\n intent: {\n ...intent,\n targetContainerId,\n additionalLinkContainerIds: available,\n ...(deferred\n ? { removedLinkContainerIds: [], replaceLinkedContainers: false }\n : {}),\n },\n };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deriveStableDocumentId } from "
|
|
1
|
+
import { deriveStableDocumentId } from "../../../data/documents/shared/stableDocumentId.js";
|
|
2
2
|
/** A deferred create keeps its intended links until its signed adoption verifies. */
|
|
3
3
|
export async function withoutDeferredDocumentLinks(links, summaries) {
|
|
4
4
|
const deferredIds = new Set(await Promise.all(summaries
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferredDocumentLinks.js","sourceRoot":"","sources":["deferredDocumentLinks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AAEzF,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAGhD,KAAmB,EACnB,SAAqC;IAErC,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,MAAM,OAAO,CAAC,GAAG,CACf,SAAS;SACN,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC;SAChD,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CACxD,CACF,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { deriveStableDocumentId } from \"../../../data/documents/shared/stableDocumentId\";\n\n/** A deferred create keeps its intended links until its signed adoption verifies. */\nexport async function withoutDeferredDocumentLinks<\n T extends { documentId: string; containerIds: readonly string[] },\n>(\n links: readonly T[],\n summaries: readonly DocumentSummary[],\n): Promise<readonly T[]> {\n const deferredIds = new Set(\n await Promise.all(\n summaries\n .filter((summary) => summary.documentId === null)\n .map((summary) => deriveStableDocumentId(summary.id)),\n ),\n );\n return links.filter((link) => !deferredIds.has(link.documentId));\n}\n"]}
|
package/workflows/container-contents/{documentLinkIntent.js → documentLinks/documentLinkIntent.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { uniqueSortedStrings } from "
|
|
2
|
-
import { sqlDocumentMoveIntentPersistence } from "
|
|
3
|
-
import { sqlDocumentContainerProjectionPersistence as links } from "
|
|
4
|
-
import { defaultDocumentsPersistence } from "
|
|
1
|
+
import { uniqueSortedStrings } from "../../../data/documents/shared/readers.js";
|
|
2
|
+
import { sqlDocumentMoveIntentPersistence } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
3
|
+
import { sqlDocumentContainerProjectionPersistence as links } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
4
|
+
import { defaultDocumentsPersistence } from "../../documents/index.js";
|
|
5
5
|
import { relinkContainerDocumentLocally } from "./documentLocalRelink.js";
|
|
6
6
|
export async function addDocumentLinkLocally(input) {
|
|
7
7
|
const { note, runtime, targetContainerId } = input;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentLinkIntent.js","sourceRoot":"","sources":["documentLinkIntent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { uniqueSortedStrings } from \"../../../data/documents/shared/readers\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentContainerProjectionPersistence as links } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { defaultDocumentsPersistence } from \"../../documents\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRuntime,\n SetLinkedContainerIdsForDocument,\n} from \"../documentQueries/documentStructureTypes\";\nimport { relinkContainerDocumentLocally } from \"./documentLocalRelink\";\n\nexport async function addDocumentLinkLocally<TRuntime>(input: {\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary & { documentId: string; containerId: string };\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<DocumentSummary | null> {\n const { note, runtime, targetContainerId } = input;\n const persisted = await defaultDocumentsPersistence.loadDocument(\n runtime.infra.execSql,\n note.id,\n );\n if (!persisted) return null;\n const intentId = crypto.randomUUID();\n let linkedContainerIds: readonly string[] = [];\n const linkedNote = await relinkContainerDocumentLocally({\n ...input,\n accessEpoch: persisted.accessEpoch,\n requestSync: false,\n targetContainerId: note.containerId,\n commitSideEffect: async (execSql) => {\n const currentLinks = await links.listLinkedContainerIds(\n execSql,\n note.documentId,\n );\n linkedContainerIds = uniqueSortedStrings([\n ...currentLinks,\n note.containerId,\n targetContainerId,\n ]);\n await sqlDocumentMoveIntentPersistence.enqueueLinkIntent(execSql, {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n sourceContainerId: note.containerId,\n targetContainerId,\n });\n await links.replaceDocumentLinks(\n execSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n });\n if (!linkedNote) return null;\n input.setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n input.scheduleSync?.();\n runtime.util.log(\n `Container contents: queued note ${note.id} link to ${targetContainerId}`,\n );\n return linkedNote;\n}\n\nexport async function removeDocumentLinkLocally<TRuntime>(\n input: Omit<\n Parameters<typeof addDocumentLinkLocally<TRuntime>>[0],\n \"targetContainerId\"\n > & { removedContainerId: string },\n): Promise<DocumentSummary | null> {\n const { note, runtime, removedContainerId } = input;\n const execSql = runtime.infra.execSql;\n const persisted = await defaultDocumentsPersistence.loadDocument(\n execSql,\n note.id,\n );\n if (!persisted) return null;\n const currentLinks = await links.listLinkedContainerIds(\n execSql,\n note.documentId,\n );\n const remaining = currentLinks.filter((id) => id !== removedContainerId);\n const nextContainerId = remaining.includes(note.containerId)\n ? note.containerId\n : remaining[0];\n if (!nextContainerId || !currentLinks.includes(removedContainerId))\n return null;\n const intentId = crypto.randomUUID();\n let linkedContainerIds: readonly string[] = [];\n const unlinkedNote = await relinkContainerDocumentLocally({\n ...input,\n accessEpoch: persisted.accessEpoch,\n requestSync: false,\n targetContainerId: nextContainerId,\n commitSideEffect: async (transactionExecSql) => {\n linkedContainerIds = (\n await links.listLinkedContainerIds(transactionExecSql, note.documentId)\n ).filter((id) => id !== removedContainerId);\n if (!linkedContainerIds.includes(nextContainerId))\n throw new Error(\"Document placement changed before unlink\");\n await sqlDocumentMoveIntentPersistence.enqueueUnlinkIntent(\n transactionExecSql,\n {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n removedContainerId,\n targetContainerId: nextContainerId,\n },\n );\n await links.replaceDocumentLinks(\n transactionExecSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n });\n if (!unlinkedNote) return null;\n input.setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n input.scheduleSync?.();\n return unlinkedNote;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentLocalRelink.js","sourceRoot":"","sources":["documentLocalRelink.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAW,MAW9D;IACC,MAAM,EACJ,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,WAAW,EACX,OAAO,EACP,iBAAiB,GAClB,GAAG,MAAM,CAAC;IAEX,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC;QACrD,WAAW;QACX,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;QAC7D,WAAW,EAAE,iBAAiB;QAC9B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,GAAG,WAAW;QACd,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,OAAO,EAAE,IAAI,CAAC,EAAE;KACjB,CAAC,CAAC;IACH,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,GAAG,CACd,4BAA4B,IAAI,CAAC,EAAE,oDAAoD,CACxF,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACxC,oBAAoB,CAAC,aAAa,CAChC,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAChD,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,oBAAoB,CAAC,WAAW,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRelinkInput,\n DocumentStructuralMutationRuntime,\n} from \"../documentQueries/documentStructureTypes\";\nimport type { RemoteDocumentPersistedState } from \"./index\";\n\nexport async function relinkContainerDocumentLocally<TRuntime>(params: {\n accessEpoch: number;\n commitSideEffect?: DocumentStructuralMutationRelinkInput[\"commitSideEffect\"];\n accessStateHash?: string | null | undefined;\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary;\n remoteState?: RemoteDocumentPersistedState | undefined;\n requestSync: boolean;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}) {\n const {\n accessEpoch,\n accessStateHash,\n currentDocumentStore,\n host,\n note,\n remoteState,\n requestSync,\n runtime,\n targetContainerId,\n } = params;\n\n const relinkedNote = await currentDocumentStore.relink({\n accessEpoch,\n ...(accessStateHash === undefined ? {} : { accessStateHash }),\n containerId: targetContainerId,\n commitSideEffect: params.commitSideEffect,\n ...remoteState,\n documentId: note.documentId,\n localId: note.id,\n });\n if (!relinkedNote) {\n runtime.util.log(\n `Container contents: note ${note.id} could not be relinked after a structural mutation`,\n );\n return null;\n }\n\n host.mergeDocumentSummary(relinkedNote);\n currentDocumentStore.updateRuntime(\n host.documentWorkflowRuntime(targetContainerId),\n );\n if (requestSync) {\n currentDocumentStore.requestSync();\n }\n return relinkedNote;\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ProjectionUserKeyResolver } from "
|
|
2
|
-
import type { ExecSql } from "
|
|
3
|
-
import { type DocumentLinkSetFailureHandler, type RelinkRemoteDocumentResult, relinkRemoteDocument } from "
|
|
4
|
-
import type { SubtreePurgeRoot } from "
|
|
5
|
-
import type { ContainerContentsWorkflowRuntime } from "
|
|
1
|
+
import type { ProjectionUserKeyResolver } from "../../../data/keyingProjectionVerification/index.js";
|
|
2
|
+
import type { ExecSql } from "../../../data/sqlite/sqlSchema.js";
|
|
3
|
+
import { type DocumentLinkSetFailureHandler, type RelinkRemoteDocumentResult, relinkRemoteDocument } from "../../documents/index.js";
|
|
4
|
+
import type { SubtreePurgeRoot } from "../../documents/subtreePurgeScope.js";
|
|
5
|
+
import type { ContainerContentsWorkflowRuntime } from "../runtime.js";
|
|
6
6
|
type ContainerDocumentLinkApi = Parameters<typeof relinkRemoteDocument>[0]["apiClient"];
|
|
7
7
|
type ContainerDocumentLinkOperation = Parameters<typeof relinkRemoteDocument>[0]["operation"];
|
|
8
8
|
type RemoteDocumentPersistedState = RelinkRemoteDocumentResult["persistedState"];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { assertDocumentWriterProjectionConsistent, readLinkedContainerIdsFromDocumentManifest, } from "
|
|
2
|
-
import { persistedDocumentCreateStateFromWriterProjection } from "
|
|
3
|
-
import { reportAndRethrowKeyingVerificationError } from "
|
|
4
|
-
import { sqlDocumentContainerProjectionPersistence } from "
|
|
5
|
-
import { errorMessage } from "
|
|
6
|
-
import { isDatabaseUnavailableError } from "
|
|
7
|
-
import { relinkRemoteDocument, resolveDocumentCreateAuthor, } from "
|
|
8
|
-
import { createRuntimePrincipalPolicyWarmer } from "
|
|
9
|
-
import { resolveContainerDocumentMoveUnlinkIds } from "
|
|
1
|
+
import { assertDocumentWriterProjectionConsistent, readLinkedContainerIdsFromDocumentManifest, } from "../../../data/documents/shared/projection.js";
|
|
2
|
+
import { persistedDocumentCreateStateFromWriterProjection } from "../../../data/documents/shared/responses.js";
|
|
3
|
+
import { reportAndRethrowKeyingVerificationError } from "../../../data/keyingProjectionVerification/error.js";
|
|
4
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
5
|
+
import { errorMessage } from "../../../data/shared/errorMessage.js";
|
|
6
|
+
import { isDatabaseUnavailableError } from "../../../data/sync/databaseUnavailable.js";
|
|
7
|
+
import { relinkRemoteDocument, resolveDocumentCreateAuthor, } from "../../documents/index.js";
|
|
8
|
+
import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
|
|
9
|
+
import { resolveContainerDocumentMoveUnlinkIds } from "../documentMove/documentMoveUnlinkIds.js";
|
|
10
10
|
// A cold-cache denial must keep its HTTP status: collapsing a 403 to null
|
|
11
11
|
// would leave an access-denied move routinely retriable instead of parking
|
|
12
12
|
// it for the access-restored signal (row 7).
|
|
@@ -261,4 +261,4 @@ async function unlinkMovedDocumentSources(input) {
|
|
|
261
261
|
}
|
|
262
262
|
return { failedUnlinkContainerIds, latestDocument, latestLinkedContainerIds };
|
|
263
263
|
}
|
|
264
|
-
//# sourceMappingURL=
|
|
264
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { VerifiedDocumentLinkSetManifest } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n assertDocumentWriterProjectionConsistent,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"../../../data/documents/shared/projection\";\nimport { persistedDocumentCreateStateFromWriterProjection } from \"../../../data/documents/shared/responses\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { isDatabaseUnavailableError } from \"../../../data/sync/databaseUnavailable\";\nimport {\n type DocumentLinkSetFailureHandler,\n type RelinkRemoteDocumentResult,\n relinkRemoteDocument,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport type { SubtreePurgeRoot } from \"../../documents/subtreePurgeScope\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport { resolveContainerDocumentMoveUnlinkIds } from \"../documentMove/documentMoveUnlinkIds\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\ntype ContainerDocumentLinkApi = Parameters<\n typeof relinkRemoteDocument\n>[0][\"apiClient\"];\ntype ContainerDocumentLinkOperation = Parameters<\n typeof relinkRemoteDocument\n>[0][\"operation\"];\ntype RemoteDocumentPersistedState =\n RelinkRemoteDocumentResult[\"persistedState\"];\n\n// A cold-cache denial must keep its HTTP status: collapsing a 403 to null\n// would leave an access-denied move routinely retriable instead of parking\n// it for the access-restored signal (row 7).\nasync function fetchMoveWriterProjection(input: {\n documentId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n runtime: ContainerDocumentLinkRuntime;\n}): Promise<Awaited<\n ReturnType<ContainerDocumentLinkApi[\"getDocumentWriterProjection\"]>\n> | null> {\n const { apiClient } = input.runtime;\n const result = await apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (result.ok) {\n return result.data;\n }\n result.report();\n input.onFailure?.({ message: result.message, status: result.status });\n return null;\n}\n\ninterface ContainerDocumentLinkRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n apiClient: ContainerDocumentLinkApi &\n Pick<\n ContainerContentsWorkflowRuntime[\"apiClient\"],\n \"getPrincipalPolicyPages\" | \"getProjectionPolicyHistoryPages\"\n >;\n}\n\ntype MoveRemoteContainerDocumentStatus = \"complete\" | \"partial\";\n\ninterface MoveRemoteContainerDocumentResult {\n accessEpoch: number | null;\n accessStateHash: string | null;\n linkedContainerIds: readonly string[];\n nextContainerId: string;\n remoteState: RemoteDocumentPersistedState | null;\n status: MoveRemoteContainerDocumentStatus;\n}\n\nexport type { RemoteDocumentPersistedState };\n\nexport async function initializeDocumentLinksSchema(\n execSql: ExecSql,\n): Promise<void> {\n await sqlDocumentContainerProjectionPersistence.ensureSchema(execSql);\n}\n\nexport async function listDocumentLinkedContainerIds(\n execSql: ExecSql,\n documentId: string,\n): Promise<ReadonlyArray<string>> {\n return sqlDocumentContainerProjectionPersistence.listLinkedContainerIds(\n execSql,\n documentId,\n );\n}\n\nexport async function replaceDocumentLinks(\n execSql: ExecSql,\n documentId: string,\n containerIds: ReadonlyArray<string>,\n): Promise<void> {\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n documentId,\n containerIds,\n );\n}\n\nfunction resolveActiveDocumentContainerId(\n linkedContainerIds: ReadonlyArray<string>,\n preferredContainerId: string,\n): string | null {\n if (linkedContainerIds.includes(preferredContainerId)) {\n return preferredContainerId;\n }\n\n return linkedContainerIds[0] ?? null;\n}\n\nfunction containerDocumentMoveResult(input: {\n document: RelinkRemoteDocumentResult;\n nextContainerId: string;\n status: MoveRemoteContainerDocumentStatus;\n}): MoveRemoteContainerDocumentResult {\n return {\n accessEpoch: input.document.plan.state.epoch,\n accessStateHash: input.document.response.accessManifest.manifestHash,\n linkedContainerIds: input.document.linkedContainerIds,\n nextContainerId: input.nextContainerId,\n remoteState: input.document.persistedState,\n status: input.status,\n };\n}\n\nasync function containerDocumentAlreadyMovedResult(input: {\n writerProjection: DocumentWriterProjectionResponse;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentLinkRuntime;\n isCurrent?: (() => boolean) | undefined;\n linkedContainerIds: readonly string[];\n nextContainerId: string;\n status: MoveRemoteContainerDocumentStatus;\n}): Promise<MoveRemoteContainerDocumentResult> {\n const verified: { head?: VerifiedDocumentLinkSetManifest | undefined } = {};\n await assertDocumentWriterProjectionConsistent(input.writerProjection, {\n execSql: input.runtime.infra.execSql,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.isCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n onVerifiedAuthorization: (authorization) => {\n verified.head = authorization.documentManifestByHash.get(\n input.writerProjection.documentManifest.manifestHash,\n );\n },\n });\n if (!verified.head)\n throw new Error(\"Move replay lacks a verified document head\");\n return {\n accessEpoch: verified.head.state.epoch,\n accessStateHash: verified.head.manifestHash,\n linkedContainerIds: input.linkedContainerIds,\n nextContainerId: input.nextContainerId,\n remoteState: persistedDocumentCreateStateFromWriterProjection(\n input.writerProjection,\n ),\n status: input.status,\n };\n}\n\n/**\n * Hand a link/unlink/move/purge failure to host diagnostics as a real `Error`.\n * The caller's string-only log line stays the fallback for a host without\n * `logError`, so this never logs a second copy of the same failure.\n */\nfunction reportDocumentLinkMutationFailure(\n util: ContainerDocumentLinkRuntime[\"util\"],\n error: unknown,\n): void {\n // `ApiClient` returns `RequestFailure` objects instead of throwing, so\n // offline and 403/404/409 already left through the `!result` branch: a status\n // filter here would be dead code. Only a database lost mid-flight stays quiet.\n if (!util.logError || isDatabaseUnavailableError(error)) return;\n try {\n // A host logger that throws or rejects must not replace the null result or\n // skip the failure handler below.\n void Promise.resolve(\n util.logError(\"Container contents: document link mutation failed\", error),\n ).catch(() => undefined);\n } catch {\n // Hosts may throw synchronously or return a rejected promise.\n }\n}\n\nexport async function relinkRemoteContainerDocument(input: {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n operation: ContainerDocumentLinkOperation;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot?: Uint8Array | undefined;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n const {\n documentId,\n noteId,\n operation,\n resolveProjectionUserKey,\n runtime,\n targetContainerId,\n } = input;\n const author = resolveDocumentCreateAuthor(runtime);\n const targetSecretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n const execSql = runtime.infra.execSql;\n if (input.isCurrent?.() === false) return null;\n if (!author || !targetSecretKey) {\n runtime.util.log(\n \"Container contents: document mutation skipped because the local key context is unavailable\",\n );\n input.onFailure?.({\n message: \"the local key context is unavailable\",\n status: null,\n });\n return null;\n }\n\n try {\n const result = await relinkRemoteDocument({\n beforeSubmit: input.beforeSubmit,\n apiClient: runtime.apiClient,\n author,\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n execSql,\n onFailure: input.onFailure,\n operation,\n resolveProjectionUserKey,\n rotationSnapshot: input.rotationSnapshot,\n stillCurrent: input.isCurrent,\n targetContainerId,\n targetSecretKey,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!result) {\n runtime.util.log(\n `Container contents: failed to ${operation} note ${noteId} ${operation === \"link\" ? \"to\" : \"from\"} container ${targetContainerId}`,\n );\n return null;\n }\n if (input.isCurrent?.() === false) return null;\n\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n documentId,\n result.linkedContainerIds,\n { stillCurrent: input.isCurrent },\n );\n\n return result;\n } catch (error) {\n await reportAndRethrowKeyingVerificationError(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: `document.${operation}`,\n },\n );\n const message = errorMessage(error);\n runtime.util.log(\n `Container contents: failed to ${operation} note ${noteId} ${operation === \"link\" ? \"to\" : \"from\"} container ${targetContainerId}: ${message}`,\n );\n // After the keying rethrow above, so a verification failure keeps its\n // security incident instead of being reported twice, and before the failure\n // handler, so a throwing caller callback cannot swallow the report.\n reportDocumentLinkMutationFailure(runtime.util, error);\n input.onFailure?.({ message, status: null });\n return null;\n }\n}\n\nasync function linkRemoteContainerDocument(input: {\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n return relinkRemoteContainerDocument({\n ...input,\n operation: \"link\",\n });\n}\n\nexport async function unlinkRemoteContainerDocument(input: {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n return relinkRemoteContainerDocument({\n ...input,\n operation: \"unlink\",\n });\n}\n\nexport async function moveRemoteContainerDocument(input: {\n linkOnly?: boolean | undefined;\n additionalLinkContainerIds?: readonly string[] | undefined;\n removedLinkContainerIds?: readonly string[] | undefined;\n currentContainerId: string;\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n replaceLinkedContainers?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<MoveRemoteContainerDocumentResult | null> {\n const {\n documentId,\n noteId,\n resolveProjectionUserKey,\n runtime,\n targetContainerId,\n } = input;\n if (input.isCurrent?.() === false) return null;\n const writerProjection = await fetchMoveWriterProjection({\n documentId,\n onFailure: input.onFailure,\n runtime,\n });\n if (!writerProjection || input.isCurrent?.() === false) {\n return null;\n }\n if (writerProjection.documentId !== documentId)\n throw new Error(\"Move replay document id mismatch\");\n const initialLinkedContainerIds =\n readLinkedContainerIdsFromDocumentManifest(writerProjection);\n\n let latestLinkedContainerIds: readonly string[] = initialLinkedContainerIds;\n let latestDocument: RelinkRemoteDocumentResult | null = null;\n for (const linkTarget of new Set([\n ...(input.linkOnly ? [] : [targetContainerId]),\n ...(input.additionalLinkContainerIds ?? []),\n ])) {\n if (latestLinkedContainerIds.includes(linkTarget)) continue;\n const linkedDocument = await linkRemoteContainerDocument({\n documentId,\n isCurrent: input.isCurrent,\n noteId,\n onFailure: input.onFailure,\n resolveProjectionUserKey,\n runtime,\n targetContainerId: linkTarget,\n });\n if (!linkedDocument || input.isCurrent?.() === false) {\n return null;\n }\n\n latestDocument = linkedDocument;\n latestLinkedContainerIds = linkedDocument.linkedContainerIds;\n }\n\n const unlinkContainerIds = resolveContainerDocumentMoveUnlinkIds({\n ...input,\n linkedContainerIds: latestLinkedContainerIds,\n });\n\n const unlinked = await unlinkMovedDocumentSources({\n ...input,\n latestDocument,\n latestLinkedContainerIds,\n unlinkContainerIds,\n });\n if (!unlinked) return null;\n latestDocument = unlinked.latestDocument;\n latestLinkedContainerIds = unlinked.latestLinkedContainerIds;\n\n const nextContainerId = resolveActiveDocumentContainerId(\n latestLinkedContainerIds,\n targetContainerId,\n );\n if (!nextContainerId) {\n return null;\n }\n\n const status =\n unlinked.failedUnlinkContainerIds.length > 0 ? \"partial\" : \"complete\";\n return latestDocument\n ? containerDocumentMoveResult({\n document: latestDocument,\n nextContainerId,\n status,\n })\n : containerDocumentAlreadyMovedResult({\n writerProjection,\n resolveProjectionUserKey,\n runtime,\n isCurrent: input.isCurrent,\n linkedContainerIds: latestLinkedContainerIds,\n nextContainerId,\n status,\n });\n}\n\n// The unlink half of a move: every source is attempted even when an earlier\n// one fails, so one dead source cannot strand the others; a failed unlink\n// leaves the move \"partial\" for the queue to retry.\nasync function unlinkMovedDocumentSources(input: {\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n latestDocument: RelinkRemoteDocumentResult | null;\n latestLinkedContainerIds: readonly string[];\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n unlinkContainerIds: readonly string[];\n}): Promise<{\n failedUnlinkContainerIds: readonly string[];\n latestDocument: RelinkRemoteDocumentResult | null;\n latestLinkedContainerIds: readonly string[];\n} | null> {\n const { noteId, runtime, targetContainerId } = input;\n let { latestDocument, latestLinkedContainerIds } = input;\n const failedUnlinkContainerIds: string[] = [];\n for (const unlinkContainerId of input.unlinkContainerIds) {\n if (input.isCurrent?.() === false) return null;\n const unlinkedDocument = await unlinkRemoteContainerDocument({\n documentId: input.documentId,\n isCurrent: input.isCurrent,\n noteId,\n onFailure: input.onFailure,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n rotationSnapshot: input.rotationSnapshot,\n runtime,\n targetContainerId: unlinkContainerId,\n });\n if (input.isCurrent?.() === false) return null;\n if (!unlinkedDocument) {\n failedUnlinkContainerIds.push(unlinkContainerId);\n runtime.util.log(\n `Container contents: note ${noteId} was linked to ${targetContainerId} but failed to unlink from ${unlinkContainerId}`,\n );\n continue;\n }\n\n latestDocument = unlinkedDocument;\n latestLinkedContainerIds = unlinkedDocument.linkedContainerIds;\n }\n return { failedUnlinkContainerIds, latestDocument, latestLinkedContainerIds };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentMoveDeniedReplay.js","sourceRoot":"","sources":["documentMoveDeniedReplay.ts"],"names":[],"mappings":"AAaA,+EAA+E;AAC/E,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,gFAAgF;AAChF,yEAAyE;AACzE,8CAA8C;AAC9C,MAAM,6BAA6B,GAAG,IAAI,OAAO,EAG9C,CAAC;AAEJ,MAAM,UAAU,6BAA6B,CAC3C,KAA4B,EAC5B,OAAgB;IAEhB,MAAM,SAAS,GAAG,6BAA6B,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3D,OAAO,CACL,SAAS,EAAE,OAAO,KAAK,OAAO;QAC9B,SAAS,CAAC,mBAAmB,KAAK,KAAK,CAAC,mBAAmB,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,KAA4B,EAC5B,OAAgB;IAEhB,6BAA6B,CAAC,GAAG,CAAC,KAAK,EAAE;QACvC,OAAO;QACP,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;KAC/C,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\ntype ExecSql = ContainerContentsWorkflowRuntime[\"infra\"][\"execSql\"];\n\ninterface DeniedReplayLifecycle {\n readonly lifecycleGeneration?: number | undefined;\n}\n\ninterface DeniedReplayGeneration {\n execSql: ExecSql;\n lifecycleGeneration: number | undefined;\n}\n\n// One replay per store/database generation: parked denied intents flip back to\n// pending ahead of its first scan (row 7). A restart loses the in-memory\n// access-restored edge, and replacing the executor or lifecycle can expose a\n// different durable queue. Running inside the scan keeps ordering trivially\n// correct: replayed intents are attempted by this same pass, not stranded until\n// an unrelated trigger. Marked complete only after the reset lands, so a\n// transient failure retries on the next pass.\nconst deniedReplayGenerationByState = new WeakMap<\n DeniedReplayLifecycle,\n DeniedReplayGeneration\n>();\n\nexport function deniedReplayMatchesGeneration(\n state: DeniedReplayLifecycle,\n execSql: ExecSql,\n): boolean {\n const completed = deniedReplayGenerationByState.get(state);\n return (\n completed?.execSql === execSql &&\n completed.lifecycleGeneration === state.lifecycleGeneration\n );\n}\n\nexport function markDeniedReplayGeneration(\n state: DeniedReplayLifecycle,\n execSql: ExecSql,\n): void {\n deniedReplayGenerationByState.set(state, {\n execSql,\n lifecycleGeneration: state.lifecycleGeneration,\n });\n}\n"]}
|
package/workflows/container-contents/{documentMoveFailure.js → documentMove/documentMoveFailure.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isVanishedContainerFailure } from "
|
|
1
|
+
import { isVanishedContainerFailure } from "../../../data/containers/shared/mutationFailures.js";
|
|
2
2
|
export function createDocumentMoveFailureState() {
|
|
3
3
|
return {
|
|
4
4
|
current: null,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentMoveFailure.js","sourceRoot":"","sources":["documentMoveFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAC;AAsB9F,MAAM,UAAU,8BAA8B;IAC5C,OAAO;QACL,OAAO,EAAE,IAAI;QACb,mBAAmB,EAAE,KAAK;QAC1B,oBAAoB,EAAE,KAAK;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAA+B,EAC/B,OAAuC;IAEvC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,KAAK,CAAC,mBAAmB;QACvB,KAAK,CAAC,mBAAmB,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,CAAC;IACtD,KAAK,CAAC,oBAAoB;QACxB,KAAK,CAAC,oBAAoB,IAAI,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAA+B;IAE/B,MAAM,MAAM,GAAG,KAAK,CAAC,oBAAoB;QACvC,CAAC,CAAC,8DAA8D;QAChE,CAAC,CAAC,kDAAkD,CAAC;IACvD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,KAAK,IAAI;QACrB,CAAC,CAAC,OAAO,CAAC,OAAO;QACjB,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC;IAC/C,OAAO,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import { isVanishedContainerFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type { DocumentLinkSetMutationFailure } from \"../../documents\";\n\n/**\n * What a queued document move learned from its remote link/unlink attempts.\n * Every failure handed to the move's `onFailure` folds into this state; the\n * verdict (`pending`, `blocked`, `denied`) is read off it afterwards.\n */\nexport interface DocumentMoveFailureState {\n current: DocumentLinkSetMutationFailure | null;\n /** A 403 anywhere in the pass parks the intent as denied (row 7). */\n sawPermissionDenial: boolean;\n /**\n * The server proved a cited container no longer exists (coded projection\n * 404 or coded commit 409 `container_unavailable`). Retrying the SAME\n * request can never succeed — but the cited container may be a stale\n * ancestor in a cached path, so the verdict triggers a projection refresh\n * (documentMoveVanishedRefresh) before the intent parks terminally.\n */\n sawVanishedContainer: boolean;\n}\n\nexport function createDocumentMoveFailureState(): DocumentMoveFailureState {\n return {\n current: null,\n sawPermissionDenial: false,\n sawVanishedContainer: false,\n };\n}\n\nexport function recordDocumentMoveFailure(\n state: DocumentMoveFailureState,\n failure: DocumentLinkSetMutationFailure,\n): void {\n state.current = failure;\n state.sawPermissionDenial =\n state.sawPermissionDenial || failure.status === 403;\n state.sawVanishedContainer =\n state.sawVanishedContainer || isVanishedContainerFailure(failure);\n}\n\n/**\n * The queue-facing description of a failed remote move. The stable prefixes\n * are kept so existing consumers keep matching; the captured detail appends\n * the HTTP status when one was seen, so a revoked permission (403) reads\n * differently from an offline blip.\n */\nexport function describeRejectedDocumentMove(\n state: DocumentMoveFailureState,\n): string {\n const prefix = state.sawVanishedContainer\n ? \"Remote document move cites a container deleted on the server\"\n : \"Remote document move was rejected or unavailable\";\n const failure = state.current;\n if (!failure) {\n return prefix;\n }\n const detail =\n failure.status === null\n ? failure.message\n : `${failure.message} (${failure.status})`;\n return `${prefix}: ${detail}`;\n}\n"]}
|
package/workflows/container-contents/{documentMoveIntent.js → documentMove/documentMoveIntent.js}
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from "
|
|
2
|
-
import { uniqueSortedStrings } from "
|
|
3
|
-
import { sqlDocumentMoveIntentPersistence } from "
|
|
4
|
-
import { sqlDocumentContainerProjectionPersistence } from "
|
|
5
|
-
import { defaultDocumentsPersistence } from "
|
|
6
|
-
import { listDocumentLinkedContainerIds } from "
|
|
7
|
-
import { relinkContainerDocumentLocally } from "
|
|
1
|
+
import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from "../../../data/documents/documentConstants.js";
|
|
2
|
+
import { uniqueSortedStrings } from "../../../data/documents/shared/readers.js";
|
|
3
|
+
import { sqlDocumentMoveIntentPersistence } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
4
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
5
|
+
import { defaultDocumentsPersistence } from "../../documents/index.js";
|
|
6
|
+
import { listDocumentLinkedContainerIds } from "../documentLinks/index.js";
|
|
7
|
+
import { relinkContainerDocumentLocally } from "../documentLinks/documentLocalRelink.js";
|
|
8
8
|
async function resolveOptimisticDocumentMoveLinks(input) {
|
|
9
9
|
if (input.replaceLinkedContainers) {
|
|
10
10
|
return [input.targetContainerId];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentMoveIntent.js","sourceRoot":"","sources":["documentMoveIntent.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from \"../../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { uniqueSortedStrings } from \"../../../data/documents/shared/readers\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { defaultDocumentsPersistence } from \"../../documents\";\nimport { listDocumentLinkedContainerIds } from \"../documentLinks\";\nimport { relinkContainerDocumentLocally } from \"../documentLinks/documentLocalRelink\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRuntime,\n SetLinkedContainerIdsForDocument,\n} from \"../documentQueries/documentStructureTypes\";\n\nasync function resolveOptimisticDocumentMoveLinks(input: {\n currentContainerId: string | null;\n documentId: string;\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}): Promise<string[]> {\n if (input.replaceLinkedContainers) {\n return [input.targetContainerId];\n }\n\n const currentLinkedContainerIds = await listDocumentLinkedContainerIds(\n input.runtime.infra.execSql,\n input.documentId,\n );\n const linkedContainerIds =\n currentLinkedContainerIds.length > 0\n ? currentLinkedContainerIds\n : input.currentContainerId\n ? [input.currentContainerId]\n : [];\n\n return uniqueSortedStrings([\n ...linkedContainerIds.filter(\n (containerId) => containerId !== input.currentContainerId,\n ),\n input.targetContainerId,\n ]);\n}\n\nasync function resolveLocalMoveAccessEpoch(input: {\n localId: string;\n runtime: DocumentStructuralMutationRuntime;\n}): Promise<number> {\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n input.runtime.infra.execSql,\n input.localId,\n );\n // The local relink must keep the document's current key epoch. Falling back\n // is only for partially seeded local state; downgrading synced documents\n // would make offline edits use stale access material.\n return existingDocument?.accessEpoch ?? DEFAULT_DOCUMENT_ACCESS_EPOCH;\n}\n\nexport async function moveRemoteDocumentLinkLocally<TRuntime>(params: {\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n expandNode: (nodeId: string) => void;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary & { documentId: string };\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<{ linksChanged: boolean; note: DocumentSummary | null }> {\n const {\n currentDocumentStore,\n expandNode,\n host,\n note,\n replaceLinkedContainers,\n runtime,\n scheduleSync,\n setLinkedContainerIdsForDocument,\n targetContainerId,\n } = params;\n const linkedContainerIds = await resolveOptimisticDocumentMoveLinks({\n currentContainerId: note.containerId,\n documentId: note.documentId,\n replaceLinkedContainers,\n runtime,\n targetContainerId,\n });\n\n // Apply the user's chosen placement locally now, then replay the signed\n // link-set mutation from this durable intent when auth/network/key context is\n // back. This mirrors container move intents: UI state should not wait on the\n // server, but the remote contract still converges through the normal writer\n // projection path.\n const intentId = crypto.randomUUID();\n\n const movedNote = await relinkContainerDocumentLocally({\n accessEpoch: await resolveLocalMoveAccessEpoch({\n localId: note.id,\n runtime,\n }),\n currentDocumentStore,\n host,\n note,\n commitSideEffect: async (execSql) => {\n await sqlDocumentMoveIntentPersistence.enqueueMoveIntent(execSql, {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n replaceLinkedContainers,\n sourceContainerId: note.containerId,\n targetContainerId,\n });\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n requestSync: false,\n runtime,\n targetContainerId,\n });\n if (!movedNote) {\n return { linksChanged: false, note: null };\n }\n\n setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n expandNode(targetContainerId);\n scheduleSync?.();\n runtime.util.log(\n `Container contents: queued note ${movedNote.id} move to ${targetContainerId}`,\n );\n return { linksChanged: true, note: movedNote };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sqlDocumentMoveIntentPersistence } from "
|
|
1
|
+
import { sqlDocumentMoveIntentPersistence } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
2
2
|
export async function recordPendingDocumentMoveIntentError(input) {
|
|
3
3
|
if (!input.isCurrent())
|
|
4
4
|
return false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentMoveIntentErrors.js","sourceRoot":"","sources":["documentMoveIntentErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,4EAA4E,CAAC;AAG9H,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,KAU1D;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,gCAAgC,CAAC,qBAAqB,CAC1D,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EACjC;QACE,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY,EAAE,KAAK,CAAC,SAAS;QAC7B,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CACF,CAAC;IACF,OAAO,KAAK,CAAC,SAAS,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { sqlDocumentMoveIntentPersistence } from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\nexport async function recordPendingDocumentMoveIntentError(input: {\n blocked?: boolean | undefined;\n denied?: boolean | undefined;\n documentId: string;\n expectedIntentId?: string | undefined;\n expectedUpdatedAt?: string | undefined;\n isCurrent: () => boolean;\n message: string;\n state: { runtime: ContainerContentsWorkflowRuntime };\n unavailable?: boolean | undefined;\n}): Promise<boolean> {\n if (!input.isCurrent()) return false;\n await sqlDocumentMoveIntentPersistence.recordMoveIntentError(\n input.state.runtime.infra.execSql,\n {\n blocked: input.blocked,\n denied: input.denied,\n documentId: input.documentId,\n expectedIntentId: input.expectedIntentId,\n expectedUpdatedAt: input.expectedUpdatedAt,\n message: input.message,\n stillCurrent: input.isCurrent,\n unavailable: input.unavailable,\n },\n );\n return input.isCurrent();\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { sqlDocumentMoveIntentPersistence, } from "
|
|
2
|
-
import { sqlDocumentContainerProjectionPersistence } from "
|
|
3
|
-
import { loadDocumentMovePlacement } from "
|
|
4
|
-
import { getClientSQLitePersistenceRuntime } from "
|
|
1
|
+
import { sqlDocumentMoveIntentPersistence, } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
2
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
3
|
+
import { loadDocumentMovePlacement } from "../../../data/persistence/containers/documentPlacement.js";
|
|
4
|
+
import { getClientSQLitePersistenceRuntime } from "../../../data/sqlite/sqlitePersistenceRuntime.js";
|
|
5
5
|
export async function settleDocumentMoveIntent(input) {
|
|
6
6
|
if (!input.isCurrent()) {
|
|
7
7
|
throw new Error("Document move generation changed before local settlement");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentMoveIntentSettlement.js","sourceRoot":"","sources":["documentMoveIntentSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gCAAgC,GACjC,MAAM,4EAA4E,CAAC;AACpF,OAAO,EAAE,yCAAyC,EAAE,MAAM,6EAA6E,CAAC;AACxI,OAAO,EAAE,yBAAyB,EAAE,MAAM,wDAAwD,CAAC;AACnG,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAGlG,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAM9C;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAC5C,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EACnD,KAAK,CAAC,MAAM,CAAC,UAAU,CACxB,CAAC;QACF,IAAI,MAAM,EAAE,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE;YAChC,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;QACJ,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,gCAAgC,CAAC,oBAAoB,CACzE,KAAK,CAAC,OAAO,EACb;QACE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACjC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;KAC1C,CACF,CAAC;IACF,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IACD,MAAM,yCAAyC,CAAC,oBAAoB,CAClE,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,MAAM,CAAC,UAAU,EACvB,KAAK,CAAC,kBAAkB,CACzB,CAAC;AACJ,CAAC","sourcesContent":["import {\n type DocumentMoveIntentRecord,\n sqlDocumentMoveIntentPersistence,\n} from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { loadDocumentMovePlacement } from \"../../../data/persistence/containers/documentPlacement\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\n\nexport async function settleDocumentMoveIntent(input: {\n execSql: ExecSql;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n linkedContainerIds: readonly string[];\n partial: boolean;\n}): Promise<void> {\n if (!input.isCurrent()) {\n throw new Error(\"Document move generation changed before local settlement\");\n }\n if (input.partial) {\n const intent = await loadDocumentMovePlacement(\n getClientSQLitePersistenceRuntime(input.execSql).db,\n input.intent.documentId,\n );\n if (intent?.id !== input.intent.id)\n throw new Error(\n \"Document move intent was superseded before local settlement\",\n );\n return;\n }\n const settled = await sqlDocumentMoveIntentPersistence.markMoveIntentSynced(\n input.execSql,\n {\n documentId: input.intent.documentId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n },\n );\n if (!settled || !input.isCurrent()) {\n throw new Error(\n \"Document move intent was superseded before local settlement\",\n );\n }\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n input.execSql,\n input.intent.documentId,\n input.linkedContainerIds,\n );\n}\n"]}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { reportAndRethrowKeyingVerificationError } from "
|
|
2
|
-
import { DOCUMENT_LINK_INTENT_TYPE, sqlDocumentMoveIntentPersistence, } from "
|
|
3
|
-
import { errorMessage } from "
|
|
4
|
-
import { defaultDocumentsPersistence, } from "
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { reportAndRethrowKeyingVerificationError } from "../../../data/keyingProjectionVerification/error.js";
|
|
2
|
+
import { DOCUMENT_LINK_INTENT_TYPE, sqlDocumentMoveIntentPersistence, } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
3
|
+
import { errorMessage } from "../../../data/shared/errorMessage.js";
|
|
4
|
+
import { defaultDocumentsPersistence, } from "../../documents/index.js";
|
|
5
|
+
import { moveRemoteContainerDocument } from "../documentLinks/index.js";
|
|
6
|
+
import { availableDocumentLinkIntent } from "../documentLinks/availableDocumentLinkIntent.js";
|
|
7
|
+
import { hasRemoteContainerMetadataState } from "../remoteHydration/reconciliation.js";
|
|
7
8
|
import { deniedReplayMatchesGeneration, markDeniedReplayGeneration, } from "./documentMoveDeniedReplay.js";
|
|
8
9
|
import { describeRejectedDocumentMove, } from "./documentMoveFailure.js";
|
|
9
10
|
import { recordPendingDocumentMoveIntentError } from "./documentMoveIntentErrors.js";
|
|
10
11
|
import { settleDocumentMoveIntent } from "./documentMoveIntentSettlement.js";
|
|
11
12
|
import { moveWithVanishedContainerRefresh } from "./documentMoveVanishedRefresh.js";
|
|
12
|
-
import { hasRemoteContainerMetadataState } from "./remoteHydration/reconciliation.js";
|
|
13
13
|
async function relinkMovedDocumentStore(input) {
|
|
14
14
|
if (!input.isCurrent())
|
|
15
15
|
return false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentMoveIntentSync.js","sourceRoot":"","sources":["documentMoveIntentSync.ts"],"names":[],"mappings":"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","sourcesContent":["import { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport {\n DOCUMENT_LINK_INTENT_TYPE,\n type DocumentMoveIntentRecord,\n sqlDocumentMoveIntentPersistence,\n} from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport {\n type DocumentLinkSetFailureHandler,\n type DocumentRecord,\n defaultDocumentsPersistence,\n} from \"../../documents\";\nimport { moveRemoteContainerDocument } from \"../documentLinks\";\nimport { availableDocumentLinkIntent } from \"../documentLinks/availableDocumentLinkIntent\";\nimport type {\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRelinkInput,\n} from \"../documentQueries/documentStructureTypes\";\nimport type { ContainerContentsProjectionUserKeyResolver } from \"../projectionKeys\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { hasRemoteContainerMetadataState } from \"../remoteHydration/reconciliation\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\nimport {\n deniedReplayMatchesGeneration,\n markDeniedReplayGeneration,\n} from \"./documentMoveDeniedReplay\";\nimport {\n type DocumentMoveFailureState,\n describeRejectedDocumentMove,\n} from \"./documentMoveFailure\";\nimport { recordPendingDocumentMoveIntentError } from \"./documentMoveIntentErrors\";\nimport { settleDocumentMoveIntent } from \"./documentMoveIntentSettlement\";\nimport { moveWithVanishedContainerRefresh } from \"./documentMoveVanishedRefresh\";\n\ntype DocumentMoveIntentReplayResult =\n | \"abandoned\"\n | \"moved\"\n | \"partial\"\n | \"blocked\"\n | \"failed\";\n\nexport interface DocumentMoveIntentSyncHost<TRuntime> {\n documentWorkflowRuntime: (containerId: string) => TRuntime;\n openDocumentStore: (input: {\n containerId: string;\n documentId: string | null;\n localId: string;\n }) => DocumentStructuralMutationLocalStore<TRuntime>;\n}\n\ninterface DocumentMoveIntentSyncState {\n containersById: ReadonlyMap<string, ContainerState>;\n lifecycleGeneration?: number | undefined;\n resolveProjectionUserKey: ContainerContentsProjectionUserKeyResolver;\n runtime: ContainerContentsWorkflowRuntime;\n}\n\nasync function relinkMovedDocumentStore<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n relinkInput: DocumentStructuralMutationRelinkInput;\n targetContainerId: string;\n}): Promise<boolean> {\n if (!input.isCurrent()) return false;\n const documentStore = input.host.openDocumentStore({\n containerId: input.targetContainerId,\n documentId: input.intent.documentId,\n localId: input.intent.localId,\n });\n if (!(await documentStore.ensureInitialized()) || !input.isCurrent()) {\n return false;\n }\n\n const relinked = await documentStore.relink({\n ...input.relinkInput,\n stillCurrent: input.isCurrent,\n });\n if (!relinked || !input.isCurrent()) {\n return false;\n }\n\n documentStore.updateRuntime(\n input.host.documentWorkflowRuntime(input.targetContainerId),\n );\n return input.isCurrent();\n}\n\nasync function persistMovedDocumentReplay<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n moved: NonNullable<Awaited<ReturnType<typeof moveRemoteContainerDocument>>>;\n state: DocumentMoveIntentSyncState;\n}): Promise<boolean> {\n const { host, intent, moved, state } = input;\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n state.runtime.infra.execSql,\n intent.localId,\n );\n if (!input.isCurrent() || !existingDocument) {\n return false;\n }\n\n const targetContainerId =\n intent.intentType === DOCUMENT_LINK_INTENT_TYPE &&\n existingDocument.containerId &&\n moved.linkedContainerIds.includes(existingDocument.containerId)\n ? existingDocument.containerId\n : moved.nextContainerId;\n\n const relinkInput: DocumentStructuralMutationRelinkInput = {\n accessEpoch: moved.accessEpoch ?? existingDocument.accessEpoch,\n ...(moved.accessStateHash === null\n ? {}\n : { accessStateHash: moved.accessStateHash }),\n containerId: targetContainerId,\n documentId: intent.documentId,\n localId: intent.localId,\n ...(moved.remoteState ?? {}),\n commitSideEffect: (transactionExecSql) =>\n settleDocumentMoveIntent({\n execSql: transactionExecSql,\n intent,\n isCurrent: input.isCurrent,\n linkedContainerIds: moved.linkedContainerIds,\n partial: moved.status === \"partial\",\n }),\n };\n\n return relinkMovedDocumentStore({\n host,\n isCurrent: input.isCurrent,\n intent,\n relinkInput,\n targetContainerId,\n });\n}\n\nasync function assertMoveIntentRotationPreflight<TRuntime>(input: {\n existingContainerId: string | null | undefined;\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n}): Promise<Uint8Array | null> {\n if (!input.isCurrent()) return null;\n const preflightStore = input.host.openDocumentStore({\n // The optimistic move already changed local placement. Use that scope so\n // opening the destination view cannot invalidate this shared store's proof.\n // Remote link-set authorization still uses the intent's source below.\n containerId: input.existingContainerId ?? input.intent.targetContainerId,\n documentId: input.intent.documentId,\n localId: input.intent.localId,\n });\n if (!(await preflightStore.ensureInitialized())) {\n throw new Error(\"Document rotation preflight could not load the document\");\n }\n if (!input.isCurrent()) return null;\n const rotationSnapshot = await preflightStore.assertCanRotateContentKey();\n return input.isCurrent() ? rotationSnapshot : null;\n}\n\nasync function movePendingDocumentIntent<TRuntime>(input: {\n existingContainerId: string | null | undefined;\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n onFailure: DocumentLinkSetFailureHandler;\n state: DocumentMoveIntentSyncState;\n}) {\n // Adding links keeps the content key and needs no full-history rotation proof.\n const linkOnly = input.intent.intentType === DOCUMENT_LINK_INTENT_TYPE;\n const rotationSnapshot =\n linkOnly && !input.intent.removedLinkContainerIds?.length\n ? new Uint8Array()\n : await assertMoveIntentRotationPreflight(input);\n if (!rotationSnapshot || !input.isCurrent()) return \"abandoned\" as const;\n return moveRemoteContainerDocument({\n linkOnly,\n additionalLinkContainerIds: input.intent.additionalLinkContainerIds,\n removedLinkContainerIds: input.intent.removedLinkContainerIds,\n currentContainerId:\n input.intent.sourceContainerId ??\n input.existingContainerId ??\n input.intent.targetContainerId,\n documentId: input.intent.documentId,\n isCurrent: input.isCurrent,\n noteId: input.intent.localId,\n onFailure: input.onFailure,\n replaceLinkedContainers: input.intent.replaceLinkedContainers,\n resolveProjectionUserKey: input.state.resolveProjectionUserKey,\n rotationSnapshot,\n runtime: input.state.runtime,\n targetContainerId: input.intent.targetContainerId,\n });\n}\n\nasync function resolveMoveIntentPreflight(input: {\n isCreatePending: (containerId: string) => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n state: DocumentMoveIntentSyncState;\n}): Promise<\n | { existingDocument: DocumentRecord; result?: undefined }\n | { existingDocument?: undefined; result: DocumentMoveIntentReplayResult }\n> {\n const { intent, state } = input;\n const execSql = state.runtime.infra.execSql;\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n execSql,\n intent.localId,\n );\n if (!input.isCurrent()) return { result: \"abandoned\" };\n if (!existingDocument || existingDocument.documentId !== intent.documentId) {\n await recordPendingDocumentMoveIntentError({\n blocked: true,\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Document move intent references a missing local document\",\n state,\n });\n return { result: \"blocked\" };\n }\n\n for (const targetId of new Set([\n intent.targetContainerId,\n ...(intent.additionalLinkContainerIds ?? []),\n ])) {\n const targetState = state.containersById.get(targetId);\n if (!targetState) {\n await recordPendingDocumentMoveIntentError({\n blocked: true,\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message:\n \"Document move intent references a missing destination container\",\n state,\n });\n return { result: \"blocked\" };\n }\n if (input.isRemoteSyncBlocked(targetState.container.organizationId)) {\n return { result: \"blocked\" };\n }\n if (\n !hasRemoteContainerMetadataState(targetState) ||\n input.isCreatePending(targetId)\n ) {\n await recordPendingDocumentMoveIntentError({\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Document move destination container is not synced yet\",\n state,\n });\n return { result: \"failed\" };\n }\n }\n return { existingDocument };\n}\n\nasync function recordRejectedDocumentMove(input: {\n failure: DocumentMoveFailureState;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n state: DocumentMoveIntentSyncState;\n unavailable: boolean;\n}): Promise<void> {\n await recordPendingDocumentMoveIntentError({\n // A permission denial parks the intent for the access-restored signal\n // instead of replaying on every structural pass (row 7).\n denied: input.failure.sawPermissionDenial,\n documentId: input.intent.documentId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n isCurrent: input.isCurrent,\n message: describeRejectedDocumentMove(input.failure),\n state: input.state,\n // Terminal only after the vanished-container refresh proved the\n // destination itself gone: the intent can never commit as written and\n // nothing on this device can heal it, so it leaves the replay set instead\n // of re-issuing doomed requests every pass. The tombstone cascade\n // retargets it once hydration tears the deleted container down locally.\n // Every other vanished verdict stays pending for the next pass.\n unavailable: input.unavailable,\n });\n}\n\nfunction logSyncedDocumentMove(\n intent: DocumentMoveIntentRecord,\n state: DocumentMoveIntentSyncState,\n): void {\n state.runtime.util.log(\n `Container contents: synced queued document move ${intent.documentId}`,\n );\n}\n\nasync function settleMovedDocumentIntent<TRuntime>(input: {\n failure: DocumentMoveFailureState;\n host: DocumentMoveIntentSyncHost<TRuntime>;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n moved: NonNullable<Awaited<ReturnType<typeof moveRemoteContainerDocument>>>;\n state: DocumentMoveIntentSyncState;\n unavailable: boolean;\n}): Promise<DocumentMoveIntentReplayResult> {\n const { intent, moved, state } = input;\n if (\n !(await persistMovedDocumentReplay({\n host: input.host,\n intent,\n isCurrent: input.isCurrent,\n moved,\n state,\n }))\n ) {\n if (!input.isCurrent()) return \"abandoned\";\n await recordPendingDocumentMoveIntentError({\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Document move replay could not relink the local document\",\n state,\n });\n return \"failed\";\n }\n if (moved.status === \"partial\") {\n await recordPendingDocumentMoveIntentError({\n // An unlink refused for permissions parks like any other denied\n // move (row 7); other partials keep row 15's replay.\n denied: input.failure.sawPermissionDenial,\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: \"Remote document move partially applied; retry required\",\n state,\n // Terminal only when the refresh proved the destination itself gone\n // after the link had already landed; a vanished unlink alone stays\n // pending with its live link for the next pass to revoke.\n unavailable: input.unavailable,\n });\n return \"partial\";\n }\n\n logSyncedDocumentMove(intent, state);\n return \"moved\";\n}\n\nasync function trySyncPendingDocumentMoveIntent<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n isCreatePending: (containerId: string) => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n isCurrent: () => boolean;\n intent: DocumentMoveIntentRecord;\n state: DocumentMoveIntentSyncState;\n}): Promise<DocumentMoveIntentReplayResult> {\n const { host, intent, state } = input;\n const available = availableDocumentLinkIntent(intent, (id) =>\n state.containersById.has(id),\n );\n const preflight = await resolveMoveIntentPreflight({\n ...input,\n intent: available.intent,\n });\n if (preflight.result !== undefined) {\n return preflight.result;\n }\n const { existingDocument } = preflight;\n\n try {\n const outcome = await moveWithVanishedContainerRefresh({\n apiClient: state.runtime.apiClient,\n attempt: (onFailure) =>\n movePendingDocumentIntent({\n existingContainerId: existingDocument.containerId,\n host,\n isCurrent: input.isCurrent,\n intent: available.intent,\n onFailure,\n state,\n }),\n execSql: state.runtime.infra.execSql,\n existingContainerId: existingDocument.containerId,\n intent: available.intent,\n isCurrent: input.isCurrent,\n });\n if (outcome === \"abandoned\" || !input.isCurrent()) return \"abandoned\";\n if (!outcome.moved) {\n await recordRejectedDocumentMove({\n failure: outcome.failure,\n intent,\n isCurrent: input.isCurrent,\n state,\n unavailable: outcome.unavailable,\n });\n return \"failed\";\n }\n return await settleMovedDocumentIntent({\n failure: outcome.failure,\n host,\n intent,\n isCurrent: input.isCurrent,\n moved: available.deferred\n ? { ...outcome.moved, status: \"partial\" }\n : outcome.moved,\n state,\n unavailable: outcome.unavailable,\n });\n } catch (error: unknown) {\n if (!input.isCurrent()) return \"abandoned\";\n await reportAndRethrowKeyingVerificationError(\n error,\n state.runtime.util.reportSecurityIncident,\n {\n objectId: intent.documentId,\n objectKind: \"document\",\n operation: \"document.move.replay\",\n },\n );\n if (!input.isCurrent()) return \"abandoned\";\n const message = errorMessage(error);\n await recordPendingDocumentMoveIntentError({\n documentId: intent.documentId,\n expectedIntentId: intent.id,\n expectedUpdatedAt: intent.updatedAt,\n isCurrent: input.isCurrent,\n message: `Failed to sync document move: ${message}`,\n state,\n });\n return \"failed\";\n }\n}\n\nexport async function syncPendingDocumentMoveIntents<TRuntime>(input: {\n host: DocumentMoveIntentSyncHost<TRuntime>;\n /** A destination whose create has not settled takes no document yet. */\n isCreatePending: (containerId: string) => boolean;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n state: DocumentMoveIntentSyncState;\n}): Promise<number> {\n if (!input.isCurrent()) return 0;\n const lifecycleState = input.state;\n const state = { ...lifecycleState };\n const execSql = state.runtime.infra.execSql;\n if (!deniedReplayMatchesGeneration(lifecycleState, execSql)) {\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql);\n if (!input.isCurrent()) return 0;\n markDeniedReplayGeneration(lifecycleState, execSql);\n }\n const pendingIntents =\n await sqlDocumentMoveIntentPersistence.listPendingMoveIntents(execSql);\n if (!input.isCurrent()) return 0;\n let movedCount = 0;\n\n for (const intent of pendingIntents) {\n if (!input.isCurrent()) return movedCount;\n const result = await trySyncPendingDocumentMoveIntent({\n host: input.host,\n isCreatePending: input.isCreatePending,\n isCurrent: input.isCurrent,\n isRemoteSyncBlocked: input.isRemoteSyncBlocked,\n intent,\n state,\n });\n if (result === \"abandoned\") return movedCount;\n // A \"partial\" result (link applied, unlink still pending) must not count:\n // the caller re-arms this same structural lane whenever the count is\n // positive, so a deterministically failing unlink hot-looped the pump\n // (issue #1744). The intent row stays pending; event-driven, manual, and\n // startup lane requests retry it.\n if (result === \"moved\") {\n movedCount += 1;\n }\n }\n\n return movedCount;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { isContainerNotFoundFailure } from "
|
|
2
|
-
import { readLinkedContainerIdsFromDocumentManifest } from "
|
|
3
|
-
import { listDocumentLinkedContainerIds } from "
|
|
1
|
+
import { isContainerNotFoundFailure } from "../../../data/containers/shared/mutationFailures.js";
|
|
2
|
+
import { readLinkedContainerIdsFromDocumentManifest } from "../../../data/documents/shared/projection.js";
|
|
3
|
+
import { listDocumentLinkedContainerIds } from "../documentLinks/index.js";
|
|
4
4
|
import { createDocumentMoveFailureState, recordDocumentMoveFailure, } from "./documentMoveFailure.js";
|
|
5
5
|
/**
|
|
6
6
|
* Every container the unlink half of the move can cite. The unlink set is
|