@tearleads/client-sdk 0.1.60 → 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/Tearleads.d.ts +8 -48
- package/Tearleads.js +18 -25
- package/Tearleads.js.map +1 -1
- package/TearleadsOptions.d.ts +49 -0
- package/TearleadsOptions.js +2 -0
- package/TearleadsOptions.js.map +1 -0
- 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/client/root/index.d.ts +1 -1
- package/client/root/index.js.map +1 -1
- package/client/runtime/workflowRuntime.d.ts +1 -1
- package/client/runtime/workflowRuntime.js.map +1 -1
- package/index.d.ts +2 -1
- package/index.js +1 -1
- package/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/projectionKeys.d.ts +1 -1
- package/workflows/container-contents/projectionKeys.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/runtime.d.ts +1 -1
- package/workflows/container-contents/runtime.js.map +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/documents/projectionKeys.d.ts +1 -1
- package/workflows/documents/projectionKeys.js.map +1 -1
- package/workflows/documents/reportDocumentSyncQuarantine.js.map +1 -1
- package/workflows/documents/runtime.d.ts +1 -1
- package/workflows/documents/runtime.js.map +1 -1
- package/workflows/{runtimeInput.d.ts → shared/runtimeInput.d.ts} +6 -6
- package/workflows/shared/runtimeInput.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/runtimeInput.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
- /package/workflows/{runtimeInput.js → shared/runtimeInput.js} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { reportAndRethrowKeyingVerificationError } from "
|
|
2
|
-
import { rethrowProjectionVerificationCancelled } from "
|
|
3
|
-
import { errorMessage } from "
|
|
4
|
-
import { defaultDocumentsPersistence, deletePersistedDocument, purgeRemoteDocument, reclaimDocumentOrphanBlobs, resolveDocumentCreateAuthor, } from "
|
|
5
|
-
import { ensureDocumentClientProjectionTables } from "
|
|
6
|
-
import { createRuntimePrincipalPolicyWarmer } from "
|
|
1
|
+
import { reportAndRethrowKeyingVerificationError } from "../../../data/keyingProjectionVerification/error.js";
|
|
2
|
+
import { rethrowProjectionVerificationCancelled } from "../../../data/keyingProjectionVerification/types.js";
|
|
3
|
+
import { errorMessage } from "../../../data/shared/errorMessage.js";
|
|
4
|
+
import { defaultDocumentsPersistence, deletePersistedDocument, purgeRemoteDocument, reclaimDocumentOrphanBlobs, resolveDocumentCreateAuthor, } from "../../documents/index.js";
|
|
5
|
+
import { ensureDocumentClientProjectionTables } from "../../documents/persistence.js";
|
|
6
|
+
import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
|
|
7
7
|
async function deleteAbsentDocumentState(input) {
|
|
8
8
|
return input.persistence.deleteDocumentSideRowsIfAbsent(input.runtime.infra.execSql, input.noteId, input.documentId, async (transactionExecSql) => {
|
|
9
9
|
await input.runtime.infra.documentProjectors.deleteStoredDocumentClientProjection({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentPurge.js","sourceRoot":"","sources":["documentPurge.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentPurgeResponse } from \"@tearleads/validators/response\";\nimport type { StoredDocumentKind } from \"../../../data/documents/documentKinds\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { rethrowProjectionVerificationCancelled } from \"../../../data/keyingProjectionVerification/types\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport {\n type DocumentsPersistence,\n defaultDocumentsPersistence,\n deletePersistedDocument,\n purgeRemoteDocument,\n reclaimDocumentOrphanBlobs,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport { ensureDocumentClientProjectionTables } from \"../../documents/persistence\";\nimport type { SubtreePurgeRoot } from \"../../documents/subtreePurgeScope\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\ntype ContainerDocumentPurgeApi = Pick<\n ContainerContentsWorkflowRuntime[\"apiClient\"],\n | \"getPrincipalPolicyPages\"\n | \"getProjectionPolicyHistoryPages\"\n | \"getDocumentPurgeProof\"\n | \"getDocumentWriterProjectionResult\"\n | \"purgeDocument\"\n>;\ntype DocumentPurgeResult =\n | DocumentPurgeResponse\n | {\n readonly documentId: string;\n readonly purgedAt: string;\n readonly reclaimedBlobStorageKeys: readonly string[];\n }\n | null;\n\ninterface ContainerDocumentPurgeRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n apiClient: ContainerDocumentPurgeApi;\n}\n\ninterface PurgeRemoteContainerDocumentInput {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n stillCurrent?: (() => boolean) | undefined;\n documentKind: StoredDocumentKind;\n noteId: string;\n persistence?: DocumentsPersistence | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentPurgeRuntime;\n}\n\nasync function deleteAbsentDocumentState(input: {\n readonly commitPurgeProof: (\n transactionExecSql: ContainerDocumentPurgeRuntime[\"infra\"][\"execSql\"],\n ) => Promise<void>;\n readonly documentId: string;\n readonly documentKind: StoredDocumentKind;\n readonly noteId: string;\n readonly persistence: DocumentsPersistence;\n readonly runtime: ContainerDocumentPurgeRuntime;\n}): Promise<boolean> {\n return input.persistence.deleteDocumentSideRowsIfAbsent(\n input.runtime.infra.execSql,\n input.noteId,\n input.documentId,\n async (transactionExecSql) => {\n await input.runtime.infra.documentProjectors.deleteStoredDocumentClientProjection(\n {\n documentKind: input.documentKind,\n execSql: transactionExecSql,\n localId: input.noteId,\n },\n );\n await input.commitPurgeProof(transactionExecSql);\n },\n );\n}\n\nasync function commitVerifiedDocumentPurge(input: {\n readonly commitPurgeProof: (\n transactionExecSql: ContainerDocumentPurgeRuntime[\"infra\"][\"execSql\"],\n ) => Promise<void>;\n readonly documentId: string;\n readonly documentKind: StoredDocumentKind;\n readonly noteId: string;\n readonly persistence: DocumentsPersistence;\n readonly runtime: ContainerDocumentPurgeRuntime;\n}): Promise<boolean> {\n await input.persistence.ensureSchema(input.runtime.infra.execSql);\n await ensureDocumentClientProjectionTables({\n documentProjectors: input.runtime.infra.documentProjectors,\n execSql: input.runtime.infra.execSql,\n });\n const expectedRecord = await input.persistence.loadDocument(\n input.runtime.infra.execSql,\n input.noteId,\n );\n if (expectedRecord && expectedRecord.documentId !== input.documentId) {\n throw new Error(\n \"Local document identity changed while its remote purge was committing\",\n );\n }\n const deleted = expectedRecord\n ? await deletePersistedDocument({\n beforeDeleteInTransaction: input.commitPurgeProof,\n documentProjectors: input.runtime.infra.documentProjectors,\n execSql: input.runtime.infra.execSql,\n expectedRecord,\n localId: input.noteId,\n persistence: input.persistence,\n })\n : await deleteAbsentDocumentState(input);\n if (!deleted) {\n throw new Error(\n \"Local document state changed while its remote purge was committing\",\n );\n }\n return true;\n}\n\nexport async function purgeRemoteContainerDocument(\n input: PurgeRemoteContainerDocumentInput,\n): Promise<DocumentPurgeResult> {\n const { documentId, noteId, runtime } = input;\n const persistence = input.persistence ?? defaultDocumentsPersistence;\n try {\n const author = resolveDocumentCreateAuthor(runtime);\n if (!author) {\n runtime.util.log(\n `Container contents: failed to purge note ${noteId} because the local signing context is unavailable`,\n );\n return null;\n }\n let deleted = false;\n const response = await purgeRemoteDocument({\n apiClient: runtime.apiClient,\n beforeSubmit: input.beforeSubmit,\n author,\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n stillCurrent: input.stillCurrent,\n execSql: runtime.infra.execSql,\n onVerifiedPurge: async ({ commitPurgeProof }) => {\n deleted = await commitVerifiedDocumentPurge({\n commitPurgeProof,\n documentId,\n documentKind: input.documentKind,\n noteId,\n persistence,\n runtime,\n });\n },\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!response) {\n runtime.util.log(\n `Container contents: failed to purge note ${noteId} (document ${documentId})`,\n );\n return null;\n }\n if (deleted) {\n void reclaimDocumentOrphanBlobs(runtime, persistence);\n }\n runtime.util.log(\n `Container contents: purged note ${noteId} (document ${documentId})`,\n );\n return response;\n } catch (error) {\n // A cancelled verification is neither a failure nor a completed purge; the\n // caller that owns the generation decides what to do with it.\n rethrowProjectionVerificationCancelled(error);\n await reportAndRethrowKeyingVerificationError(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: \"document.purge\",\n },\n );\n runtime.util.log(\n `Container contents: failed to purge note ${noteId} (document ${documentId}): ${errorMessage(error)}`,\n );\n return null;\n }\n}\n\ninterface ContainerDocumentLocalPurgeRuntime\n extends Pick<ContainerContentsWorkflowRuntime, \"infra\" | \"util\"> {}\n\nexport async function purgeLocalContainerDocument(input: {\n beforeDeleteInTransaction?: Parameters<\n typeof deletePersistedDocument\n >[0][\"beforeDeleteInTransaction\"];\n noteId: string;\n expectedContainerId?: string | null | undefined;\n persistence?: DocumentsPersistence | undefined;\n runtime: ContainerDocumentLocalPurgeRuntime;\n}): Promise<DocumentPurgeResult> {\n const { noteId, runtime } = input;\n const persistence = input.persistence ?? defaultDocumentsPersistence;\n try {\n await persistence.ensureSchema(runtime.infra.execSql);\n const expectedRecord = await persistence.loadDocument(\n runtime.infra.execSql,\n noteId,\n );\n if (\n !expectedRecord ||\n expectedRecord.documentId !== null ||\n (input.expectedContainerId !== undefined &&\n expectedRecord.containerId !== input.expectedContainerId)\n ) {\n runtime.util.log(\n `Container contents: local-only purge refused for note ${noteId} because it is absent or remote-backed`,\n );\n return null;\n }\n const deleted = await deletePersistedDocument({\n beforeDeleteInTransaction: input.beforeDeleteInTransaction,\n documentProjectors: runtime.infra.documentProjectors,\n execSql: runtime.infra.execSql,\n expectedRecord,\n localId: noteId,\n persistence,\n });\n if (!deleted) {\n runtime.util.log(\n `Container contents: local-only purge refused for note ${noteId} because its identity changed`,\n );\n return null;\n }\n if (deleted) {\n void reclaimDocumentOrphanBlobs(runtime, persistence);\n }\n runtime.util.log(`Container contents: purged local-only note ${noteId}`);\n return {\n documentId: noteId,\n purgedAt: new Date().toISOString(),\n reclaimedBlobStorageKeys: [],\n };\n } catch (error) {\n runtime.util.log(\n `Container contents: failed to purge local-only note ${noteId}: ${errorMessage(error)}`,\n );\n return null;\n }\n}\n"]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { DOCUMENT_NOT_FOUND_ERROR_CODE, } from "
|
|
2
|
-
import { assertDocumentWriterProjectionConsistent } from "
|
|
3
|
-
import { uniqueSortedStrings } from "
|
|
4
|
-
import { ProjectionDependencyUnavailableError } from "
|
|
5
|
-
import { reportKeyingVerificationErrorInCauseChain } from "
|
|
6
|
-
import { createProjectionUserKeyResolver } from "
|
|
7
|
-
import { loadDocumentPurgeCheckpoint } from "
|
|
8
|
-
import { createRuntimePrincipalPolicyWarmer } from "
|
|
9
|
-
import { documentHeadMatchesOrganization } from "
|
|
1
|
+
import { DOCUMENT_NOT_FOUND_ERROR_CODE, } from "../../../internal/validators/response/index.js";
|
|
2
|
+
import { assertDocumentWriterProjectionConsistent } from "../../../data/documents/shared/projection.js";
|
|
3
|
+
import { uniqueSortedStrings } from "../../../data/documents/shared/readers.js";
|
|
4
|
+
import { ProjectionDependencyUnavailableError } from "../../../data/keyingProjectionVerification/dependencyUnavailable.js";
|
|
5
|
+
import { reportKeyingVerificationErrorInCauseChain } from "../../../data/keyingProjectionVerification/error.js";
|
|
6
|
+
import { createProjectionUserKeyResolver } from "../../../data/keyingProjectionVerification/userKeyResolver.js";
|
|
7
|
+
import { loadDocumentPurgeCheckpoint } from "../../../data/persistence/documentPurgeCheckpointPersistence.js";
|
|
8
|
+
import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
|
|
9
|
+
import { documentHeadMatchesOrganization } from "../documentDiscovery/documentHeadScope.js";
|
|
10
10
|
export const HEAD_LINK_SET_LOAD_CONCURRENCY = 4;
|
|
11
11
|
/**
|
|
12
12
|
* Head loads per settle. Tombstones beyond it stay unverified and are held
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentTombstoneEvidence.js","sourceRoot":"","sources":["documentTombstoneEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DOCUMENT_NOT_FOUND_ERROR_CODE,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../../data/documents/shared/projection\";\nimport { uniqueSortedStrings } from \"../../../data/documents/shared/readers\";\nimport { ProjectionDependencyUnavailableError } from \"../../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { reportKeyingVerificationErrorInCauseChain } from \"../../../data/keyingProjectionVerification/error\";\nimport { createProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification/userKeyResolver\";\nimport { loadDocumentPurgeCheckpoint } from \"../../../data/persistence/documentPurgeCheckpointPersistence\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type {\n ContainerDocumentTombstone,\n ContainerDocumentTombstoneVerdict,\n ContainerDocumentTombstoneVerifier,\n} from \"../documentDiscovery/documentDiscoveryTypes\";\nimport { documentHeadMatchesOrganization } from \"../documentDiscovery/documentHeadScope\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\nexport interface VerifiedDocumentHeadLinkSet {\n readonly organizationId: string | null;\n readonly accessEpoch: number;\n /** Present for a signed head; a terminal purge has no live access state. */\n readonly accessStateHash?: string;\n readonly linkedContainerIds: ReadonlyArray<string>;\n}\n\n/**\n * The document's verified head link set, or `null` when no verified head is\n * available: the projection could not be fetched (the requester may no\n * longer read the document, or it was purged) or failed verification.\n */\nexport type DocumentHeadLinkSetLoader = (\n documentId: string,\n expectedManifestHash?: string,\n) => Promise<VerifiedDocumentHeadLinkSet | \"not-found\" | null>;\n\n/** The highest access epoch local state records for the document. */\nexport type LocalDocumentAccessEpochLoader = (\n documentId: string,\n) => Promise<number>;\n\nexport interface DocumentHeadLinkSetLoaderDeps {\n readonly assertDocumentWriterProjectionConsistent: typeof assertDocumentWriterProjectionConsistent;\n readonly loadDocumentPurgeCheckpoint: typeof loadDocumentPurgeCheckpoint;\n}\n\nexport const HEAD_LINK_SET_LOAD_CONCURRENCY = 4;\n/**\n * Head loads per settle. Tombstones beyond it stay unverified and are held\n * for a later, backed-off retry, so a bulk move out of a folder does not cost\n * every device an unbounded burst of fetches before the watermark advances.\n */\nexport const HEAD_LINK_SET_LOADS_PER_RUN = 32;\n\nasync function verifiedHeadLinkSet(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps,\n documentId: string,\n projection: DocumentWriterProjectionResponse,\n): Promise<VerifiedDocumentHeadLinkSet> {\n const verified: { value?: VerifiedDocumentHeadLinkSet } = {};\n await deps.assertDocumentWriterProjectionConsistent(projection, {\n // Only the link set is read; a bundle wrapped to superseded KEK targets\n // still carries the signed head.\n allowStaleContentKeyBundle: true,\n execSql: runtime.infra.execSql,\n onVerifiedAuthorization: (authorization) => {\n const head = authorization.documentManifestByHash.get(\n projection.documentManifest.manifestHash,\n );\n if (head && head.state.documentId === documentId) {\n verified.value = {\n organizationId: head.state.organizationId,\n accessEpoch: head.state.epoch,\n accessStateHash: head.manifestHash,\n linkedContainerIds: uniqueSortedStrings(\n head.state.linkedContainerIds,\n ),\n };\n }\n },\n resolveProjectionUserKey: createProjectionUserKeyResolver(runtime),\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!verified.value) {\n throw new Error(\"Tombstone evidence lacks a verified document head\");\n }\n return verified.value;\n}\n\nasync function reportUnavailableHead(\n runtime: ContainerContentsWorkflowRuntime,\n documentId: string,\n error: unknown,\n): Promise<void> {\n const integrityFailure = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: \"document.tombstone-evidence\",\n },\n );\n try {\n if (\n !integrityFailure &&\n error instanceof ProjectionDependencyUnavailableError\n ) {\n // A policy can advance without changing this document's hash. Drop its\n // cached evidence so the held head can recover on the next run.\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is awaiting current policy history`,\n );\n return;\n }\n runtime.util.logError?.(\n \"Container contents: tombstone evidence is unavailable\",\n error,\n );\n } catch {\n // A host logger that throws must not fail the discovery pass.\n }\n}\n\nexport function createDocumentHeadLinkSetLoader(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps = {\n assertDocumentWriterProjectionConsistent,\n loadDocumentPurgeCheckpoint,\n },\n): DocumentHeadLinkSetLoader {\n return async (documentId, expectedManifestHash) => {\n try {\n // A verified purge proof is terminal signed evidence that the document\n // links nothing any more.\n if (\n await deps.loadDocumentPurgeCheckpoint(\n runtime.infra.execSql,\n documentId,\n )\n ) {\n return {\n organizationId: null,\n accessEpoch: Number.MAX_SAFE_INTEGER,\n linkedContainerIds: [],\n };\n }\n // Tombstones require a fresh head. Listings can reuse a matching cached\n // projection, whose signature and local checkpoint are still verified.\n if (!expectedManifestHash)\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n let result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n if (\n expectedManifestHash &&\n result.ok &&\n result.data.documentManifest.manifestHash !== expectedManifestHash\n ) {\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n }\n if (!result.ok) {\n if (\n result.status === 404 &&\n result.code === DOCUMENT_NOT_FOUND_ERROR_CODE\n )\n return \"not-found\";\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is unavailable (${result.status ?? \"offline\"})`,\n );\n return null;\n }\n return await verifiedHeadLinkSet(runtime, deps, documentId, result.data);\n } catch (error) {\n // Any failure leaves the tombstone unverified (held and retried); a\n // thrown error here must not fail the whole discovery pass.\n await reportUnavailableHead(runtime, documentId, error);\n return null;\n }\n };\n}\n\nfunction judgeTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n head: VerifiedDocumentHeadLinkSet | null,\n): ContainerDocumentTombstoneVerdict[] {\n return tombstones.map((tombstone): ContainerDocumentTombstoneVerdict => {\n if (head === null) {\n return { kind: \"unverified\", tombstone };\n }\n if (head.linkedContainerIds.includes(tombstone.containerId)) {\n return {\n kind: \"refuted\",\n linkedContainerIds: head.linkedContainerIds,\n tombstone,\n };\n }\n return {\n kind: \"verified\",\n tombstone: {\n ...tombstone,\n accessEpoch: head.accessEpoch,\n linkedContainerIds: head.linkedContainerIds,\n },\n };\n });\n}\n\n/**\n * Judge listing tombstones against each document's verified head link set,\n * fetched once per document with bounded concurrency and a per-run cap. A\n * head whose epoch is below local document state is no evidence: it may be a\n * lagging replica or a replay, and applying it could delete rows a newer\n * listing or settled move wrote.\n */\nexport function createContainerDocumentTombstoneVerifier(\n organizationId: string | undefined,\n loadDocumentHeadLinkSet: DocumentHeadLinkSetLoader,\n loadLocalDocumentAccessEpoch: LocalDocumentAccessEpochLoader,\n): ContainerDocumentTombstoneVerifier {\n return async (tombstones) => {\n const byDocumentId = new Map<string, ContainerDocumentTombstone[]>();\n for (const tombstone of tombstones) {\n const group = byDocumentId.get(tombstone.documentId) ?? [];\n group.push(tombstone);\n byDocumentId.set(tombstone.documentId, group);\n }\n const groups = [...byDocumentId.entries()];\n const verdicts: ContainerDocumentTombstoneVerdict[][] = groups.map(\n ([, group], index): ContainerDocumentTombstoneVerdict[] =>\n index < HEAD_LINK_SET_LOADS_PER_RUN\n ? judgeTombstones(group, null)\n : group.map((tombstone) => ({ kind: \"deferred\", tombstone })),\n );\n let next = 0;\n const worker = async () => {\n while (next < Math.min(groups.length, HEAD_LINK_SET_LOADS_PER_RUN)) {\n const index = next++;\n const entry = groups[index];\n if (!entry) break;\n const [documentId, group] = entry;\n const head = await loadDocumentHeadLinkSet(documentId);\n if (head === null || head === \"not-found\") continue;\n if (!documentHeadMatchesOrganization(head, organizationId)) continue;\n // A local-state read that fails is treated like an unavailable head:\n // the tombstones stay held rather than failing the discovery pass.\n const localEpoch = await loadLocalDocumentAccessEpoch(documentId).catch(\n () => Number.MAX_SAFE_INTEGER,\n );\n if (head.accessEpoch < localEpoch) continue;\n verdicts[index] = judgeTombstones(group, head);\n }\n };\n await Promise.all(\n Array.from(\n { length: Math.min(HEAD_LINK_SET_LOAD_CONCURRENCY, groups.length) },\n worker,\n ),\n );\n return verdicts.flat();\n };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { containerDocumentPlacementKey as placementKey } from "
|
|
1
|
+
import { containerDocumentPlacementKey as placementKey } from "../../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js";
|
|
2
2
|
function dedupePlacements(placements) {
|
|
3
3
|
const seen = new Set();
|
|
4
4
|
return placements.filter((placement) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentTombstoneGate.js","sourceRoot":"","sources":["documentTombstoneGate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { containerDocumentPlacementKey as placementKey } from \"../../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport type {\n ContainerDocumentPlacement,\n ContainerDocumentTombstone,\n ContainerDocumentTombstoneVerdict,\n DiscoverContainerDocumentsOptions,\n} from \"../documentDiscovery/documentDiscoveryTypes\";\n\ntype TombstoneGateStore = Pick<\n DiscoverContainerDocumentsOptions,\n | \"applyContainerDocumentTombstones\"\n | \"holdContainerDocumentTombstones\"\n | \"listHeldContainerDocumentTombstones\"\n | \"listKnownContainerDocumentPlacements\"\n | \"refuteContainerDocumentTombstoneHolds\"\n | \"verifyContainerDocumentTombstones\"\n>;\n\nfunction dedupePlacements<T extends ContainerDocumentPlacement>(\n placements: ReadonlyArray<T>,\n): T[] {\n const seen = new Set<string>();\n return placements.filter((placement) => {\n const key = placementKey(placement);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * One candidate per placement the device actually holds; the newest server\n * timestamp wins. A tombstone for a placement this device never had has\n * nothing to remove or hide, so its head is not fetched.\n */\nasync function mergeTombstoneCandidates(\n store: TombstoneGateStore,\n listed: ReadonlyArray<ContainerDocumentTombstone>,\n held: ReadonlyArray<ContainerDocumentTombstone>,\n): Promise<ContainerDocumentTombstone[]> {\n const known = new Set(\n (await store.listKnownContainerDocumentPlacements(listed)).map(\n placementKey,\n ),\n );\n const byPlacement = new Map<string, ContainerDocumentTombstone>();\n for (const tombstone of [\n ...held,\n ...listed.filter((tombstone) => known.has(placementKey(tombstone))),\n ]) {\n const key = placementKey(tombstone);\n const current = byPlacement.get(key);\n if (\n !current ||\n Date.parse(current.updatedAt) < Date.parse(tombstone.updatedAt)\n ) {\n byPlacement.set(key, tombstone);\n }\n }\n return [...byPlacement.values()];\n}\n\nfunction assertVerdictsCoverCandidates(\n candidates: ReadonlyArray<ContainerDocumentTombstone>,\n verdicts: ReadonlyArray<ContainerDocumentTombstoneVerdict>,\n): void {\n const verdictKeys = new Set(\n verdicts.map((verdict) => placementKey(verdict.tombstone)),\n );\n if (\n verdictKeys.size !== verdicts.length ||\n verdictKeys.size !== candidates.length ||\n candidates.some((candidate) => !verdictKeys.has(placementKey(candidate)))\n ) {\n throw new Error(\n \"Container document tombstone verification must return one verdict per tombstone\",\n );\n }\n}\n\n/**\n * Apply a tombstone only when the signed head omits its container. Unavailable\n * heads leave hidden placements. A head that still links a container keeps its\n * placement visible, but retains a backed-off retry: even an uncached signed\n * head can lag the listing, so its refutation must not discard an honest move.\n * Listing items pass their own signed-head gate before reaching persistence.\n */\nexport async function settleContainerDocumentTombstones(input: {\n containerIds: ReadonlyArray<string>;\n store: TombstoneGateStore;\n tombstones: ReadonlyArray<ContainerDocumentTombstone>;\n}): Promise<ReadonlyArray<DocumentSummary>> {\n const { store } = input;\n const held = await store.listHeldContainerDocumentTombstones(\n input.containerIds,\n );\n const candidates = await mergeTombstoneCandidates(\n store,\n input.tombstones,\n held,\n );\n if (candidates.length === 0) {\n return [];\n }\n\n const verdicts = await store.verifyContainerDocumentTombstones(candidates);\n assertVerdictsCoverCandidates(candidates, verdicts);\n const verified = verdicts.flatMap((verdict) =>\n verdict.kind === \"verified\" ? [verdict.tombstone] : [],\n );\n const refuted = verdicts.flatMap((verdict) =>\n verdict.kind === \"refuted\" ? [verdict.tombstone] : [],\n );\n const unverified = verdicts.flatMap((verdict) =>\n verdict.kind === \"unverified\" ? [verdict.tombstone] : [],\n );\n const deferred = verdicts.flatMap((verdict) =>\n verdict.kind === \"deferred\"\n ? [{ ...verdict.tombstone, deferred: true }]\n : [],\n );\n // A loaded head is evidence for every placement it links, including holds\n // on this document that were not due this run: make them visible while\n // retaining each retry, since the head may lag any of those tombstones.\n const headLinkedPlacements = verdicts.flatMap((verdict) => {\n if (verdict.kind !== \"verified\" && verdict.kind !== \"refuted\") return [];\n const linked =\n verdict.kind === \"verified\"\n ? verdict.tombstone.linkedContainerIds\n : verdict.linkedContainerIds;\n return linked.map((containerId) => ({\n containerId,\n documentId: verdict.tombstone.documentId,\n }));\n });\n\n const summaries =\n verified.length > 0\n ? await store.applyContainerDocumentTombstones(verified)\n : [];\n const retryKeys = new Set(refuted.map(placementKey));\n const visibleRetries = dedupePlacements(headLinkedPlacements).filter(\n (placement) => !retryKeys.has(placementKey(placement)),\n );\n if (visibleRetries.length > 0) {\n await store.refuteContainerDocumentTombstoneHolds(visibleRetries);\n }\n const retries = [\n ...unverified,\n ...deferred,\n ...refuted.map((tombstone) => ({ ...tombstone, refuted: true })),\n ];\n if (retries.length > 0) await store.holdContainerDocumentTombstones(retries);\n return summaries;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ProjectionUserKeyResolver } from "../../data/keyingProjectionVerification/index.js";
|
|
2
2
|
import { createProjectionUserKeyResolver } from "../../data/keyingProjectionVerification/userKeyResolver.js";
|
|
3
|
-
import type { WorkflowRuntimeAuthInput, WorkflowRuntimeCryptoInput, WorkflowRuntimeStateInput } from "../runtimeInput.js";
|
|
3
|
+
import type { WorkflowRuntimeAuthInput, WorkflowRuntimeCryptoInput, WorkflowRuntimeStateInput } from "../shared/runtimeInput.js";
|
|
4
4
|
export type DocumentProjectionUserKeyResolver = ProjectionUserKeyResolver;
|
|
5
5
|
type ProjectionKeyRuntime = Parameters<typeof createProjectionUserKeyResolver>[0];
|
|
6
6
|
export interface DocumentProjectionKeyRuntime {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectionKeys.js","sourceRoot":"","sources":["projectionKeys.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,yDAAyD,CAAC;AAmB1G,MAAM,UAAU,uCAAuC,CACrD,OAAqC;IAErC,OAAO,+BAA+B,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,eAA6C,EAC7C,WAAyC;IAEzC,4EAA4E;IAC5E,uEAAuE;IACvE,6EAA6E;IAC7E,wDAAwD;IACxD,OAAO,CACL,eAAe,CAAC,0BAA0B;QACxC,WAAW,CAAC,0BAA0B;QACxC,eAAe,CAAC,IAAI,CAAC,eAAe,KAAK,WAAW,CAAC,IAAI,CAAC,eAAe;QACzE,eAAe,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,IAAI,CAAC,MAAM;QACvD,eAAe,CAAC,MAAM,CAAC,oBAAoB;YACzC,WAAW,CAAC,MAAM,CAAC,oBAAoB;QACzC,eAAe,CAAC,MAAM,CAAC,kBAAkB;YACvC,WAAW,CAAC,MAAM,CAAC,kBAAkB;QACvC,eAAe,CAAC,MAAM,CAAC,cAAc;YACnC,WAAW,CAAC,MAAM,CAAC,cAAc;QACnC,eAAe,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAAC,KAAK,CAAC,WAAW,CACpE,CAAC;AACJ,CAAC","sourcesContent":["import type { ProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeStateInput,\n} from \"../runtimeInput\";\n\nexport type DocumentProjectionUserKeyResolver = ProjectionUserKeyResolver;\ntype ProjectionKeyRuntime = Parameters<\n typeof createProjectionUserKeyResolver\n>[0];\n\nexport interface DocumentProjectionKeyRuntime {\n readonly auth: Pick<WorkflowRuntimeAuthInput, \"isAuthenticated\" | \"userId\">;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly resolveTrustedUserIdentity: ProjectionKeyRuntime[\"resolveTrustedUserIdentity\"];\n readonly state: Pick<WorkflowRuntimeStateInput, \"domainScope\">;\n}\n\nexport function createDocumentProjectionUserKeyResolver(\n runtime: DocumentProjectionKeyRuntime,\n): DocumentProjectionUserKeyResolver {\n return createProjectionUserKeyResolver(runtime);\n}\n\nexport function didDocumentProjectionKeyRuntimeChange(\n previousRuntime: DocumentProjectionKeyRuntime,\n nextRuntime: DocumentProjectionKeyRuntime,\n): boolean {\n // The SDK-owned resolver is stable for the lifetime of Tearleads, but reads\n // mutable session, identity, and database dependencies. The projection\n // resolver adds its own per-user cache, so compare that trust context rather\n // than relying only on the resolver function reference.\n return (\n previousRuntime.resolveTrustedUserIdentity !==\n nextRuntime.resolveTrustedUserIdentity ||\n previousRuntime.auth.isAuthenticated !== nextRuntime.auth.isAuthenticated ||\n previousRuntime.auth.userId !== nextRuntime.auth.userId ||\n previousRuntime.crypto.encapsulationKeyPair !==\n nextRuntime.crypto.encapsulationKeyPair ||\n previousRuntime.crypto.signingFingerprint !==\n nextRuntime.crypto.signingFingerprint ||\n previousRuntime.crypto.signingKeyPair !==\n nextRuntime.crypto.signingKeyPair ||\n previousRuntime.state.domainScope !== nextRuntime.state.domainScope\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"projectionKeys.js","sourceRoot":"","sources":["projectionKeys.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,yDAAyD,CAAC;AAmB1G,MAAM,UAAU,uCAAuC,CACrD,OAAqC;IAErC,OAAO,+BAA+B,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,eAA6C,EAC7C,WAAyC;IAEzC,4EAA4E;IAC5E,uEAAuE;IACvE,6EAA6E;IAC7E,wDAAwD;IACxD,OAAO,CACL,eAAe,CAAC,0BAA0B;QACxC,WAAW,CAAC,0BAA0B;QACxC,eAAe,CAAC,IAAI,CAAC,eAAe,KAAK,WAAW,CAAC,IAAI,CAAC,eAAe;QACzE,eAAe,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,IAAI,CAAC,MAAM;QACvD,eAAe,CAAC,MAAM,CAAC,oBAAoB;YACzC,WAAW,CAAC,MAAM,CAAC,oBAAoB;QACzC,eAAe,CAAC,MAAM,CAAC,kBAAkB;YACvC,WAAW,CAAC,MAAM,CAAC,kBAAkB;QACvC,eAAe,CAAC,MAAM,CAAC,cAAc;YACnC,WAAW,CAAC,MAAM,CAAC,cAAc;QACnC,eAAe,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAAC,KAAK,CAAC,WAAW,CACpE,CAAC;AACJ,CAAC","sourcesContent":["import type { ProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeStateInput,\n} from \"../shared/runtimeInput\";\n\nexport type DocumentProjectionUserKeyResolver = ProjectionUserKeyResolver;\ntype ProjectionKeyRuntime = Parameters<\n typeof createProjectionUserKeyResolver\n>[0];\n\nexport interface DocumentProjectionKeyRuntime {\n readonly auth: Pick<WorkflowRuntimeAuthInput, \"isAuthenticated\" | \"userId\">;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly resolveTrustedUserIdentity: ProjectionKeyRuntime[\"resolveTrustedUserIdentity\"];\n readonly state: Pick<WorkflowRuntimeStateInput, \"domainScope\">;\n}\n\nexport function createDocumentProjectionUserKeyResolver(\n runtime: DocumentProjectionKeyRuntime,\n): DocumentProjectionUserKeyResolver {\n return createProjectionUserKeyResolver(runtime);\n}\n\nexport function didDocumentProjectionKeyRuntimeChange(\n previousRuntime: DocumentProjectionKeyRuntime,\n nextRuntime: DocumentProjectionKeyRuntime,\n): boolean {\n // The SDK-owned resolver is stable for the lifetime of Tearleads, but reads\n // mutable session, identity, and database dependencies. The projection\n // resolver adds its own per-user cache, so compare that trust context rather\n // than relying only on the resolver function reference.\n return (\n previousRuntime.resolveTrustedUserIdentity !==\n nextRuntime.resolveTrustedUserIdentity ||\n previousRuntime.auth.isAuthenticated !== nextRuntime.auth.isAuthenticated ||\n previousRuntime.auth.userId !== nextRuntime.auth.userId ||\n previousRuntime.crypto.encapsulationKeyPair !==\n nextRuntime.crypto.encapsulationKeyPair ||\n previousRuntime.crypto.signingFingerprint !==\n nextRuntime.crypto.signingFingerprint ||\n previousRuntime.crypto.signingKeyPair !==\n nextRuntime.crypto.signingKeyPair ||\n previousRuntime.state.domainScope !== nextRuntime.state.domainScope\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reportDocumentSyncQuarantine.js","sourceRoot":"","sources":["reportDocumentSyncQuarantine.ts"],"names":[],"mappings":"AAGA,MAAM,qBAAqB,GAAG,IAAI,OAAO,EAAkB,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,UAAU,4BAA4B,CAC1C,KAAa,EACb,QAA0D,EAC1D,OAAyC;IAEzC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IAC5E,IAAI,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,OAAO;IAC3D,4EAA4E;IAC5E,yEAAyE;IACzE,qBAAqB,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,KAAK,OAAO,CAAC,OAAO,CAClB,QAAQ,CAAC,qCAAqC,EAAE,OAAO,CAAC,CACzD,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;AACH,CAAC","sourcesContent":["import type { DocumentSyncUpdateIsolationError } from \"../../data/documents/shared/documentSyncUpdateIsolation\";\nimport type { WorkflowRuntimeUtilInput } from \"../runtimeInput\";\n\nconst lastQuarantineByScope = new WeakMap<object, string>();\n\n/** Keep host diagnostics failures from replacing the durable quarantine. */\nexport function reportDocumentSyncQuarantine(\n scope: object,\n logError: WorkflowRuntimeUtilInput[\"logError\"] | undefined,\n failure: DocumentSyncUpdateIsolationError,\n): void {\n if (!logError) return;\n const signature = JSON.stringify([failure.message, failure.batchUpdateIds]);\n if (lastQuarantineByScope.get(scope) === signature) return;\n // Suppress repeats before the host appends local logs and breadcrumbs. Keep\n // only the last failure, and let discarded document scopes be collected.\n lastQuarantineByScope.set(scope, signature);\n try {\n void Promise.resolve(\n logError(\"Documents: sync updates quarantined\", failure),\n ).catch(() => undefined);\n } catch {\n // Hosts may throw synchronously or return a rejected promise.\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reportDocumentSyncQuarantine.js","sourceRoot":"","sources":["reportDocumentSyncQuarantine.ts"],"names":[],"mappings":"AAGA,MAAM,qBAAqB,GAAG,IAAI,OAAO,EAAkB,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,UAAU,4BAA4B,CAC1C,KAAa,EACb,QAA0D,EAC1D,OAAyC;IAEzC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IAC5E,IAAI,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,OAAO;IAC3D,4EAA4E;IAC5E,yEAAyE;IACzE,qBAAqB,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,KAAK,OAAO,CAAC,OAAO,CAClB,QAAQ,CAAC,qCAAqC,EAAE,OAAO,CAAC,CACzD,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;AACH,CAAC","sourcesContent":["import type { DocumentSyncUpdateIsolationError } from \"../../data/documents/shared/documentSyncUpdateIsolation\";\nimport type { WorkflowRuntimeUtilInput } from \"../shared/runtimeInput\";\n\nconst lastQuarantineByScope = new WeakMap<object, string>();\n\n/** Keep host diagnostics failures from replacing the durable quarantine. */\nexport function reportDocumentSyncQuarantine(\n scope: object,\n logError: WorkflowRuntimeUtilInput[\"logError\"] | undefined,\n failure: DocumentSyncUpdateIsolationError,\n): void {\n if (!logError) return;\n const signature = JSON.stringify([failure.message, failure.batchUpdateIds]);\n if (lastQuarantineByScope.get(scope) === signature) return;\n // Suppress repeats before the host appends local logs and breadcrumbs. Keep\n // only the last failure, and let discarded document scopes be collected.\n lastQuarantineByScope.set(scope, signature);\n try {\n void Promise.resolve(\n logError(\"Documents: sync updates quarantined\", failure),\n ).catch(() => undefined);\n } catch {\n // Hosts may throw synchronously or return a rejected promise.\n }\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import type { ApiClient } from "../../internal/api-client/index.js";
|
|
|
2
2
|
import { type DocumentProjectorRegistryInput } from "../../data/documents/documentKinds.js";
|
|
3
3
|
import type { PrincipalHistoryProtectionLease } from "../../data/principals/principalHistoryProtection.js";
|
|
4
4
|
import { type TrustedUserIdentityResolver } from "../../data/trustedUserIdentity/index.js";
|
|
5
|
-
import type { WorkflowRuntimeAuthInput, WorkflowRuntimeCryptoInput, WorkflowRuntimeInfraInput, WorkflowRuntimeStateInput, WorkflowRuntimeUtilInput } from "../runtimeInput.js";
|
|
5
|
+
import type { WorkflowRuntimeAuthInput, WorkflowRuntimeCryptoInput, WorkflowRuntimeInfraInput, WorkflowRuntimeStateInput, WorkflowRuntimeUtilInput } from "../shared/runtimeInput.js";
|
|
6
6
|
interface DocumentsWorkflowRuntimeUtilInput extends Omit<WorkflowRuntimeUtilInput, "logError"> {
|
|
7
7
|
/** Receives handled quarantine errors without converting them to strings. */
|
|
8
8
|
readonly logError?: WorkflowRuntimeUtilInput["logError"] | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAClG,OAAO,EACL,kCAAkC,GAEnC,MAAM,gCAAgC,CAAC;AAyDxC,MAAM,UAAU,8BAA8B,CAC5C,KAAoC;IAEpC,MAAM,kBAAkB,GAAG,gCAAgC,CACzD,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAC/B,CAAC;IACF,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,KAAK;QACd,kBAAkB;KACnB,CAAC;IAEF,OAAO,iCAAiC,CAAC,KAAK,EAAE;QAC9C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK;QACL,0BAA0B,EAAE,kCAAkC,CAC5D,KAAK,CAAC,0BAA0B,CACjC;QACD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport {\n type DocumentProjectorRegistryInput,\n resolveDocumentProjectorRegistry,\n} from \"../../data/documents/documentKinds\";\nimport type { PrincipalHistoryProtectionLease } from \"../../data/principals/principalHistoryProtection\";\nimport { inheritPrincipalHistoryProtection } from \"../../data/principals/principalHistoryRuntime\";\nimport {\n requireTrustedUserIdentityResolver,\n type TrustedUserIdentityResolver,\n} from \"../../data/trustedUserIdentity\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../runtimeInput\";\n\ninterface DocumentsWorkflowRuntimeUtilInput\n extends Omit<WorkflowRuntimeUtilInput, \"logError\"> {\n /** Receives handled quarantine errors without converting them to strings. */\n readonly logError?: WorkflowRuntimeUtilInput[\"logError\"] | undefined;\n}\n\nexport interface DocumentsWorkflowRuntimeInfra\n extends Omit<WorkflowRuntimeInfraInput, \"dbStatus\"> {\n readonly dbStatus: string;\n}\n\ninterface DocumentsWorkflowRuntimeInputInfra\n extends Omit<DocumentsWorkflowRuntimeInfra, \"documentProjectors\"> {\n readonly documentProjectors: DocumentProjectorRegistryInput;\n}\n\nexport interface DocumentsWorkflowRuntimeGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: DocumentsWorkflowRuntimeInfra;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: DocumentsWorkflowRuntimeUtilInput;\n}\n\nexport interface DocumentsWorkflowRuntimeInputGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: DocumentsWorkflowRuntimeInputInfra;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: DocumentsWorkflowRuntimeUtilInput;\n}\n\nexport interface DocumentsWorkflowRuntimeInput\n extends DocumentsWorkflowRuntimeInputGroups {\n /** Private host custody, inherited without exposing it on runtime views. */\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n readonly apiClient: ApiClient;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport interface DocumentsWorkflowRuntime\n extends DocumentsWorkflowRuntimeGroups {\n readonly apiClient: ApiClient;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport function createDocumentsWorkflowRuntime(\n input: DocumentsWorkflowRuntimeInput,\n): DocumentsWorkflowRuntime {\n const documentProjectors = resolveDocumentProjectorRegistry(\n input.infra.documentProjectors,\n );\n const infra = {\n ...input.infra,\n documentProjectors,\n };\n\n return inheritPrincipalHistoryProtection(input, {\n apiClient: input.apiClient,\n auth: input.auth,\n crypto: input.crypto,\n infra,\n resolveTrustedUserIdentity: requireTrustedUserIdentityResolver(\n input.resolveTrustedUserIdentity,\n ),\n state: input.state,\n util: input.util,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAClG,OAAO,EACL,kCAAkC,GAEnC,MAAM,gCAAgC,CAAC;AAyDxC,MAAM,UAAU,8BAA8B,CAC5C,KAAoC;IAEpC,MAAM,kBAAkB,GAAG,gCAAgC,CACzD,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAC/B,CAAC;IACF,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,KAAK;QACd,kBAAkB;KACnB,CAAC;IAEF,OAAO,iCAAiC,CAAC,KAAK,EAAE;QAC9C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK;QACL,0BAA0B,EAAE,kCAAkC,CAC5D,KAAK,CAAC,0BAA0B,CACjC;QACD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport {\n type DocumentProjectorRegistryInput,\n resolveDocumentProjectorRegistry,\n} from \"../../data/documents/documentKinds\";\nimport type { PrincipalHistoryProtectionLease } from \"../../data/principals/principalHistoryProtection\";\nimport { inheritPrincipalHistoryProtection } from \"../../data/principals/principalHistoryRuntime\";\nimport {\n requireTrustedUserIdentityResolver,\n type TrustedUserIdentityResolver,\n} from \"../../data/trustedUserIdentity\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../shared/runtimeInput\";\n\ninterface DocumentsWorkflowRuntimeUtilInput\n extends Omit<WorkflowRuntimeUtilInput, \"logError\"> {\n /** Receives handled quarantine errors without converting them to strings. */\n readonly logError?: WorkflowRuntimeUtilInput[\"logError\"] | undefined;\n}\n\nexport interface DocumentsWorkflowRuntimeInfra\n extends Omit<WorkflowRuntimeInfraInput, \"dbStatus\"> {\n readonly dbStatus: string;\n}\n\ninterface DocumentsWorkflowRuntimeInputInfra\n extends Omit<DocumentsWorkflowRuntimeInfra, \"documentProjectors\"> {\n readonly documentProjectors: DocumentProjectorRegistryInput;\n}\n\nexport interface DocumentsWorkflowRuntimeGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: DocumentsWorkflowRuntimeInfra;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: DocumentsWorkflowRuntimeUtilInput;\n}\n\nexport interface DocumentsWorkflowRuntimeInputGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: DocumentsWorkflowRuntimeInputInfra;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: DocumentsWorkflowRuntimeUtilInput;\n}\n\nexport interface DocumentsWorkflowRuntimeInput\n extends DocumentsWorkflowRuntimeInputGroups {\n /** Private host custody, inherited without exposing it on runtime views. */\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n readonly apiClient: ApiClient;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport interface DocumentsWorkflowRuntime\n extends DocumentsWorkflowRuntimeGroups {\n readonly apiClient: ApiClient;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport function createDocumentsWorkflowRuntime(\n input: DocumentsWorkflowRuntimeInput,\n): DocumentsWorkflowRuntime {\n const documentProjectors = resolveDocumentProjectorRegistry(\n input.infra.documentProjectors,\n );\n const infra = {\n ...input.infra,\n documentProjectors,\n };\n\n return inheritPrincipalHistoryProtection(input, {\n apiClient: input.apiClient,\n auth: input.auth,\n crypto: input.crypto,\n infra,\n resolveTrustedUserIdentity: requireTrustedUserIdentityResolver(\n input.resolveTrustedUserIdentity,\n ),\n state: input.state,\n util: input.util,\n });\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { EncapsulationKeyPair, SigningKeyPair } from "
|
|
2
|
-
import type { BlobStore } from "
|
|
3
|
-
import type { DocumentProjectorRegistry } from "
|
|
4
|
-
import type { DomainScope } from "
|
|
5
|
-
import type { SecurityIncidentReporter } from "
|
|
6
|
-
import type { ExecSql } from "
|
|
1
|
+
import type { EncapsulationKeyPair, SigningKeyPair } from "../../internal/crypto/index.js";
|
|
2
|
+
import type { BlobStore } from "../../data/blobs/blobContracts.js";
|
|
3
|
+
import type { DocumentProjectorRegistry } from "../../data/documents/documentKinds.js";
|
|
4
|
+
import type { DomainScope } from "../../data/shared/domainScope.js";
|
|
5
|
+
import type { SecurityIncidentReporter } from "../../data/shared/securityIncidents.js";
|
|
6
|
+
import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
|
|
7
7
|
export type WorkflowRuntimeDatabaseStatus = "idle" | "ready" | "error" | "terminated";
|
|
8
8
|
export interface WorkflowRuntimeAuthInput {
|
|
9
9
|
/** Server-backed personal organization; independent of organizationId. */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimeInput.js","sourceRoot":"","sources":["runtimeInput.ts"],"names":[],"mappings":"","sourcesContent":["import type { EncapsulationKeyPair, SigningKeyPair } from \"@tearleads/crypto\";\nimport type { BlobStore } from \"../../data/blobs/blobContracts\";\nimport type { DocumentProjectorRegistry } from \"../../data/documents/documentKinds\";\nimport type { DomainScope } from \"../../data/shared/domainScope\";\nimport type { SecurityIncidentReporter } from \"../../data/shared/securityIncidents\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\nexport type WorkflowRuntimeDatabaseStatus =\n | \"idle\"\n | \"ready\"\n | \"error\"\n | \"terminated\";\n\nexport interface WorkflowRuntimeAuthInput {\n /** Server-backed personal organization; independent of organizationId. */\n readonly defaultOrganizationId?: string | null;\n /** Session root identity, independent of a document/pane target. */\n readonly rootContainerId?: string | null | undefined;\n readonly isAuthenticated: boolean;\n /** Platform-operator flag from the server; the API enforces root access. */\n readonly isRoot?: boolean | undefined;\n readonly organizationId: string | null;\n readonly userId: string | null;\n}\n\nexport interface WorkflowRuntimeCryptoInput {\n readonly encapsulationKeyPair: EncapsulationKeyPair | null;\n readonly signingFingerprint: string | null;\n readonly signingKeyPair: SigningKeyPair | null;\n}\n\nexport interface WorkflowRuntimeStateInput {\n readonly containerId: string | null;\n readonly domainScope: DomainScope;\n readonly events: ReadonlyArray<unknown>;\n readonly online: boolean;\n /**\n * Increments after each acknowledged server-events interest declaration.\n * Unlike a boolean connection edge, this survives coalesced runtime\n * notifications and document stores retained while their host provider is\n * unmounted.\n */\n readonly serverEventsConnectionGeneration?: number | undefined;\n /**\n * Per-pane CRDT peer-seed discriminator (e.g. the pane's local identity\n * namespace). Documents in distinct panes must derive distinct Loro peer ids;\n * absent/`null` means single-pane (bare scope). The document runtime factory\n * always populates it; other runtimes and test fixtures may omit it.\n */\n readonly peerScope?: string | null;\n}\n\nexport interface WorkflowRuntimeInfraInput {\n readonly blobStore: BlobStore;\n readonly dbStatus: WorkflowRuntimeDatabaseStatus;\n readonly documentProjectors: DocumentProjectorRegistry;\n readonly execSql: ExecSql;\n}\n\nexport interface WorkflowRuntimeUtilInput {\n readonly isRemoteSyncBlocked?:\n | ((organizationId: string) => boolean)\n | undefined;\n readonly log: (message: string) => void;\n readonly logError: (message: string | Error, cause?: unknown) => void;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n}\n\nexport interface WorkflowRuntimeGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: WorkflowRuntimeInfraInput;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: WorkflowRuntimeUtilInput;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"availableDocumentLinkIntent.js","sourceRoot":"","sources":["availableDocumentLinkIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAE1B,MAAM,yEAAyE,CAAC;AAEjF,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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blobInfo.js","sourceRoot":"","sources":["blobInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,KAAK,EACL,aAAa,EACb,IAAI,EACJ,EAAE,EACF,EAAE,EACF,OAAO,EACP,MAAM,EACN,GAAG,GACJ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,uDAAuD,CAAC;AAChG,OAAO,EACL,UAAU,EACV,gCAAgC,EAChC,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,iCAAiC,GAClC,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAqBxB,MAAM,uBAAuB,GAAG,GAAG,CAAC;AACpC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,sBAAsB,GAAiB;IAC3C,SAAS,EAAE,MAAM;IACjB,GAAG,EAAE,SAAS;CACf,CAAC;AAEF,SAAS,4BAA4B,CAAC,KAAyB;IAC7D,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAyB;IACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAyB;IACvD,OAAO,KAAK,EAAE,IAAI,EAAE,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,qBAAqB,CAAC,KAA+B;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,IACE,CAAC,KAAK,CAAC,SAAS,KAAK,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC;QACzD,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY;YACzB,KAAK,CAAC,GAAG,KAAK,UAAU;YACxB,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,EAC1B,CAAC;QACD,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,qCAAqC,CAAC,EAAwB;IACrE,OAAO,EAAE;SACN,MAAM,CAAC;QACN,cAAc,EAAE,GAAG,CAAwB,WAAW,CAAC,EAAE,CACvD,iBAAiB,CAClB;QACD,MAAM,EAAE,GAAG,CAAe,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC;QAC9C,OAAO,EACL,GAAG,CAAQ,iBAAiB,0BAA0B,CAAC,UAAU,EAAE,CAAC,EAAE,CACpE,UAAU,CACX;QACH,UAAU,EAAE,0BAA0B,CAAC,UAAU;QACjD,aAAa,EAAE,GAAG,CAAQ,GAAG,0BAA0B,CAAC,SAAS,EAAE,CAAC,EAAE,CACpE,iBAAiB,CAClB;QACD,WAAW,EAAE,kBAAkB,CAAC,WAAW;QAC3C,SAAS,EAAE,GAAG,CAAe,GAAG,0BAA0B,CAAC,SAAS,EAAE,CAAC,EAAE,CACvE,YAAY,CACb;QACD,UAAU,EAAE,kBAAkB,CAAC,UAAU;QACzC,YAAY,EAAE,kBAAkB,CAAC,YAAY;QAC7C,aAAa,EAAE,kBAAkB,CAAC,KAAK;QACvC,OAAO,EAAE,0BAA0B,CAAC,OAAO;QAC3C,QAAQ,EAAE,0BAA0B,CAAC,QAAQ;QAC7C,IAAI,EAAE,GAAG,CAAe,GAAG,0BAA0B,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC;QACvE,cAAc,EAAE,GAAG,CAAe;iBACvB,UAAU,CAAC,cAAc;iBACzB,kBAAkB,CAAC,cAAc;QAC1C,CAAC,EAAE,CAAC,iBAAiB,CAAC;QACxB,UAAU,EAAE,GAAG,CAAQ;mBACV,0BAA0B,CAAC,UAAU;iCACvB,0BAA0B,CAAC,QAAQ;iCACnC,0BAA0B,CAAC,IAAI;iCAC/B,0BAA0B,CAAC,OAAO;iCAClC,kBAAkB,CAAC,UAAU;iCAC7B,kBAAkB,CAAC,KAAK;iCACxB,kBAAkB,CAAC,WAAW;;mBAE5C,UAAU,CAAC,cAAc;mBACzB,kBAAkB,CAAC,cAAc;;;iCAGnB,0BAA0B,CAAC,MAAM;QAC1D,CAAC,EAAE,CAAC,aAAa,CAAC;QACpB,MAAM,EAAE,0BAA0B,CAAC,MAAM;QACzC,UAAU,EAAE,0BAA0B,CAAC,UAAU;QACjD,SAAS,EAAE,GAAG,CAAe,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC;KACrD,CAAC;SACD,IAAI,CAAC,0BAA0B,CAAC;SAChC,QAAQ,CACP,kBAAkB,EAClB,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,0BAA0B,CAAC,OAAO,CAAC,CACnE;SACA,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,iFAAiF;AACjF,gFAAgF;AAChF,wDAAwD;AACxD,SAAS,mCAAmC,CAAC,EAAwB;IACnE,OAAO,EAAE;SACN,MAAM,CAAC;QACN,cAAc,EAAE,GAAG,CAAwB,SAAS,CAAC,EAAE,CACrD,iBAAiB,CAClB;QACD,MAAM,EAAE,gCAAgC,CAAC,MAAM;QAC/C,OAAO,EAAE,GAAG,CAAQ;eACX,gCAAgC,CAAC,MAAM;gBACtC,gCAAgC,CAAC,MAAM;4BAC3B,gCAAgC,CAAC,MAAM;6BACtC,gCAAgC,CAAC,UAAU;UAC9D,CAAC,EAAE,CAAC,UAAU,CAAC;QACnB,UAAU,EAAE,gCAAgC,CAAC,UAAU;QACvD,aAAa,EACX,GAAG,CAAQ,GAAG,gCAAgC,CAAC,SAAS,EAAE,CAAC,EAAE,CAC3D,iBAAiB,CAClB;QACH,WAAW,EAAE,kBAAkB,CAAC,WAAW;QAC3C,SAAS,EAAE,GAAG,CAAe,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC;QACpD,UAAU,EAAE,kBAAkB,CAAC,UAAU;QACzC,YAAY,EAAE,kBAAkB,CAAC,YAAY;QAC7C,aAAa,EAAE,kBAAkB,CAAC,KAAK;QACvC,OAAO,EAAE,gCAAgC,CAAC,OAAO;QACjD,QAAQ,EAAE,gCAAgC,CAAC,QAAQ;QACnD,IAAI,EAAE,GAAG,CAAe,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC;QACzC,cAAc,EAAE,GAAG,CAAe;iBACvB,UAAU,CAAC,cAAc;iBACzB,kBAAkB,CAAC,cAAc;QAC1C,CAAC,EAAE,CAAC,iBAAiB,CAAC;QACxB,UAAU,EAAE,GAAG,CAAQ;mBACV,gCAAgC,CAAC,MAAM;iCACzB,gCAAgC,CAAC,UAAU;iCAC3C,gCAAgC,CAAC,QAAQ;iCACzC,gCAAgC,CAAC,OAAO;iCACxC,kBAAkB,CAAC,UAAU;iCAC7B,kBAAkB,CAAC,KAAK;iCACxB,kBAAkB,CAAC,WAAW;;mBAE5C,UAAU,CAAC,cAAc;mBACzB,kBAAkB,CAAC,cAAc;;;iCAGnB,gCAAgC,CAAC,MAAM;QAChE,CAAC,EAAE,CAAC,aAAa,CAAC;QACpB,MAAM,EAAE,gCAAgC,CAAC,MAAM;QAC/C,UAAU,EAAE,gCAAgC,CAAC,UAAU;QACvD,SAAS,EAAE,GAAG,CAEb,GAAG,gCAAgC,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC;KAClE,CAAC;SACD,IAAI,CAAC,gCAAgC,CAAC;SACtC,QAAQ,CACP,kBAAkB,EAClB,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,gCAAgC,CAAC,OAAO,CAAC,CACzE;SACA,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;SACvE,KAAK,CAAC,MAAM,CAAC,gCAAgC,CAAC,UAAU,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,2BAA2B,CAAC,EAAwB;IAC3D,OAAO,EAAE;SACN,KAAK,CAAC,sBAAsB,CAAC;SAC7B,EAAE,CACD,QAAQ,CACN,qCAAqC,CAAC,EAAE,CAAC,EACzC,mCAAmC,CAAC,EAAE,CAAC,CACxC,CACF,CAAC;AACN,CAAC;AAED,SAAS,yBAAyB,CAAC,KAGlC;IACC,MAAM,kBAAkB,GAAG,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjE,MAAM,wBAAwB,GAAG;QAC/B,MAAM,EAAE,GAAG,CAEV,cAAc,kBAAkB,CAAC,MAAM,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC;QAC9D,OAAO,EAAE,kBAAkB,CAAC,OAAO;QACnC,UAAU,EAAE,GAAG,CAAQ,OAAO,kBAAkB,CAAC,UAAU,GAAG,CAAC,EAAE,CAC/D,aAAa,CACd;QACD,aAAa,EAAE,GAAG,CAAe;mBAClB,kBAAkB,CAAC,SAAS;mBAC5B,kBAAkB,CAAC,SAAS;MACzC,CAAC,EAAE,CAAC,iBAAiB,CAAC;QACxB,SAAS,EAAE,GAAG,CAEb,cAAc,kBAAkB,CAAC,SAAS,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC;QACpE,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,EAAE,CACzD,gBAAgB,CACjB;QACD,QAAQ,EAAE,GAAG,CAEZ,cAAc,kBAAkB,CAAC,QAAQ,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC;QAClE,IAAI,EAAE,GAAG,CAAe,cAAc,kBAAkB,CAAC,IAAI,QAAQ,CAAC,EAAE,CACtE,MAAM,CACP;QACD,cAAc,EAAE,GAAG,CAAe;0BACZ,kBAAkB,CAAC,cAAc;oCACvB,kBAAkB,CAAC,cAAc;0BAC3C,kBAAkB,CAAC,cAAc;;QAEnD,CAAC,EAAE,CAAC,iBAAiB,CAAC;QAC1B,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC;QAC7C,UAAU,EAAE,GAAG,CAAQ,OAAO,kBAAkB,CAAC,UAAU,GAAG,CAAC,EAAE,CAC/D,aAAa,CACd;QACD,SAAS,EAAE,GAAG,CAEb,cAAc,kBAAkB,CAAC,SAAS,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC;KACrE,CAAC;IAEF,IAAI,KAAK,CAAC,KAAK,KAAK,EAAE,EAAE,CAAC;QACvB,MAAM,eAAe,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAC5D,KAAK,CAAC,EAAE;aACL,MAAM,CAAC,wBAAwB,CAAC;aAChC,IAAI,CAAC,kBAAkB,CAAC;aACxB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CACrC,CAAC;QAEF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;IACzE,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAC9D,KAAK,CAAC,EAAE;SACL,cAAc,CAAC;QACd,eAAe,EAAE,GAAG,CAAQ,GAAG,kBAAkB,CAAC,OAAO,EAAE,CAAC,EAAE,CAC5D,mBAAmB,CACpB;KACF,CAAC;SACD,IAAI,CAAC,kBAAkB,CAAC;SACxB,KAAK,CACJ,EAAE,CACA,GAAG,CAAQ,SAAS,kBAAkB,CAAC,UAAU,KAAK,KAAK,CAAC,KAAK,GAAG,EACpE,CAAC,CACF,CACF,CACJ,CAAC;IACF,MAAM,eAAe,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAC5D,KAAK,CAAC,EAAE;SACL,MAAM,CAAC,wBAAwB,CAAC;SAChC,IAAI,CAAC,kBAAkB,CAAC;SACxB,SAAS,CACR,gBAAgB,EAChB,EAAE,CAAC,gBAAgB,CAAC,eAAe,EAAE,kBAAkB,CAAC,OAAO,CAAC,CACjE;SACA,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CACrC,CAAC;IAEF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,KAGhC;IACC,MAAM,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAC7D,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,IAAI,GACR,gBAAgB,KAAK,IAAI;QACvB,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;aACX,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC;aACzC,MAAM,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;aACjD,IAAI,CAAC,eAAe,CAAC;QAC1B,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;aACX,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,eAAe,CAAC;aAC3D,MAAM,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;aACjD,IAAI,CAAC,eAAe,CAAC,CAAC;IAE/B,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AAChE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,KAM/B;IACC,MAAM,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAC7D,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,sBAAsB,GAC1B,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM;QAC7B,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;QACrC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,uBAAuB,GAC3B,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM;QAC7B,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;QAClC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IACtC,IAAI,OAA+C,CAAC;IACpD,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,GAAG;YACR,GAAG,CAAC,GAAG,CAAA,GAAG,eAAe,CAAC,QAAQ,UAAU,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM;gBAC7B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAA,GAAG,eAAe,CAAC,QAAQ,iBAAiB,CAAC;gBACvD,CAAC,CAAC,GAAG,CAAC,GAAG,CAAA,GAAG,eAAe,CAAC,QAAQ,iBAAiB,CAAC;YACxD,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;YACnC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC;SAC7B,CAAC;IACJ,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC;QAC3C,OAAO,GAAG;YACR,uBAAuB;YACvB,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;YACnC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC;SAC7B,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,GAAG;YACR,GAAG,CAAC,GAAG,CAAA,GAAG,eAAe,CAAC,aAAa,UAAU,CAAC;YAClD,sBAAsB;YACtB,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC;SAC7B,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,eAAe,CAAC,MAAM;QAC9B,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,UAAU,EAAE,eAAe,CAAC,UAAU;QACtC,SAAS,EAAE,eAAe,CAAC,SAAS;QACpC,aAAa,EAAE,eAAe,CAAC,aAAa;QAC5C,QAAQ,EAAE,eAAe,CAAC,QAAQ;QAClC,IAAI,EAAE,eAAe,CAAC,IAAI;QAC1B,cAAc,EAAE,eAAe,CAAC,cAAc;QAC9C,cAAc,EAAE,eAAe,CAAC,cAAc;QAC9C,UAAU,EAAE,eAAe,CAAC,UAAU;QACtC,SAAS,EAAE,eAAe,CAAC,SAAS;KACrC,CAAC;IACF,MAAM,IAAI,GACR,gBAAgB,KAAK,IAAI;QACvB,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;aACX,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC;aACzC,MAAM,CAAC,SAAS,CAAC;aACjB,IAAI,CAAC,eAAe,CAAC;aACrB,OAAO,CAAC,GAAG,OAAO,CAAC;aACnB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;aAClB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QACzB,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;aACX,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,eAAe,CAAC;aAC3D,MAAM,CAAC,SAAS,CAAC;aACjB,IAAI,CAAC,eAAe,CAAC;aACrB,OAAO,CAAC,GAAG,OAAO,CAAC;aACnB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;aAClB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE9B,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,KAG5C;IACC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,kBAAkB,GAAG,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,EAAE;SACxB,IAAI,CAAC,kBAAkB,CAAC;SACxB,MAAM,CAAC;QACN,cAAc,EAAE,kBAAkB,CAAC,cAAc;QACjD,MAAM,EAAE,kBAAkB,CAAC,MAAM;QACjC,UAAU,EAAE,kBAAkB,CAAC,UAAU;QACzC,WAAW,EAAE,kBAAkB,CAAC,WAAW;QAC3C,SAAS,EAAE,kBAAkB,CAAC,SAAS;QACvC,UAAU,EAAE,kBAAkB,CAAC,UAAU;QACzC,YAAY,EAAE,kBAAkB,CAAC,YAAY;QAC7C,aAAa,EAAE,kBAAkB,CAAC,aAAa;QAC/C,OAAO,EAAE,kBAAkB,CAAC,OAAO;QACnC,QAAQ,EAAE,kBAAkB,CAAC,QAAQ;QACrC,IAAI,EAAE,kBAAkB,CAAC,IAAI;QAC7B,MAAM,EAAE,kBAAkB,CAAC,MAAM;QACjC,UAAU,EAAE,kBAAkB,CAAC,UAAU;QACzC,SAAS,EAAE,kBAAkB,CAAC,SAAS;KACxC,CAAC;SACD,IAAI,CAAC,kBAAkB,CAAC;SACxB,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;SAC3D,OAAO,CACN,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAC/B,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,EACtC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAC/B,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAC/B,CAAC;IAEJ,OAAO,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAwE;IAExE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,4BAA4B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,uBAAuB,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,EAAE,EAAE,EAAE,GAAG,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEhE,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC;QACzC,EAAE;QACF,KAAK;KACN,CAAC,CAAC;IACH,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,IAAI,UAAU,EAAE,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC;QACzC,EAAE;QACF,KAAK;QACL,MAAM;QACN,KAAK;QACL,IAAI;KACL,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,6BAA6B,CAAC;QACrD,EAAE;QACF,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;KACxC,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,wBAAwB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QACjE,UAAU;KACX,CAAC;AACJ,CAAC","sourcesContent":["import {\n asc,\n count,\n countDistinct,\n desc,\n eq,\n gt,\n inArray,\n isNull,\n sql,\n} from \"drizzle-orm\";\nimport { unionAll } from \"drizzle-orm/sqlite-core\";\nimport { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport {\n containers,\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n documentProjection,\n} from \"../../data/sqlite/schema\";\nimport {\n type ClientSQLiteDatabase,\n getClientSQLitePersistenceRuntime,\n} from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport {\n attachBlobInfoReferences,\n mapBlobInfoReferenceRow,\n mapBlobInfoRow,\n readRequiredNumber,\n} from \"./blobInfoRows\";\nimport type {\n BlobInfo,\n BlobInfoAttachmentKind,\n BlobInfoDocumentReference,\n BlobInfoInput,\n BlobInfoList,\n BlobInfoSort,\n} from \"./blobInfoTypes\";\n\nexport type {\n BlobInfo,\n BlobInfoAttachmentKind,\n BlobInfoDocumentReference,\n BlobInfoInput,\n BlobInfoList,\n BlobInfoSort,\n BlobInfoSortDirection,\n BlobInfoSortKey,\n} from \"./blobInfoTypes\";\n\nconst DEFAULT_BLOB_INFO_LIMIT = 200;\nconst MAX_BLOB_INFO_LIMIT = 999;\nconst DEFAULT_BLOB_INFO_SORT: BlobInfoSort = {\n direction: \"desc\",\n key: \"updated\",\n};\n\nfunction normalizeBlobInfoWindowValue(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.trunc(value));\n}\n\nfunction normalizeBlobInfoLimit(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_BLOB_INFO_LIMIT;\n }\n\n return Math.min(MAX_BLOB_INFO_LIMIT, normalizeBlobInfoWindowValue(value));\n}\n\nfunction normalizeBlobInfoQuery(value: string | undefined): string {\n return value?.trim().toLocaleLowerCase() ?? \"\";\n}\n\nfunction normalizeBlobInfoSort(value: BlobInfoSort | undefined): BlobInfoSort {\n if (!value) {\n return DEFAULT_BLOB_INFO_SORT;\n }\n\n if (\n (value.direction !== \"asc\" && value.direction !== \"desc\") ||\n (value.key !== \"byteLength\" &&\n value.key !== \"mimeType\" &&\n value.key !== \"updated\")\n ) {\n return DEFAULT_BLOB_INFO_SORT;\n }\n\n return value;\n}\n\nfunction createPendingBlobInfoReferencesSelect(db: ClientSQLiteDatabase) {\n return db\n .select({\n attachmentKind: sql<BlobInfoAttachmentKind>`'pending'`.as(\n \"attachment_kind\",\n ),\n blobId: sql<string | null>`NULL`.as(\"blob_id\"),\n blobKey:\n sql<string>`'storage:' || ${documentPendingAttachments.storageKey}`.as(\n \"blob_key\",\n ),\n byteLength: documentPendingAttachments.byteLength,\n changedAtSort: sql<string>`${documentPendingAttachments.createdAt}`.as(\n \"changed_at_sort\",\n ),\n containerId: documentProjection.containerId,\n createdAt: sql<string | null>`${documentPendingAttachments.createdAt}`.as(\n \"created_at\",\n ),\n documentId: documentProjection.documentId,\n documentKind: documentProjection.documentKind,\n documentTitle: documentProjection.title,\n localId: documentPendingAttachments.localId,\n mimeType: documentPendingAttachments.mimeType,\n name: sql<string | null>`${documentPendingAttachments.name}`.as(\"name\"),\n organizationId: sql<string | null>`COALESCE(\n NULLIF(${containers.organizationId}, ''),\n NULLIF(${documentProjection.organizationId}, '')\n )`.as(\"organization_id\"),\n searchText: sql<string>`LOWER(\n COALESCE(${documentPendingAttachments.storageKey}, '')\n || CHAR(0) || COALESCE(${documentPendingAttachments.mimeType}, '')\n || CHAR(0) || COALESCE(${documentPendingAttachments.name}, '')\n || CHAR(0) || COALESCE(${documentPendingAttachments.localId}, '')\n || CHAR(0) || COALESCE(${documentProjection.documentId}, '')\n || CHAR(0) || COALESCE(${documentProjection.title}, '')\n || CHAR(0) || COALESCE(${documentProjection.containerId}, '')\n || CHAR(0) || COALESCE(\n NULLIF(${containers.organizationId}, ''),\n NULLIF(${documentProjection.organizationId}, ''),\n ''\n )\n || CHAR(0) || COALESCE(${documentPendingAttachments.slotId}, '')\n )`.as(\"search_text\"),\n slotId: documentPendingAttachments.slotId,\n storageKey: documentPendingAttachments.storageKey,\n updatedAt: sql<string | null>`NULL`.as(\"updated_at\"),\n })\n .from(documentPendingAttachments)\n .leftJoin(\n documentProjection,\n eq(documentProjection.localId, documentPendingAttachments.localId),\n )\n .leftJoin(containers, eq(containers.id, documentProjection.containerId));\n}\n\n// Detached rows are excluded here rather than at each call site: a slot unlinked\n// from a synced document keeps its row until the detach reaches the server, and\n// it stops being a reference the moment it is unlinked.\nfunction createLocalBlobInfoReferencesSelect(db: ClientSQLiteDatabase) {\n return db\n .select({\n attachmentKind: sql<BlobInfoAttachmentKind>`'local'`.as(\n \"attachment_kind\",\n ),\n blobId: documentAttachmentBlobProjection.blobId,\n blobKey: sql<string>`CASE\n WHEN ${documentAttachmentBlobProjection.blobId} IS NOT NULL\n AND ${documentAttachmentBlobProjection.blobId} <> ''\n THEN 'blob:' || ${documentAttachmentBlobProjection.blobId}\n ELSE 'storage:' || ${documentAttachmentBlobProjection.storageKey}\n END`.as(\"blob_key\"),\n byteLength: documentAttachmentBlobProjection.byteLength,\n changedAtSort:\n sql<string>`${documentAttachmentBlobProjection.updatedAt}`.as(\n \"changed_at_sort\",\n ),\n containerId: documentProjection.containerId,\n createdAt: sql<string | null>`NULL`.as(\"created_at\"),\n documentId: documentProjection.documentId,\n documentKind: documentProjection.documentKind,\n documentTitle: documentProjection.title,\n localId: documentAttachmentBlobProjection.localId,\n mimeType: documentAttachmentBlobProjection.mimeType,\n name: sql<string | null>`NULL`.as(\"name\"),\n organizationId: sql<string | null>`COALESCE(\n NULLIF(${containers.organizationId}, ''),\n NULLIF(${documentProjection.organizationId}, '')\n )`.as(\"organization_id\"),\n searchText: sql<string>`LOWER(\n COALESCE(${documentAttachmentBlobProjection.blobId}, '')\n || CHAR(0) || COALESCE(${documentAttachmentBlobProjection.storageKey}, '')\n || CHAR(0) || COALESCE(${documentAttachmentBlobProjection.mimeType}, '')\n || CHAR(0) || COALESCE(${documentAttachmentBlobProjection.localId}, '')\n || CHAR(0) || COALESCE(${documentProjection.documentId}, '')\n || CHAR(0) || COALESCE(${documentProjection.title}, '')\n || CHAR(0) || COALESCE(${documentProjection.containerId}, '')\n || CHAR(0) || COALESCE(\n NULLIF(${containers.organizationId}, ''),\n NULLIF(${documentProjection.organizationId}, ''),\n ''\n )\n || CHAR(0) || COALESCE(${documentAttachmentBlobProjection.slotId}, '')\n )`.as(\"search_text\"),\n slotId: documentAttachmentBlobProjection.slotId,\n storageKey: documentAttachmentBlobProjection.storageKey,\n updatedAt: sql<\n string | null\n >`${documentAttachmentBlobProjection.updatedAt}`.as(\"updated_at\"),\n })\n .from(documentAttachmentBlobProjection)\n .leftJoin(\n documentProjection,\n eq(documentProjection.localId, documentAttachmentBlobProjection.localId),\n )\n .leftJoin(containers, eq(containers.id, documentProjection.containerId))\n .where(isNull(documentAttachmentBlobProjection.detachedAt));\n}\n\nfunction createBlobInfoReferencesCte(db: ClientSQLiteDatabase) {\n return db\n .$with(\"blob_info_references\")\n .as(\n unionAll(\n createPendingBlobInfoReferencesSelect(db),\n createLocalBlobInfoReferencesSelect(db),\n ),\n );\n}\n\nfunction createGroupedBlobInfoCtes(input: {\n readonly db: ClientSQLiteDatabase;\n readonly query: string;\n}) {\n const blobInfoReferences = createBlobInfoReferencesCte(input.db);\n const groupedBlobInfoSelection = {\n blobId: sql<\n string | null\n >`MIN(NULLIF(${blobInfoReferences.blobId}, ''))`.as(\"blob_id\"),\n blobKey: blobInfoReferences.blobKey,\n byteLength: sql<number>`MAX(${blobInfoReferences.byteLength})`.as(\n \"byte_length\",\n ),\n changedAtSort: sql<string | null>`COALESCE(\n MAX(NULLIF(${blobInfoReferences.updatedAt}, '')),\n MIN(NULLIF(${blobInfoReferences.createdAt}, ''))\n )`.as(\"changed_at_sort\"),\n createdAt: sql<\n string | null\n >`MIN(NULLIF(${blobInfoReferences.createdAt}, ''))`.as(\"created_at\"),\n documentCount: countDistinct(blobInfoReferences.localId).as(\n \"document_count\",\n ),\n mimeType: sql<\n string | null\n >`MIN(NULLIF(${blobInfoReferences.mimeType}, ''))`.as(\"mime_type\"),\n name: sql<string | null>`MIN(NULLIF(${blobInfoReferences.name}, ''))`.as(\n \"name\",\n ),\n organizationId: sql<string | null>`CASE\n WHEN COUNT(NULLIF(${blobInfoReferences.organizationId}, '')) = COUNT(*)\n AND COUNT(DISTINCT NULLIF(${blobInfoReferences.organizationId}, '')) = 1\n THEN MIN(NULLIF(${blobInfoReferences.organizationId}, ''))\n ELSE NULL\n END`.as(\"organization_id\"),\n referenceCount: count().as(\"reference_count\"),\n storageKey: sql<string>`MIN(${blobInfoReferences.storageKey})`.as(\n \"storage_key\",\n ),\n updatedAt: sql<\n string | null\n >`MAX(NULLIF(${blobInfoReferences.updatedAt}, ''))`.as(\"updated_at\"),\n };\n\n if (input.query === \"\") {\n const groupedBlobInfo = input.db.$with(\"grouped_blob_info\").as(\n input.db\n .select(groupedBlobInfoSelection)\n .from(blobInfoReferences)\n .groupBy(({ blobKey }) => blobKey),\n );\n\n return { blobInfoReferences, groupedBlobInfo, matchingBlobKeys: null };\n }\n\n const matchingBlobKeys = input.db.$with(\"matching_blob_keys\").as(\n input.db\n .selectDistinct({\n matchingBlobKey: sql<string>`${blobInfoReferences.blobKey}`.as(\n \"matching_blob_key\",\n ),\n })\n .from(blobInfoReferences)\n .where(\n gt(\n sql<number>`INSTR(${blobInfoReferences.searchText}, ${input.query})`,\n 0,\n ),\n ),\n );\n const groupedBlobInfo = input.db.$with(\"grouped_blob_info\").as(\n input.db\n .select(groupedBlobInfoSelection)\n .from(blobInfoReferences)\n .innerJoin(\n matchingBlobKeys,\n eq(matchingBlobKeys.matchingBlobKey, blobInfoReferences.blobKey),\n )\n .groupBy(({ blobKey }) => blobKey),\n );\n\n return { blobInfoReferences, groupedBlobInfo, matchingBlobKeys };\n}\n\nasync function countBlobInfoRows(input: {\n readonly db: ClientSQLiteDatabase;\n readonly query: string;\n}): Promise<number> {\n const { blobInfoReferences, groupedBlobInfo, matchingBlobKeys } =\n createGroupedBlobInfoCtes(input);\n const rows =\n matchingBlobKeys === null\n ? await input.db\n .with(blobInfoReferences, groupedBlobInfo)\n .select({ totalCount: count().as(\"total_count\") })\n .from(groupedBlobInfo)\n : await input.db\n .with(blobInfoReferences, matchingBlobKeys, groupedBlobInfo)\n .select({ totalCount: count().as(\"total_count\") })\n .from(groupedBlobInfo);\n\n return readRequiredNumber(rows[0]?.totalCount, \"total_count\");\n}\n\nasync function listBlobInfoRows(input: {\n readonly db: ClientSQLiteDatabase;\n readonly limit: number;\n readonly offset: number;\n readonly query: string;\n readonly sort: BlobInfoSort;\n}): Promise<Array<Omit<BlobInfo, \"references\">>> {\n const { blobInfoReferences, groupedBlobInfo, matchingBlobKeys } =\n createGroupedBlobInfoCtes(input);\n const changedAtSortDirection =\n input.sort.direction === \"desc\"\n ? desc(groupedBlobInfo.changedAtSort)\n : asc(groupedBlobInfo.changedAtSort);\n const byteLengthSortDirection =\n input.sort.direction === \"desc\"\n ? desc(groupedBlobInfo.byteLength)\n : asc(groupedBlobInfo.byteLength);\n let orderBy: ReturnType<typeof asc | typeof desc>[];\n if (input.sort.key === \"mimeType\") {\n orderBy = [\n asc(sql`${groupedBlobInfo.mimeType} IS NULL`),\n input.sort.direction === \"desc\"\n ? desc(sql`${groupedBlobInfo.mimeType} COLLATE NOCASE`)\n : asc(sql`${groupedBlobInfo.mimeType} COLLATE NOCASE`),\n desc(groupedBlobInfo.changedAtSort),\n asc(groupedBlobInfo.blobKey),\n ];\n } else if (input.sort.key === \"byteLength\") {\n orderBy = [\n byteLengthSortDirection,\n desc(groupedBlobInfo.changedAtSort),\n asc(groupedBlobInfo.blobKey),\n ];\n } else {\n orderBy = [\n asc(sql`${groupedBlobInfo.changedAtSort} IS NULL`),\n changedAtSortDirection,\n asc(groupedBlobInfo.blobKey),\n ];\n }\n const selection = {\n blobId: groupedBlobInfo.blobId,\n blobKey: groupedBlobInfo.blobKey,\n byteLength: groupedBlobInfo.byteLength,\n createdAt: groupedBlobInfo.createdAt,\n documentCount: groupedBlobInfo.documentCount,\n mimeType: groupedBlobInfo.mimeType,\n name: groupedBlobInfo.name,\n organizationId: groupedBlobInfo.organizationId,\n referenceCount: groupedBlobInfo.referenceCount,\n storageKey: groupedBlobInfo.storageKey,\n updatedAt: groupedBlobInfo.updatedAt,\n };\n const rows =\n matchingBlobKeys === null\n ? await input.db\n .with(blobInfoReferences, groupedBlobInfo)\n .select(selection)\n .from(groupedBlobInfo)\n .orderBy(...orderBy)\n .limit(input.limit)\n .offset(input.offset)\n : await input.db\n .with(blobInfoReferences, matchingBlobKeys, groupedBlobInfo)\n .select(selection)\n .from(groupedBlobInfo)\n .orderBy(...orderBy)\n .limit(input.limit)\n .offset(input.offset);\n\n return rows.map(mapBlobInfoRow);\n}\n\nasync function listBlobInfoReferencesForKeys(input: {\n readonly db: ClientSQLiteDatabase;\n readonly keys: ReadonlyArray<string>;\n}): Promise<BlobInfoDocumentReference[]> {\n if (input.keys.length === 0) {\n return [];\n }\n\n const blobInfoReferences = createBlobInfoReferencesCte(input.db);\n const rows = await input.db\n .with(blobInfoReferences)\n .select({\n attachmentKind: blobInfoReferences.attachmentKind,\n blobId: blobInfoReferences.blobId,\n byteLength: blobInfoReferences.byteLength,\n containerId: blobInfoReferences.containerId,\n createdAt: blobInfoReferences.createdAt,\n documentId: blobInfoReferences.documentId,\n documentKind: blobInfoReferences.documentKind,\n documentTitle: blobInfoReferences.documentTitle,\n localId: blobInfoReferences.localId,\n mimeType: blobInfoReferences.mimeType,\n name: blobInfoReferences.name,\n slotId: blobInfoReferences.slotId,\n storageKey: blobInfoReferences.storageKey,\n updatedAt: blobInfoReferences.updatedAt,\n })\n .from(blobInfoReferences)\n .where(inArray(blobInfoReferences.blobKey, [...input.keys]))\n .orderBy(\n asc(blobInfoReferences.blobKey),\n desc(blobInfoReferences.changedAtSort),\n asc(blobInfoReferences.localId),\n asc(blobInfoReferences.slotId),\n );\n\n return rows.map(mapBlobInfoReferenceRow);\n}\n\nexport async function listBlobInfo(\n input: BlobInfoInput & { readonly execSql?: ExecSql | null | undefined },\n): Promise<BlobInfoList> {\n if (!input.execSql) {\n return { rows: [], totalCount: 0 };\n }\n\n const query = normalizeBlobInfoQuery(input.query);\n const limit = normalizeBlobInfoLimit(input.limit);\n const offset = normalizeBlobInfoWindowValue(input.offset);\n const sort = normalizeBlobInfoSort(input.sort);\n await sqlDocumentsPersistence.ensureSchema(input.execSql);\n await ensureContainerTables(input.execSql);\n const { db } = getClientSQLitePersistenceRuntime(input.execSql);\n\n const totalCount = await countBlobInfoRows({\n db,\n query,\n });\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const groupedRows = await listBlobInfoRows({\n db,\n limit,\n offset,\n query,\n sort,\n });\n const references = await listBlobInfoReferencesForKeys({\n db,\n keys: groupedRows.map((row) => row.key),\n });\n\n return {\n rows: attachBlobInfoReferences({ references, rows: groupedRows }),\n totalCount,\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blobInfoTypes.js","sourceRoot":"","sources":["blobInfoTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { StoredDocumentKind } from \"../../data/documents/documentKinds\";\n\nexport type BlobInfoAttachmentKind = \"local\" | \"pending\";\nexport type BlobInfoSortDirection = \"asc\" | \"desc\";\nexport type BlobInfoSortKey = \"byteLength\" | \"mimeType\" | \"updated\";\n\nexport interface BlobInfoSort {\n readonly direction: BlobInfoSortDirection;\n readonly key: BlobInfoSortKey;\n}\n\nexport interface BlobInfoDocumentReference {\n readonly attachmentKind: BlobInfoAttachmentKind;\n readonly blobId: string | null;\n readonly byteLength: number;\n readonly containerId: string | null;\n readonly createdAt: string | null;\n readonly documentId: string | null;\n readonly documentKind: StoredDocumentKind | null;\n readonly documentTitle: string | null;\n readonly localId: string;\n readonly mimeType: string | null;\n readonly name: string | null;\n readonly slotId: string;\n readonly storageKey: string;\n readonly updatedAt: string | null;\n}\n\nexport interface BlobInfo {\n readonly blobId: string | null;\n readonly byteLength: number;\n readonly createdAt: string | null;\n readonly documentCount: number;\n readonly key: string;\n readonly mimeType: string | null;\n readonly name: string | null;\n // Identity-wide display attribution from referenced document containers;\n // null when missing or inconsistent rather than guessing across a boundary.\n readonly organizationId: string | null;\n readonly referenceCount: number;\n readonly references: ReadonlyArray<BlobInfoDocumentReference>;\n readonly storageKey: string;\n readonly updatedAt: string | null;\n}\n\nexport interface BlobInfoList {\n readonly rows: ReadonlyArray<BlobInfo>;\n readonly totalCount: number;\n}\n\nexport interface BlobInfoInput {\n readonly limit?: number | undefined;\n readonly offset?: number | undefined;\n readonly query?: string | undefined;\n readonly sort?: BlobInfoSort | undefined;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"containerInfo.js","sourceRoot":"","sources":["containerInfo.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerAccessLevel,\n ContainerGrantSubjectType,\n} from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../data/containers/shared/projection\";\nimport { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport {\n type ContainerSyncWatermarkLane,\n containerContentsSyncLane,\n containerParentSyncLane,\n containerSyncWatermarkLaneKey,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../data/persistence/containers/containerSyncWatermarkPersistence\";\nimport { containers } from \"../../data/sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { OrganizationGroupSummary } from \"../organizations/readModel\";\n\nexport type ContainerShareAccessLevel = ContainerAccessLevel;\n\nexport interface ContainerInfoGrant {\n accessLevel: ContainerAccessLevel;\n subjectId: string;\n subjectType: ContainerGrantSubjectType;\n}\n\nexport interface ContainerInfoGrantRow extends ContainerInfoGrant {\n inherited: boolean;\n sourceContainerId: string;\n}\n\nexport interface ContainerInfoSyncCursor {\n label: string;\n laneId: string;\n laneKind: string;\n savedAt: string | null;\n watermarkId: string | null;\n watermarkUpdatedAt: string | null;\n}\n\nexport interface ContainerInfoPathEntry {\n containerId: string;\n containerKeyEpoch: number;\n containerKeyEpochId: string;\n directGrantCount: number;\n eventHash: string;\n keyEpochHash: string;\n keyTargetHash: string;\n manifestHash: string;\n manifestHistoryCount: number;\n parentContainerId: string | null;\n parentManifestHash: string | null;\n recipientTargetCount: number;\n referencedPrincipalCount: number;\n wrapCount: number;\n}\n\nexport interface ContainerInfoSecurityDetails {\n currentContainerKeyEpoch: number;\n currentContainerKeyEpochId: string;\n currentManifestHash: string;\n currentManifestHistoryCount: number;\n currentParentContainerKeyEpochId: string | null;\n currentReferencedPrincipalCount: number;\n path: ContainerInfoPathEntry[];\n pathLength: number;\n}\n\nexport interface ContainerInfoRemoteDetails {\n grantRows: ContainerInfoGrantRow[];\n grants: ContainerInfoGrant[];\n groups: OrganizationGroupSummary[];\n security?: ContainerInfoSecurityDetails;\n syncCursors: ContainerInfoSyncCursor[];\n}\n\nexport interface ContainerInfoLocalDetails {\n createdAt: string | null;\n updatedAt: string | null;\n}\n\nexport interface ContainerInfo {\n local: ContainerInfoLocalDetails;\n remoteInfo: ContainerInfoRemoteDetails | null;\n}\n\ninterface ContainerInfoApi {\n getContainerWriterProjection: (\n containerId: string,\n ) => Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport type ContainerInfoRemoteMode = \"always\" | \"if-synced\" | \"never\";\n\ninterface LocalContainerInfoRecord {\n hasSyncedContainer: boolean;\n localCreatedAt: string | null;\n localUpdatedAt: string | null;\n organizationId: string | null;\n parentId: string | null;\n}\n\nfunction sortContainerInfoGrants<T extends ContainerInfoGrant>(\n grants: readonly T[],\n): T[] {\n return [...grants].sort((left, right) =>\n `${left.subjectType}:${left.subjectId}`.localeCompare(\n `${right.subjectType}:${right.subjectId}`,\n ),\n );\n}\n\nfunction toContainerInfoGrant(grant: ContainerInfoGrant): ContainerInfoGrant {\n return {\n accessLevel: grant.accessLevel,\n subjectId: grant.subjectId,\n subjectType: grant.subjectType,\n };\n}\n\nfunction getContainerInfoGrantRows(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoGrantRow[] {\n const rows = projection.path.flatMap((bundle) => {\n const state = readContainerState(bundle);\n\n return state.directGrants.map((grant) => ({\n ...toContainerInfoGrant(grant),\n inherited: state.containerId !== projection.containerId,\n sourceContainerId: state.containerId,\n }));\n });\n\n return sortContainerInfoGrants(rows);\n}\n\nfunction getContainerInfoPathEntries(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoPathEntry[] {\n return projection.path.map((bundle, index) => {\n const state = readContainerState(bundle);\n const kek = projection.containerKeks[index];\n if (!kek) {\n throw new Error(\"Container projection path and KEKs are inconsistent\");\n }\n\n return {\n containerId: state.containerId,\n containerKeyEpoch: kek.containerKeyEpoch,\n containerKeyEpochId: kek.containerKeyEpochId,\n directGrantCount: state.directGrants.length,\n eventHash: state.eventHash,\n keyEpochHash: kek.keyEpochHash,\n keyTargetHash: kek.keyTargetHash,\n manifestHash: bundle.manifestHash,\n manifestHistoryCount: kek.containerManifestHistory.length,\n parentContainerId: state.parentContainerId,\n parentManifestHash: state.parentManifestHash,\n recipientTargetCount: kek.recipientTargets.length,\n referencedPrincipalCount: state.referencedPrincipalHeads.length,\n wrapCount: kek.wraps.length,\n };\n });\n}\n\nfunction getContainerInfoSecurityDetails(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoSecurityDetails {\n const path = getContainerInfoPathEntries(projection);\n const targetPathEntry = path.at(-1);\n const targetKek = projection.containerKeks.at(-1);\n if (!targetPathEntry || !targetKek) {\n throw new Error(\"Container projection is empty\");\n }\n\n return {\n currentContainerKeyEpoch: targetPathEntry.containerKeyEpoch,\n currentContainerKeyEpochId: targetPathEntry.containerKeyEpochId,\n currentManifestHash: targetPathEntry.manifestHash,\n currentManifestHistoryCount: targetPathEntry.manifestHistoryCount,\n currentParentContainerKeyEpochId: targetKek.parentContainerKeyEpochId,\n currentReferencedPrincipalCount: targetPathEntry.referencedPrincipalCount,\n path,\n pathLength: path.length,\n };\n}\n\ninterface ContainerInfoSyncCursorDefinition {\n label: string;\n lane: ContainerSyncWatermarkLane;\n}\n\nfunction getContainerSyncCursorDefinitions(input: {\n containerId: string;\n parentId: string | null;\n}): ContainerInfoSyncCursorDefinition[] {\n return [\n {\n label: \"Parent Listing\",\n lane: containerParentSyncLane(input.parentId),\n },\n {\n label: \"Child Containers\",\n lane: containerParentSyncLane(input.containerId),\n },\n {\n label: \"Documents\",\n lane: containerContentsSyncLane(input.containerId),\n },\n ];\n}\n\nasync function loadContainerSyncCursors(input: {\n containerId: string;\n execSql: ExecSql | null;\n parentId: string | null;\n}): Promise<ContainerInfoSyncCursor[]> {\n const cursorDefinitions = getContainerSyncCursorDefinitions(input);\n let records: Awaited<\n ReturnType<typeof sqlContainerSyncWatermarkPersistence.loadWatermarkRecords>\n > = [];\n if (input.execSql) {\n await sqlContainerSyncWatermarkPersistence.ensureSchema(input.execSql);\n records = await sqlContainerSyncWatermarkPersistence.loadWatermarkRecords(\n input.execSql,\n cursorDefinitions.map(({ lane }) => lane),\n );\n }\n\n return cursorDefinitions.map((definition, index) => {\n const { laneId, laneKind } = containerSyncWatermarkLaneKey(definition.lane);\n const record = records[index] ?? null;\n\n return {\n label: definition.label,\n laneId,\n laneKind,\n savedAt: record?.updatedAt ?? null,\n watermarkId: record?.watermark.id ?? null,\n watermarkUpdatedAt: record?.watermark.updatedAt ?? null,\n };\n });\n}\n\nasync function loadLocalContainerInfoRecord(input: {\n containerId: string;\n execSql: ExecSql | null;\n parentId: string | null;\n}): Promise<LocalContainerInfoRecord> {\n const fallback: LocalContainerInfoRecord = {\n hasSyncedContainer: false,\n localCreatedAt: null,\n localUpdatedAt: null,\n organizationId: null,\n parentId: input.parentId,\n };\n\n if (!input.execSql) {\n return fallback;\n }\n\n await ensureContainerTables(input.execSql);\n\n const { db } = getClientSQLitePersistenceRuntime(input.execSql);\n const rows = await db\n .select({\n localCreatedAt: containers.localCreatedAt,\n localUpdatedAt: containers.localUpdatedAt,\n metadataDocumentId: containers.metadataDocumentId,\n organizationId: containers.organizationId,\n parentId: containers.parentId,\n })\n .from(containers)\n .where(eq(containers.id, input.containerId))\n .limit(1);\n const row = rows[0];\n\n if (!row) {\n return fallback;\n }\n\n return {\n hasSyncedContainer:\n typeof row.metadataDocumentId === \"string\" &&\n row.metadataDocumentId.length > 0,\n localCreatedAt: row.localCreatedAt,\n localUpdatedAt: row.localUpdatedAt,\n organizationId: row.organizationId,\n parentId: row.parentId,\n };\n}\n\nfunction shouldLoadRemoteContainerInfo(input: {\n localContainerInfo: LocalContainerInfoRecord;\n remoteInfoMode: ContainerInfoRemoteMode;\n}): boolean {\n switch (input.remoteInfoMode) {\n case \"always\":\n return true;\n case \"if-synced\":\n return input.localContainerInfo.hasSyncedContainer;\n case \"never\":\n return false;\n }\n}\n\nexport async function loadContainerInfo(input: {\n apiClient: ContainerInfoApi;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | null | undefined;\n execSql?: ExecSql | null;\n loadOrganizationGroups: () => Promise<\n ReadonlyArray<OrganizationGroupSummary>\n >;\n parentId?: string | null;\n remoteInfoMode?: ContainerInfoRemoteMode | undefined;\n}): Promise<ContainerInfo> {\n const localContainerInfo = await loadLocalContainerInfoRecord({\n containerId: input.containerId,\n execSql: input.execSql ?? null,\n parentId: input.parentId ?? null,\n });\n const local = {\n createdAt: localContainerInfo.localCreatedAt,\n updatedAt: localContainerInfo.localUpdatedAt,\n };\n\n if (\n !shouldLoadRemoteContainerInfo({\n localContainerInfo,\n remoteInfoMode: input.remoteInfoMode ?? \"always\",\n })\n ) {\n return {\n local,\n remoteInfo: null,\n };\n }\n\n const [projection, groups, syncCursors] = await Promise.all([\n input.containerProjection\n ? Promise.resolve(input.containerProjection)\n : input.apiClient.getContainerWriterProjection(input.containerId),\n input.loadOrganizationGroups(),\n loadContainerSyncCursors({\n containerId: input.containerId,\n execSql: input.execSql ?? null,\n parentId: localContainerInfo.parentId,\n }),\n ]);\n\n if (!projection) {\n throw new Error(\"Container info could not be loaded.\");\n }\n\n const target = getTargetContainerContext(projection);\n const state = readContainerState(target.manifest);\n\n return {\n local,\n remoteInfo: {\n grantRows: getContainerInfoGrantRows(projection),\n grants: sortContainerInfoGrants(\n state.directGrants.map(toContainerInfoGrant),\n ),\n groups: [...groups],\n security: getContainerInfoSecurityDetails(projection),\n syncCursors,\n },\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deferredDocumentLinks.js","sourceRoot":"","sources":["deferredDocumentLinks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAEtF,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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentCharacterBlame.js","sourceRoot":"","sources":["documentCharacterBlame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAGL,sBAAsB,GACvB,MAAM,sCAAsC,CAAC;AAE9C,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,8CAA8C;AAC9C,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEzC;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,eAA8B,EAC9B,QAAqD;IAOrD,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,2BAA2B,CACxC,aAAa,CAAC,eAAe,CAAC,EAC9B,yBAAyB,CAC1B,CAAC;QACF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { listSnapshotCharBlameSource } from \"@tearleads/loro\";\nimport type { DocumentEditAttributionResponse } from \"@tearleads/validators/response\";\nimport {\n type DocumentBlameRange,\n type DocumentCharacterBlameSummary,\n summarizeDocumentBlame,\n} from \"../../data/documents/editAttribution\";\n\n// Op-id extraction is linear (~1.8µs/char — ~90ms for a 50k snapshot, flat per\n// char), so this cap is a soft guard against pathologically large prose, not a\n// quadratic cliff: above it blame surfaces null rather than doing unbounded\n// synchronous work when the Info panel opens.\nconst MAX_BLAME_CHARACTER_COUNT = 50_000;\n\n/**\n * Rebuild the document's per-character op ids from the locally persisted\n * content snapshot and resolve them against the attribution segments — in a\n * single snapshot reconstruction — into both the per-writer blame summary and\n * the coalesced per-writer ranges. Returns null when blame can't be produced:\n * no local snapshot, a snapshot too large to scan cheaply, or an unreadable\n * snapshot — blame is supplementary and must never block (or blank) the rest\n * of the Info panel, mirroring the attribution fetch's degrade-to-null.\n */\nexport function computeDocumentBlame(\n contentSnapshot: string | null,\n segments: DocumentEditAttributionResponse[\"segments\"],\n): {\n /** Per-writer live-character counts (the Contributors-style rollup). */\n characterBlame: DocumentCharacterBlameSummary;\n /** Contiguous per-writer runs of the current prose (the read-only blame view). */\n blameRanges: DocumentBlameRange[];\n} | null {\n if (!contentSnapshot || contentSnapshot.length === 0) {\n return null;\n }\n try {\n const source = listSnapshotCharBlameSource(\n base64ToBytes(contentSnapshot),\n MAX_BLAME_CHARACTER_COUNT,\n );\n if (source === null) {\n return null;\n }\n return summarizeDocumentBlame(source, segments);\n } catch {\n return null;\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentDiscovery.js","sourceRoot":"","sources":["documentDiscovery.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 {\n listContainerDocumentLanesFromApi,\n listContainerDocumentsFromWatermarks,\n} from \"./containerDocumentListing\";\nimport { withoutDeferredDocumentLinks } from \"./deferredDocumentLinks\";\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\";\nimport { settleContainerDocumentTombstones } from \"./documentTombstoneGate\";\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentDiscoveryApply.js","sourceRoot":"","sources":["documentDiscoveryApply.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { dedupeReferencedPrincipalStates } from \"../../data/keyingProjectionVerification/principalPolicyCache\";\nimport { withoutDeferredDocumentLinks } from \"./deferredDocumentLinks\";\nimport { getApplicableDocumentTombstones } from \"./documentDiscoveryInputs\";\nimport type {\n DiscoverContainerDocumentsOptions,\n ListedContainerDocuments,\n} from \"./documentDiscoveryTypes\";\nimport { settleContainerDocumentTombstones } from \"./documentTombstoneGate\";\n\n/** A discovery lane's local stores; the listing itself is supplied by the caller. */\nexport type ContainerDocumentDiscoveryLane = Omit<\n DiscoverContainerDocumentsOptions,\n | \"beginDocumentDiscovery\"\n | \"listContainerDocumentLanes\"\n | \"loadContainerDocumentWatermark\"\n>;\n\nexport async function saveAppliedContainerDocumentWatermark(input: {\n containerId: string;\n listedDocuments: ListedContainerDocuments;\n saveContainerDocumentWatermark: DiscoverContainerDocumentsOptions[\"saveContainerDocumentWatermark\"];\n}) {\n const { containerId, listedDocuments, saveContainerDocumentWatermark } =\n input;\n if (!listedDocuments.nextWatermark) {\n return;\n }\n\n await saveContainerDocumentWatermark(\n containerId,\n listedDocuments.nextWatermark,\n );\n}\n\n/**\n * Verifies and applies one container's completed listing under a discovery\n * generation captured before the listing request, then advances its\n * watermark. Returns `null` when nothing was applied.\n */\nexport async function applyListedContainerDocuments(\n options: ContainerDocumentDiscoveryLane,\n generation: number,\n listedDocuments: ListedContainerDocuments,\n): Promise<ReadonlyArray<DocumentSummary> | null> {\n const { containerId, upsertDiscoveredDocuments } = options;\n await options.cacheReferencedPrincipalPolicies?.(\n dedupeReferencedPrincipalStates(\n listedDocuments.items.flatMap(\n (document) => document.referencedPrincipals,\n ),\n ),\n );\n\n const verification = await options.verifyDiscoveredDocuments(\n listedDocuments.items.map((document) => ({\n accessEpoch: document.currentAccessEpoch,\n accessStateHash: document.currentAccessStateHash,\n containerId,\n listedContainerIds: [containerId],\n createdAt: document.createdAt,\n documentId: document.id,\n effectiveAccessLevel: document.effectiveAccessLevel,\n linkedContainerIds: document.linkedContainerIds,\n })),\n [containerId],\n generation,\n getApplicableDocumentTombstones(listedDocuments),\n );\n if (!(await verification.isCurrent())) return null;\n const verifiedInputs = verification.inputs;\n const discoveredDocuments = verifiedInputs.length\n ? await upsertDiscoveredDocuments(verifiedInputs)\n : [];\n\n if (verifiedInputs.length)\n await options.replaceDocumentLinksBatch(\n await withoutDeferredDocumentLinks(\n verifiedInputs.map((document) => ({\n documentId: document.documentId,\n accessEpoch: document.accessEpoch,\n containerIds: document.linkedContainerIds,\n })),\n discoveredDocuments,\n ),\n );\n\n const tombstoneDocumentSummaries = await settleContainerDocumentTombstones({\n containerIds: [containerId],\n store: options,\n tombstones: getApplicableDocumentTombstones(listedDocuments),\n });\n\n const complete = await verification.commit();\n if (!(await verification.isCurrent())) return null;\n await saveAppliedContainerDocumentWatermark({\n containerId,\n listedDocuments,\n saveContainerDocumentWatermark: options.saveContainerDocumentWatermark,\n });\n\n if (listedDocuments.isFullListing) {\n // Initial probes consume ids as discovery hints and verify their own heads.\n options.onFullListing?.(\n listedDocuments.items.map((document) => document.id),\n );\n }\n\n return !complete &&\n discoveredDocuments.length === 0 &&\n tombstoneDocumentSummaries.length === 0\n ? null\n : [...discoveredDocuments, ...tombstoneDocumentSummaries];\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentDiscoveryEvidence.js","sourceRoot":"","sources":["documentDiscoveryEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DiscoveredDocumentInput } from \"../../data/documents/documentSummary\";\nimport type {\n DiscoveredDocumentCandidate,\n DocumentDiscoveryEvidenceStore,\n} from \"../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport { groupPendingDocumentDiscoveries } from \"./documentDiscoveryCandidates\";\nimport type { DiscoverContainerDocumentsOptions } from \"./documentDiscoveryTypes\";\nimport { documentHeadMatchesOrganization } from \"./documentHeadScope\";\nimport type {\n DocumentHeadLinkSetLoader,\n LocalDocumentAccessEpochLoader,\n} from \"./documentTombstoneEvidence\";\nimport {\n HEAD_LINK_SET_LOAD_CONCURRENCY,\n HEAD_LINK_SET_LOADS_PER_RUN,\n} from \"./documentTombstoneEvidence\";\n\nasync function verifyInput(\n input: DiscoveredDocumentCandidate,\n loadHead: DocumentHeadLinkSetLoader,\n loadLocalEpoch: LocalDocumentAccessEpochLoader,\n store: DocumentDiscoveryEvidenceStore,\n generation: number,\n organizationId: string | undefined,\n): Promise<DiscoveredDocumentInput | null | \"unavailable\"> {\n const localEpoch = await loadLocalEpoch(input.documentId).catch(\n () => Number.MAX_SAFE_INTEGER,\n );\n const cached = await store.loadHead(input.documentId, input.accessStateHash);\n const minimumEpoch = Math.max(localEpoch, input.accessEpoch);\n const head =\n cached && cached.accessEpoch >= minimumEpoch\n ? cached\n : await loadHead(\n input.documentId,\n input.accessEpoch >= localEpoch\n ? (input.accessStateHash ?? undefined)\n : undefined,\n );\n if (head === \"not-found\") return null;\n if (!head || head.accessEpoch < Math.max(localEpoch, input.accessEpoch))\n return \"unavailable\";\n if (!documentHeadMatchesOrganization(head, organizationId))\n return \"unavailable\";\n // A stale first lane must not hide a document present in another listed lane.\n const containerId = input.listedContainerIds.find((id) =>\n head.linkedContainerIds.includes(id),\n );\n if (!containerId) {\n // A same-epoch head can predate a link addition. Only the named head or\n // terminal signed purge evidence can settle a candidate without a retry.\n return head.accessEpoch > input.accessEpoch ||\n head.accessStateHash === input.accessStateHash ||\n (!head.accessStateHash && head.accessEpoch === Number.MAX_SAFE_INTEGER)\n ? null\n : \"unavailable\";\n }\n if (!head.accessStateHash) return \"unavailable\";\n if (!(await store.saveHead(input.documentId, head, generation)))\n return \"unavailable\";\n const { listedContainerIds: _listedContainerIds, ...document } = input;\n return {\n ...document,\n containerId,\n accessEpoch: head.accessEpoch,\n accessStateHash: head.accessStateHash,\n linkedContainerIds: head.linkedContainerIds,\n };\n}\n\n/**\n * Persist untrusted candidates before advancing listing watermarks. Each pass\n * checks a bounded batch; unavailable heads back off independently while verified\n * siblings and tombstones still settle. Acknowledgement follows local apply so\n * a crash cannot lose a candidate behind an already advanced listing watermark.\n */\nexport function createDiscoveredDocumentVerifier(\n organizationId: string | undefined,\n loadHead: DocumentHeadLinkSetLoader,\n loadLocalEpoch: LocalDocumentAccessEpochLoader,\n store: DocumentDiscoveryEvidenceStore,\n onPendingDiscovery?: ((delayMs: number) => void) | undefined,\n): DiscoverContainerDocumentsOptions[\"verifyDiscoveredDocuments\"] {\n return async (inputs, containerIds, generation, tombstones = []) => {\n const isCurrent = () => store.isCurrent(generation);\n const lanes = new Set(containerIds);\n const removed = tombstones.filter((row) => lanes.has(row.containerId));\n if (!(await store.stage(inputs, generation, removed)))\n return { inputs: [], isCurrent, commit: async () => true };\n const candidates = groupPendingDocumentDiscoveries(\n await store.pending(containerIds, HEAD_LINK_SET_LOADS_PER_RUN),\n );\n const verified = new Map<string, DiscoveredDocumentInput>();\n const settled: DiscoveredDocumentCandidate[] = [];\n let next = 0;\n const worker = async () => {\n while (next < candidates.length) {\n const group = candidates[next++];\n if (!group) break;\n const { input, rows } = group;\n const result = await verifyInput(\n input,\n loadHead,\n loadLocalEpoch,\n store,\n generation,\n organizationId,\n );\n if (result === \"unavailable\") {\n await Promise.all(rows.map((row) => store.defer(row, generation)));\n } else {\n if (result) verified.set(result.documentId, result);\n settled.push(...rows);\n }\n }\n };\n await Promise.all(\n Array.from(\n { length: Math.min(HEAD_LINK_SET_LOAD_CONCURRENCY, candidates.length) },\n worker,\n ),\n );\n return {\n inputs: [...verified.values()],\n isCurrent,\n commit: async () => {\n await store.acknowledge(settled, generation);\n const retryDelay = await store.retryDelay(containerIds);\n if (retryDelay !== null) onPendingDiscovery?.(retryDelay);\n return retryDelay === null;\n },\n };\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentFieldBlame.js","sourceRoot":"","sources":["documentFieldBlame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAEL,mBAAmB,GACpB,MAAM,sCAAsC,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,eAA8B,EAC9B,QAAqD;IAErD,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,wBAAwB,CAC3C,aAAa,CAAC,eAAe,CAAC,EAC9B,uBAAuB,CACxB,CAAC;QACF,OAAO,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { listSnapshotFieldEditors } from \"@tearleads/loro\";\nimport type { DocumentEditAttributionResponse } from \"@tearleads/validators/response\";\nimport { DOCUMENT_FIELDS_MAP_KEY } from \"../../data/documents/documentKinds\";\nimport {\n type DocumentFieldBlame,\n summarizeFieldBlame,\n} from \"../../data/documents/editAttribution\";\n\n/**\n * Per-field \"blame\" for a structured document: read the peer that last set each\n * field from the locally persisted snapshot and resolve it against the\n * attribution segments. Reconstructing the small `fields` map is cheap (no\n * per-character sweep), so this runs its own reconstruction independent of the\n * character-blame path. Returns null when it can't be produced — no local\n * snapshot or an unreadable one — mirroring the character-blame degrade-to-null;\n * a note (or any document without fields) yields an empty array, not null.\n */\nexport function computeFieldBlame(\n contentSnapshot: string | null,\n segments: DocumentEditAttributionResponse[\"segments\"],\n): DocumentFieldBlame[] | null {\n if (!contentSnapshot || contentSnapshot.length === 0) {\n return null;\n }\n try {\n const fieldEditors = listSnapshotFieldEditors(\n base64ToBytes(contentSnapshot),\n DOCUMENT_FIELDS_MAP_KEY,\n );\n return summarizeFieldBlame(fieldEditors, segments);\n } catch {\n return null;\n }\n}\n"]}
|