@tearleads/client-sdk 0.1.58 → 0.1.60
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 +17 -17
- package/Tearleads.js +15 -15
- package/Tearleads.js.map +1 -1
- package/client/{blobs.d.ts → blobs/index.d.ts} +1 -1
- package/client/{blobs.js → blobs/index.js} +3 -3
- package/client/blobs/index.js.map +1 -0
- package/client/{containerDocumentDiscovery.js → containerContents/documentDiscovery.js} +11 -11
- package/client/containerContents/documentDiscovery.js.map +1 -0
- package/client/{containerContents.d.ts → containerContents/index.d.ts} +13 -13
- package/client/{containerContents.js → containerContents/index.js} +18 -18
- package/client/containerContents/index.js.map +1 -0
- package/client/{containerContentsTypes.d.ts → containerContents/types.d.ts} +14 -14
- package/client/containerContents/types.js +2 -0
- package/client/containerContents/types.js.map +1 -0
- package/client/{deviceFirst.d.ts → deviceFirst/index.d.ts} +7 -7
- package/client/{deviceFirst.js → deviceFirst/index.js} +11 -11
- package/client/deviceFirst/index.js.map +1 -0
- package/client/{reconciledDocumentContentPull.js → deviceFirst/reconciledDocumentContentPull.js} +1 -1
- package/client/deviceFirst/reconciledDocumentContentPull.js.map +1 -0
- package/client/{documents.d.ts → documents/index.d.ts} +5 -5
- package/client/{documents.js → documents/index.js} +5 -5
- package/client/documents/index.js.map +1 -0
- package/client/{identity.d.ts → identity/index.d.ts} +2 -2
- package/client/{identity.js → identity/index.js} +5 -5
- package/client/identity/index.js.map +1 -0
- package/client/{identityKeyPackage.d.ts → identity/keyPackage.d.ts} +1 -1
- package/client/{identityKeyPackage.js → identity/keyPackage.js} +4 -4
- package/client/identity/keyPackage.js.map +1 -0
- package/client/{userIdentities.d.ts → identity/userIdentities.d.ts} +2 -2
- package/client/{userIdentities.js → identity/userIdentities.js} +4 -4
- package/client/identity/userIdentities.js.map +1 -0
- package/client/index.d.ts +18 -18
- package/client/index.js +9 -9
- package/client/index.js.map +1 -1
- package/client/organizations/currentPrincipalMutations.js.map +1 -1
- package/client/organizations/index.d.ts +2 -2
- package/client/organizations/index.js.map +1 -1
- package/client/organizations/organizationAccessRestoration.js.map +1 -1
- package/client/organizations/organizationDataUsage.d.ts +1 -1
- package/client/organizations/organizationDataUsage.js.map +1 -1
- package/client/organizations/organizationGroupNameHydration.js.map +1 -1
- package/client/organizations/organizationGroupPresentation.d.ts +1 -1
- package/client/organizations/organizationGroupPresentation.js.map +1 -1
- package/client/organizations/organizationMetadataProfileSync.js +1 -1
- package/client/organizations/organizationMetadataProfileSync.js.map +1 -1
- package/client/organizations/organizationReadModels.d.ts +1 -1
- package/client/organizations/organizationReadModels.js.map +1 -1
- package/client/organizations/organizationWorkflowRuntime.js.map +1 -1
- package/client/organizations/organizationsTypes.d.ts +1 -1
- package/client/organizations/organizationsTypes.js.map +1 -1
- package/client/organizations/principalContainerMutations.js.map +1 -1
- package/client/organizations/principalMutationRecovery.d.ts +1 -1
- package/client/organizations/principalMutationRecovery.js.map +1 -1
- package/client/organizations/principalMutationScope.js.map +1 -1
- package/client/organizations/principalMutations.d.ts +2 -2
- package/client/organizations/principalMutations.js.map +1 -1
- package/client/root/index.d.ts +1 -1
- package/client/root/index.js.map +1 -1
- package/client/{database.d.ts → runtime/database.d.ts} +1 -1
- package/client/{database.js → runtime/database.js} +1 -1
- package/client/runtime/database.js.map +1 -0
- package/client/{principalHistoryProtection.d.ts → runtime/principalHistoryProtection.d.ts} +1 -1
- package/client/{principalHistoryProtection.js → runtime/principalHistoryProtection.js} +2 -2
- package/client/runtime/principalHistoryProtection.js.map +1 -0
- package/client/{principalMutationApi.d.ts → runtime/principalMutationApi.d.ts} +4 -4
- package/client/{principalMutationApi.js → runtime/principalMutationApi.js} +2 -2
- package/client/runtime/principalMutationApi.js.map +1 -0
- package/client/{principalMutationDispatch.js → runtime/principalMutationDispatch.js} +2 -2
- package/client/runtime/principalMutationDispatch.js.map +1 -0
- package/client/runtime/rootContainerAdoption.js.map +1 -0
- package/client/{workflowRuntime.d.ts → runtime/workflowRuntime.d.ts} +12 -12
- package/client/{workflowRuntime.js → runtime/workflowRuntime.js} +5 -5
- package/client/runtime/workflowRuntime.js.map +1 -0
- package/client/{securityIncidents.d.ts → securityIncidents/index.d.ts} +3 -3
- package/client/{securityIncidents.js → securityIncidents/index.js} +5 -5
- package/client/securityIncidents/index.js.map +1 -0
- package/client/session/index.js +1 -1
- package/client/session/index.js.map +1 -1
- package/client/session/sessionIdentityTrust.d.ts +1 -1
- package/client/session/sessionLoginRefusal.js.map +1 -1
- package/client/session/sessionOrganizationCreation.js.map +1 -1
- package/client/session/sessionPurgeRecovery.js.map +1 -1
- package/client/session/sessionRootAuthority.js.map +1 -1
- package/client/session/sessionTypes.d.ts +3 -3
- package/client/session/sessionTypes.js.map +1 -1
- package/data/blobs/createBlobStore.d.ts +1 -1
- package/data/blobs/createBlobStore.js.map +1 -1
- package/data/blobs/encryptedBlobByteSource.js +1 -1
- package/data/blobs/encryptedBlobByteSource.js.map +1 -1
- package/data/blobs/encryptedBlobEnvelope.d.ts +1 -1
- package/data/blobs/encryptedBlobEnvelope.js +2 -2
- package/data/blobs/encryptedBlobEnvelope.js.map +1 -1
- package/data/blobs/encryptedBlobStore.d.ts +1 -1
- package/data/blobs/encryptedBlobStore.js +1 -1
- package/data/blobs/encryptedBlobStore.js.map +1 -1
- package/data/blobs/memoryBlobStore.d.ts +1 -1
- package/data/blobs/memoryBlobStore.js +1 -1
- package/data/blobs/memoryBlobStore.js.map +1 -1
- package/data/blobs/opfsBlobStore.d.ts +1 -1
- package/data/blobs/opfsBlobStore.js +1 -1
- package/data/blobs/opfsBlobStore.js.map +1 -1
- package/data/containers/containerMetadataDocument.js +1 -1
- package/data/containers/containerMetadataDocument.js.map +1 -1
- package/data/containers/shared/events.js +1 -1
- package/data/containers/shared/events.js.map +1 -1
- package/data/containers/shared/heldContainerHeads.js +1 -1
- package/data/containers/shared/heldContainerHeads.js.map +1 -1
- package/data/containers/shared/mutationAcknowledgement.js +1 -1
- package/data/containers/shared/mutationAcknowledgement.js.map +1 -1
- package/data/containers/shared/principalPolicies.js +1 -1
- package/data/containers/shared/principalPolicies.js.map +1 -1
- package/data/containers/shared/readers.js +2 -2
- package/data/containers/shared/readers.js.map +1 -1
- package/data/documents/attachmentContentIdentity.js +1 -1
- package/data/documents/attachmentContentIdentity.js.map +1 -1
- package/data/documents/blob/shared/blobEnvelopeStream.js.map +1 -1
- package/data/documents/blob/shared/blobSourceSnapshot.d.ts +1 -1
- package/data/documents/blob/shared/blobSourceSnapshot.js.map +1 -1
- package/data/documents/blob/shared/chunkedBlobCrypto.js.map +1 -1
- package/data/documents/blob/shared/encryptedUploadParts.js.map +1 -1
- package/data/documents/blob/shared/events.js +1 -1
- package/data/documents/blob/shared/events.js.map +1 -1
- package/data/documents/blob/shared/types.d.ts +2 -2
- package/data/documents/blob/shared/types.js.map +1 -1
- package/data/documents/shared/containerKekPathHistory.js +1 -1
- package/data/documents/shared/containerKekPathHistory.js.map +1 -1
- package/data/documents/shared/containerKekPathVerification.d.ts +1 -1
- package/data/documents/shared/containerKekPathVerification.js +1 -1
- package/data/documents/shared/events.js +1 -1
- package/data/documents/shared/events.js.map +1 -1
- package/data/documents/shared/manifestBundleReaders.js +2 -2
- package/data/documents/shared/manifestBundleReaders.js.map +1 -1
- package/data/documents/shared/projection.d.ts +1 -1
- package/data/documents/shared/projection.js +2 -2
- package/data/documents/shared/projection.js.map +1 -1
- package/data/documents/shared/projectionContentKeys.d.ts +1 -1
- package/data/documents/shared/readers.js +3 -3
- package/data/documents/shared/readers.js.map +1 -1
- package/data/documents/shared/stableDocumentId.js +1 -1
- package/data/documents/shared/stableDocumentId.js.map +1 -1
- package/data/documents/shared/types.d.ts +1 -1
- package/data/documents/shared/types.js +1 -1
- package/data/{keyingCanonicalJson.js → keying/canonicalJson.js} +3 -3
- package/data/keying/canonicalJson.js.map +1 -0
- package/data/keyingProjectionVerification/bundleVerification.js +1 -1
- package/data/keyingProjectionVerification/bundleVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerAncestorCitations.js +1 -1
- package/data/keyingProjectionVerification/containerAncestorCitations.js.map +1 -1
- package/data/keyingProjectionVerification/containerManifestVerification.js +1 -1
- package/data/keyingProjectionVerification/containerManifestVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentManifestVerification.js +1 -1
- package/data/keyingProjectionVerification/documentManifestVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js +1 -1
- package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
- package/data/keyingProjectionVerification/error.js +1 -1
- package/data/keyingProjectionVerification/error.js.map +1 -1
- package/data/keyingProjectionVerification/index.d.ts +9 -0
- package/data/{keyingProjectionVerification.js → keyingProjectionVerification/index.js} +8 -8
- package/data/keyingProjectionVerification/index.js.map +1 -0
- package/data/keyingProjectionVerification/principalPolicyCache.js +1 -1
- package/data/keyingProjectionVerification/principalPolicyCache.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicyVerification.js +1 -1
- package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
- package/data/keyingProjectionVerification/readers.d.ts +1 -1
- package/data/keyingProjectionVerification/readers.js +3 -3
- package/data/keyingProjectionVerification/readers.js.map +1 -1
- package/data/keyingProjectionVerification/userKeyResolver.d.ts +1 -1
- package/data/keyingProjectionVerification/userKeyResolver.js.map +1 -1
- package/data/persistence/containers/containerPersistence.js +1 -1
- package/data/persistence/containers/containerPersistence.js.map +1 -1
- package/data/persistence/documents/documentDiscoveryCandidate.js +1 -1
- package/data/persistence/documents/documentDiscoveryCandidate.js.map +1 -1
- package/data/persistence/documents/documentDiscoveryEvidencePersistence.js +1 -1
- package/data/persistence/documents/documentDiscoveryEvidencePersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentProjectionRows.js +1 -1
- package/data/persistence/documents/internal/documentProjectionRows.js.map +1 -1
- package/data/persistence/documents/internal/documentRows.js +1 -1
- package/data/persistence/documents/internal/documentRows.js.map +1 -1
- package/data/persistence/principalPolicyBundleIntegrity.js +1 -1
- package/data/persistence/principalPolicyBundleIntegrity.js.map +1 -1
- package/data/persistence/principalPolicyReferenceCheckpoint.js +1 -1
- package/data/persistence/principalPolicyReferenceCheckpoint.js.map +1 -1
- package/data/persistence/principalPolicyReferenceIndexPersistence.js +1 -1
- package/data/persistence/principalPolicyReferenceIndexPersistence.js.map +1 -1
- package/data/persistence/principalPolicyReferencePersistence.js +1 -1
- package/data/persistence/principalPolicyReferencePersistence.js.map +1 -1
- package/data/persistence/securityIncidentPersistence.js.map +1 -1
- package/data/persistence/verifiedPrincipalPolicyBundle.js +1 -1
- package/data/persistence/verifiedPrincipalPolicyBundle.js.map +1 -1
- package/data/persistence/verifiedPrincipalPolicyCurrent.js +1 -1
- package/data/persistence/verifiedPrincipalPolicyCurrent.js.map +1 -1
- package/data/principals/principalMutationJournal.js +1 -1
- package/data/principals/principalMutationJournal.js.map +1 -1
- package/data/{securityIncidents.d.ts → shared/securityIncidents.d.ts} +1 -1
- package/data/sqlite/documentRecordPersistence.js +1 -1
- package/data/sqlite/documentRecordPersistence.js.map +1 -1
- package/data/sync/crdtPeerSeed.d.ts +18 -0
- package/data/sync/originatedDocuments.d.ts +1 -1
- package/data/sync/originatedDocuments.js.map +1 -1
- package/data/sync/syncCoordinator.d.ts +1 -1
- package/data/sync/syncCoordinator.js.map +1 -1
- package/package.json +1 -1
- package/stores/container-contents/backgroundHydration.js +1 -1
- package/stores/container-contents/backgroundHydration.js.map +1 -1
- package/stores/container-contents/containerContentsStore.d.ts +1 -1
- package/stores/container-contents/containerContentsStore.js.map +1 -1
- package/stores/container-contents/localRefresh.js +1 -1
- package/stores/container-contents/localRefresh.js.map +1 -1
- package/stores/container-contents/remoteContainerIngestion.js +1 -1
- package/stores/container-contents/remoteContainerIngestion.js.map +1 -1
- package/stores/container-contents/remoteWriteQueue.js +1 -1
- package/stores/container-contents/remoteWriteQueue.js.map +1 -1
- package/stores/container-contents/systemContainerHydration.js +1 -1
- package/stores/container-contents/systemContainerHydration.js.map +1 -1
- package/stores/container-contents/utils.js +1 -1
- package/stores/container-contents/utils.js.map +1 -1
- package/stores/documents/documentStore/attachmentIntents.js +1 -1
- package/stores/documents/documentStore/attachmentIntents.js.map +1 -1
- package/stores/documents/documentStore/attachmentSourceUpload.js.map +1 -1
- package/stores/documents/documentStore/attachmentStaging.js +1 -1
- package/stores/documents/documentStore/attachmentStaging.js.map +1 -1
- package/stores/documents/documentStore/attachmentUploadLane.js.map +1 -1
- package/stores/documents/documentStore/persistence.js +2 -2
- package/stores/documents/documentStore/persistence.js.map +1 -1
- package/stores/documents/documentStore/state.js +1 -1
- package/stores/documents/documentStore/state.js.map +1 -1
- package/stores/documents/documentStore/storedDocument.js +1 -1
- package/stores/documents/documentStore/storedDocument.js.map +1 -1
- package/stores/documents/documentStore/syncAttachments.js.map +1 -1
- package/stores/documents/documentStore.d.ts +1 -1
- package/stores/documents/documentStore.js.map +1 -1
- package/stores/documents/registry.d.ts +1 -1
- package/stores/documents/registry.js.map +1 -1
- package/stores/documents/types.d.ts +1 -1
- package/stores/documents/types.js.map +1 -1
- package/stores/local-projection/registry.d.ts +1 -1
- package/stores/local-projection/registry.js.map +1 -1
- package/sync/reconciliation/serviceTypes.d.ts +1 -1
- package/sync/reconciliation/serviceTypes.js.map +1 -1
- package/sync/reconciliation/triggers.d.ts +1 -1
- package/sync/reconciliation/triggers.js.map +1 -1
- package/workflows/blobs/attachmentBindingVerification.js +2 -2
- package/workflows/blobs/attachmentBindingVerification.js.map +1 -1
- package/workflows/blobs/blobChunkDecryption.js.map +1 -1
- package/workflows/blobs/decrypt.d.ts +1 -1
- package/workflows/blobs/decrypt.js +2 -2
- package/workflows/blobs/decrypt.js.map +1 -1
- package/workflows/blobs/detach.js +2 -2
- package/workflows/blobs/detach.js.map +1 -1
- package/workflows/blobs/hydrate.d.ts +3 -3
- package/workflows/blobs/hydrate.js +1 -1
- package/workflows/blobs/hydrate.js.map +1 -1
- package/workflows/blobs/hydrationResults.js.map +1 -1
- package/workflows/blobs/index.d.ts +2 -2
- package/workflows/blobs/index.js +1 -1
- package/workflows/blobs/index.js.map +1 -1
- package/workflows/blobs/multipartFirstParts.js.map +1 -1
- package/workflows/blobs/retainedAttachmentVerification.js +1 -1
- package/workflows/blobs/upload.js +3 -3
- package/workflows/blobs/upload.js.map +1 -1
- package/workflows/container-contents/container-state/createAdoption.js +1 -1
- package/workflows/container-contents/container-state/createAdoption.js.map +1 -1
- package/workflows/container-contents/container-state/createChild.js +1 -1
- package/workflows/container-contents/container-state/createChild.js.map +1 -1
- 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/groupGrantVerification.js +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/purgeTreeScope.js +1 -1
- package/workflows/container-contents/container-state/purgeTreeScope.js.map +1 -1
- package/workflows/container-contents/container-state/share.js +1 -1
- package/workflows/container-contents/documentDiscoveryInputs.js +1 -1
- package/workflows/container-contents/documentDiscoveryInputs.js.map +1 -1
- package/workflows/container-contents/documentInfo.d.ts +1 -1
- package/workflows/container-contents/documentInfo.js.map +1 -1
- package/workflows/container-contents/documentLinks.d.ts +1 -1
- package/workflows/container-contents/documentLinks.js +1 -1
- package/workflows/container-contents/documentLinks.js.map +1 -1
- package/workflows/container-contents/documentMoveIntentSync.js +1 -1
- package/workflows/container-contents/documentMoveIntentSync.js.map +1 -1
- package/workflows/container-contents/documentPurge.d.ts +1 -1
- package/workflows/container-contents/documentPurge.js +1 -1
- package/workflows/container-contents/documentPurge.js.map +1 -1
- package/workflows/container-contents/documentQueries/rows.js +1 -1
- package/workflows/container-contents/documentQueries/rows.js.map +1 -1
- package/workflows/container-contents/metadata.d.ts +1 -1
- package/workflows/container-contents/metadataMutationPreparation.js +1 -1
- package/workflows/container-contents/metadataMutationPreparation.js.map +1 -1
- package/workflows/container-contents/metadataRemoteSync.d.ts +1 -1
- package/workflows/container-contents/metadataSyncErrors.js.map +1 -1
- package/workflows/container-contents/projectionKeys.d.ts +1 -1
- package/workflows/container-contents/syncLane.d.ts +1 -1
- package/workflows/container-contents/syncLane.js.map +1 -1
- package/workflows/containers/child/carriedDescendantRekeys.js +1 -1
- package/workflows/containers/child/create.d.ts +1 -1
- package/workflows/containers/child/create.js +2 -2
- package/workflows/containers/child/create.js.map +1 -1
- package/workflows/containers/child/createProjection.js +1 -1
- package/workflows/containers/child/createProjection.js.map +1 -1
- package/workflows/containers/child/createSubmission.d.ts +2 -2
- package/workflows/containers/child/createSubmission.js.map +1 -1
- package/workflows/containers/child/move.d.ts +2 -2
- package/workflows/containers/child/move.js +2 -2
- package/workflows/containers/child/move.js.map +1 -1
- package/workflows/containers/child/moveWraps.js +1 -1
- package/workflows/containers/child/mutationRequestCore.js +1 -1
- package/workflows/containers/child/mutationRequestCore.js.map +1 -1
- package/workflows/containers/child/mutationSubmit.js.map +1 -1
- package/workflows/containers/child/recite.js.map +1 -1
- package/workflows/containers/child/recitePlan.js +1 -1
- package/workflows/containers/child/recitePlan.js.map +1 -1
- package/workflows/containers/child/rekey.d.ts +1 -1
- package/workflows/containers/child/rekey.js +2 -2
- package/workflows/containers/child/rekey.js.map +1 -1
- package/workflows/containers/child/rekeyProjection.js +1 -1
- package/workflows/containers/child/rekeyProjection.js.map +1 -1
- package/workflows/containers/child/rekeyRemote.d.ts +2 -2
- package/workflows/containers/child/rekeyRemote.js.map +1 -1
- package/workflows/containers/child/revoke.d.ts +2 -2
- package/workflows/containers/child/revoke.js +2 -2
- package/workflows/containers/child/revoke.js.map +1 -1
- package/workflows/containers/child/rotationPrincipalPolicies.js +1 -1
- package/workflows/containers/child/runtimeCurrentGroupShare.js +1 -1
- package/workflows/containers/child/share.d.ts +2 -2
- package/workflows/containers/child/share.js +1 -1
- package/workflows/containers/child/share.js.map +1 -1
- package/workflows/containers/child/shareAncestorRepair.js.map +1 -1
- package/workflows/containers/child/shareMaterialization.d.ts +1 -1
- package/workflows/containers/child/sharePlanCore.d.ts +1 -1
- package/workflows/containers/child/sharePlanCore.js +1 -1
- package/workflows/containers/root/create.js +1 -1
- package/workflows/containers/root/create.js.map +1 -1
- package/workflows/containers/root/initialGroupPolicy.js +1 -1
- package/workflows/containers/root/initialGroupPolicy.js.map +1 -1
- package/workflows/documents/create.d.ts +1 -1
- package/workflows/documents/create.js +1 -1
- package/workflows/documents/documentMutationPreparation.js +1 -1
- package/workflows/documents/documentMutationPreparation.js.map +1 -1
- package/workflows/documents/historyContent.js +1 -1
- package/workflows/documents/historyContent.js.map +1 -1
- package/workflows/documents/linkSet.js +1 -1
- package/workflows/documents/linkSet.js.map +1 -1
- package/workflows/documents/linkSetAuthority.js +1 -1
- package/workflows/documents/linkSetBlobRewraps.js +2 -2
- package/workflows/documents/linkSetBlobRewraps.js.map +1 -1
- package/workflows/documents/linkSetRemote.d.ts +1 -1
- package/workflows/documents/linkSetRemote.js +1 -1
- package/workflows/documents/orphanBlobReclaims.js +1 -1
- package/workflows/documents/orphanBlobReclaims.js.map +1 -1
- package/workflows/documents/projectionKeys.d.ts +1 -1
- package/workflows/documents/purge.d.ts +1 -1
- package/workflows/documents/purge.js +2 -2
- package/workflows/documents/purge.js.map +1 -1
- package/workflows/documents/readOnlySync.d.ts +1 -1
- package/workflows/documents/readOnlySync.js +1 -1
- package/workflows/documents/readOnlySync.js.map +1 -1
- package/workflows/documents/sync.js +1 -1
- package/workflows/documents/syncContainerRekeyPreparation.js +1 -1
- package/workflows/documents/syncLane.d.ts +1 -1
- package/workflows/documents/syncLane.js.map +1 -1
- package/workflows/documents/syncPlanIdentity.js +1 -1
- package/workflows/documents/syncPlanIdentity.js.map +1 -1
- package/workflows/documents/syncRepairAccess.js +1 -1
- package/workflows/documents/syncSubmittedResult.js +1 -1
- package/workflows/organizations/authoredPrincipalPolicyWarmer.js +1 -1
- package/workflows/organizations/authoredPrincipalPolicyWarmer.js.map +1 -1
- package/workflows/organizations/containerGrantRevocation.d.ts +2 -2
- package/workflows/organizations/containerGrantRevocation.js.map +1 -1
- package/workflows/organizations/createCurrentOrganizationGroup.js.map +1 -1
- package/workflows/organizations/currentOrganizationGroupNames.js.map +1 -1
- package/workflows/organizations/currentPolicyMutationAcknowledgement.js +1 -1
- package/workflows/organizations/currentPolicyMutationAcknowledgement.js.map +1 -1
- package/workflows/organizations/groupCreation.d.ts +1 -1
- package/workflows/organizations/groupCreation.js.map +1 -1
- package/workflows/organizations/groupMetadataAccess.d.ts +1 -1
- package/workflows/organizations/groupMetadataContainerAuthority.js.map +1 -1
- package/workflows/organizations/groupMetadataRuntime.js.map +1 -1
- package/workflows/organizations/groupNameUniqueness.js.map +1 -1
- package/workflows/organizations/groupPolicyMutationAcknowledgement.js +1 -1
- package/workflows/organizations/groupPolicyMutationAcknowledgement.js.map +1 -1
- package/workflows/organizations/groupPolicyRequests.js.map +1 -1
- package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
- package/workflows/organizations/organizationGroupDirectory.js.map +1 -1
- package/workflows/organizations/organizationProfile.js +1 -1
- package/workflows/organizations/organizationProfile.js.map +1 -1
- package/workflows/organizations/policyHistoryCache.js.map +1 -1
- package/workflows/organizations/principalContainerRematerialization.js +1 -1
- package/workflows/organizations/principalContainerRematerializationPlanning.js.map +1 -1
- package/workflows/organizations/principalMutationJournalManagement.js +1 -1
- package/workflows/organizations/principalMutationJournalManagement.js.map +1 -1
- package/workflows/organizations/principalMutationReceipt.js +1 -1
- package/workflows/organizations/principalMutationReceipt.js.map +1 -1
- package/workflows/organizations/principalPolicy.d.ts +1 -1
- package/workflows/organizations/principalPolicy.js.map +1 -1
- package/workflows/organizations/principalPolicyReceiptArtifacts.js +1 -1
- package/workflows/organizations/principalPolicyReceiptArtifacts.js.map +1 -1
- package/workflows/organizations/rosterProfileContainer.js +1 -1
- package/workflows/organizations/rosterProfileContainer.js.map +1 -1
- package/workflows/principals/policyCache.d.ts +1 -1
- package/workflows/principals/policyCache.js +2 -2
- package/workflows/principals/policyCache.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/runtimePolicyWarmer.js +1 -1
- package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
- package/workflows/registration/persistRegistrationBootstrap.js +1 -1
- package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
- package/workflows/runtimeInput.d.ts +3 -3
- package/workflows/runtimeInput.js.map +1 -1
- package/workflows/sync/index.d.ts +2 -1
- package/workflows/sync/index.js +2 -1
- package/workflows/sync/index.js.map +1 -1
- package/client/blobs.js.map +0 -1
- package/client/containerContents.js.map +0 -1
- package/client/containerContentsTypes.js +0 -2
- package/client/containerContentsTypes.js.map +0 -1
- package/client/containerDocumentDiscovery.js.map +0 -1
- package/client/database.js.map +0 -1
- package/client/deviceFirst.js.map +0 -1
- package/client/documents.js.map +0 -1
- package/client/identity.js.map +0 -1
- package/client/identityKeyPackage.js.map +0 -1
- package/client/principalHistoryProtection.js.map +0 -1
- package/client/principalMutationApi.js.map +0 -1
- package/client/principalMutationDispatch.js.map +0 -1
- package/client/reconciledDocumentContentPull.js.map +0 -1
- package/client/rootContainerAdoption.js.map +0 -1
- package/client/securityIncidents.js.map +0 -1
- package/client/userIdentities.js.map +0 -1
- package/client/workflowRuntime.js.map +0 -1
- package/data/keyingCanonicalJson.js.map +0 -1
- package/data/keyingProjectionVerification.d.ts +0 -9
- package/data/keyingProjectionVerification.js.map +0 -1
- /package/client/{fileSaver.d.ts → host/fileSaver.d.ts} +0 -0
- /package/client/{fileSaver.js → host/fileSaver.js} +0 -0
- /package/client/{fileSaver.js.map → host/fileSaver.js.map} +0 -0
- /package/client/{logger.d.ts → host/logger.d.ts} +0 -0
- /package/client/{logger.js → host/logger.js} +0 -0
- /package/client/{logger.js.map → host/logger.js.map} +0 -0
- /package/client/{apiVersion.d.ts → runtime/apiVersion.d.ts} +0 -0
- /package/client/{apiVersion.js → runtime/apiVersion.js} +0 -0
- /package/client/{apiVersion.js.map → runtime/apiVersion.js.map} +0 -0
- /package/client/{events.d.ts → runtime/events.d.ts} +0 -0
- /package/client/{events.js → runtime/events.js} +0 -0
- /package/client/{events.js.map → runtime/events.js.map} +0 -0
- /package/client/{listenerSet.js → runtime/listenerSet.js} +0 -0
- /package/client/{listenerSet.js.map → runtime/listenerSet.js.map} +0 -0
- /package/client/{network.d.ts → runtime/network.d.ts} +0 -0
- /package/client/{network.js → runtime/network.js} +0 -0
- /package/client/{network.js.map → runtime/network.js.map} +0 -0
- /package/client/{principalMutationDeadline.js → runtime/principalMutationDeadline.js} +0 -0
- /package/client/{principalMutationDeadline.js.map → runtime/principalMutationDeadline.js.map} +0 -0
- /package/client/{rootContainerAdoption.js → runtime/rootContainerAdoption.js} +0 -0
- /package/client/{syncBillingGate.d.ts → runtime/syncBillingGate.d.ts} +0 -0
- /package/client/{syncBillingGate.js → runtime/syncBillingGate.js} +0 -0
- /package/client/{syncBillingGate.js.map → runtime/syncBillingGate.js.map} +0 -0
- /package/data/{blobContracts.d.ts → blobs/blobContracts.d.ts} +0 -0
- /package/data/{blobContracts.js → blobs/blobContracts.js} +0 -0
- /package/data/{blobContracts.js.map → blobs/blobContracts.js.map} +0 -0
- /package/data/{accessLevel.js → keying/accessLevel.js} +0 -0
- /package/data/{accessLevel.js.map → keying/accessLevel.js.map} +0 -0
- /package/data/{stableUuid.js → keying/stableUuid.js} +0 -0
- /package/data/{stableUuid.js.map → keying/stableUuid.js.map} +0 -0
- /package/data/{principalPolicyStates.js → principals/principalPolicyStates.js} +0 -0
- /package/data/{principalPolicyStates.js.map → principals/principalPolicyStates.js.map} +0 -0
- /package/data/{domainScope.d.ts → shared/domainScope.d.ts} +0 -0
- /package/data/{domainScope.js → shared/domainScope.js} +0 -0
- /package/data/{domainScope.js.map → shared/domainScope.js.map} +0 -0
- /package/data/{errorMessage.js → shared/errorMessage.js} +0 -0
- /package/data/{errorMessage.js.map → shared/errorMessage.js.map} +0 -0
- /package/data/{recordReaders.d.ts → shared/recordReaders.d.ts} +0 -0
- /package/data/{recordReaders.js → shared/recordReaders.js} +0 -0
- /package/data/{recordReaders.js.map → shared/recordReaders.js.map} +0 -0
- /package/data/{securityIncidents.js → shared/securityIncidents.js} +0 -0
- /package/data/{securityIncidents.js.map → shared/securityIncidents.js.map} +0 -0
- /package/data/{crdtPeerSeed.js → sync/crdtPeerSeed.js} +0 -0
- /package/data/{crdtPeerSeed.js.map → sync/crdtPeerSeed.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { serializeKeyingCanonicalJson } from "
|
|
2
|
-
import { isPlainObject } from "
|
|
1
|
+
import { serializeKeyingCanonicalJson } from "../../internal/crypto/index.js";
|
|
2
|
+
import { isPlainObject } from "../../internal/validators/isPlainObject.js";
|
|
3
3
|
function isCanonicalJsonScalar(value) {
|
|
4
4
|
return (value === null ||
|
|
5
5
|
typeof value === "string" ||
|
|
@@ -80,4 +80,4 @@ export function readCanonicalRecords(values, label) {
|
|
|
80
80
|
export function canonicalKeyingJsonString(value, label) {
|
|
81
81
|
return serializeKeyingCanonicalJson(readCanonicalJson(value, label));
|
|
82
82
|
}
|
|
83
|
-
//# sourceMappingURL=
|
|
83
|
+
//# sourceMappingURL=canonicalJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalJson.js","sourceRoot":"","sources":["canonicalJson.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeyingCanonicalJson } from \"@tearleads/crypto\";\nimport { serializeKeyingCanonicalJson } from \"@tearleads/crypto\";\nimport { isPlainObject } from \"@tearleads/validators/isPlainObject\";\n\ninterface CanonicalJsonFrame {\n leave?: object;\n value?: unknown;\n}\n\nfunction isCanonicalJsonScalar(value: unknown): boolean {\n return (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (typeof value === \"number\" && Number.isFinite(value))\n );\n}\n\nfunction pushCanonicalJsonChildren(\n value: unknown,\n active: WeakSet<object>,\n pending: CanonicalJsonFrame[],\n): boolean {\n if (Array.isArray(value)) {\n if (active.has(value)) {\n return false;\n }\n active.add(value);\n pending.push({ leave: value });\n for (let index = 0; index < value.length; index += 1) {\n if (!(index in value)) {\n return false;\n }\n pending.push({ value: value[index] });\n }\n return true;\n }\n\n if (!isPlainObject(value)) {\n return false;\n }\n if (active.has(value)) {\n return false;\n }\n active.add(value);\n pending.push({ leave: value });\n for (const key of Object.keys(value)) {\n pending.push({ value: Reflect.get(value, key) });\n }\n return true;\n}\n\nfunction isCanonicalJson(value: unknown): value is KeyingCanonicalJson {\n const pending: CanonicalJsonFrame[] = [{ value }];\n const active = new WeakSet<object>();\n\n while (pending.length > 0) {\n const frame = pending.pop();\n if (!frame) {\n break;\n }\n if (frame.leave) {\n active.delete(frame.leave);\n continue;\n }\n\n const item = frame.value;\n if (isCanonicalJsonScalar(item)) {\n continue;\n }\n if (!pushCanonicalJsonChildren(item, active, pending)) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function readCanonicalJson(\n value: unknown,\n label: string,\n): KeyingCanonicalJson {\n if (!isCanonicalJson(value)) {\n throw new Error(`${label} must be canonical JSON`);\n }\n return value;\n}\n\nexport function readCanonicalRecord(\n value: unknown,\n label: string,\n): Record<string, unknown> {\n if (!isPlainObject(value)) {\n throw new Error(`${label} must be an object`);\n }\n readCanonicalJson(value, label);\n return value;\n}\n\nexport function readCanonicalRecords(\n values: readonly unknown[],\n label: string,\n): Record<string, unknown>[] {\n return values.map((value, index) =>\n readCanonicalRecord(value, `${label}[${index}]`),\n );\n}\n\n/**\n * Canonicalize-then-serialize, the one string form every keying equality\n * check compares. Both halves are shared already; composing them per-file\n * invited the composition itself to drift.\n */\nexport function canonicalKeyingJsonString(\n value: unknown,\n label: string,\n): string {\n return serializeKeyingCanonicalJson(readCanonicalJson(value, label));\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyingVerificationError, verifySignedAccessEvent, } from "../../internal/crypto/index.js";
|
|
2
|
-
import { canonicalKeyingJsonString, readCanonicalJson, readCanonicalRecord, } from "../
|
|
2
|
+
import { canonicalKeyingJsonString, readCanonicalJson, readCanonicalRecord, } from "../keying/canonicalJson.js";
|
|
3
3
|
import { ProjectionDependencyUnavailableError } from "./dependencyUnavailable.js";
|
|
4
4
|
import { readKeyingVerificationShape } from "./error.js";
|
|
5
5
|
import { readAccessEvent, readRecordString, readRequiredRecordValue, } from "./readers.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundleVerification.js","sourceRoot":"","sources":["bundleVerification.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,
|
|
1
|
+
{"version":3,"file":"bundleVerification.js","sourceRoot":"","sources":["bundleVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n verifySignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWireResponse } from \"@tearleads/validators/response\";\nimport type { AccessEventBundleWireResponse } from \"@tearleads/validators/util\";\nimport {\n canonicalKeyingJsonString,\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../keying/canonicalJson\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { readKeyingVerificationShape } from \"./error\";\nimport {\n readAccessEvent,\n readRecordString,\n readRequiredRecordValue,\n} from \"./readers\";\nimport type { ProjectionUserKeyResolver } from \"./types\";\n\nfunction canonicalBundleJson(value: unknown, label: string): string {\n return readKeyingVerificationShape(() =>\n canonicalKeyingJsonString(value, label),\n );\n}\n\nexport function assertCanonicalEqual(input: {\n readonly actual: unknown;\n readonly expected: unknown;\n readonly label: string;\n}): void {\n if (\n canonicalBundleJson(input.actual, `${input.label} actual`) !==\n canonicalBundleJson(input.expected, `${input.label} expected`)\n ) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n `${input.label} mismatch`,\n );\n }\n}\n\nexport function addBundleByHash(\n bundlesByHash: Map<string, AccessManifestBundleWireResponse>,\n bundle: AccessManifestBundleWireResponse,\n label: string,\n): void {\n const existing = bundlesByHash.get(bundle.manifestHash);\n if (!existing) {\n bundlesByHash.set(bundle.manifestHash, bundle);\n return;\n }\n\n if (\n canonicalBundleJson(existing, `${label} existing`) !==\n canonicalBundleJson(bundle, `${label} duplicate`)\n ) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n `Writer projection has equivocal manifest bundle ${bundle.manifestHash}`,\n );\n }\n}\n\nfunction readStandaloneEventBundle(\n bundle: AccessEventBundleWireResponse,\n label: string,\n) {\n return readKeyingVerificationShape(() => {\n const eventBundle = readCanonicalRecord(bundle, `${label} event bundle`);\n const eventHash = readRecordString(\n eventBundle,\n \"eventHash\",\n `${label} event bundle`,\n );\n const event = readAccessEvent(\n readRequiredRecordValue(eventBundle, \"event\", `${label} event bundle`),\n `${label} signed event`,\n );\n const body = readCanonicalJson(\n readRequiredRecordValue(eventBundle, \"body\", `${label} event bundle`),\n `${label} event body`,\n );\n return { eventHash, event, body };\n });\n}\n\nexport async function verifyStandaloneAccessEventBundle(input: {\n readonly bundle: AccessEventBundleWireResponse;\n readonly label: string;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}) {\n const { eventHash, event, body } = readStandaloneEventBundle(\n input.bundle,\n input.label,\n );\n const userKey = await input.resolveUserKey(event.signerUserId);\n if (!userKey) {\n throw new ProjectionDependencyUnavailableError(\n `${input.label} signer public key could not be resolved for ${event.signerUserId}`,\n );\n }\n\n const verified = await verifySignedAccessEvent({\n body,\n event,\n signerPublicKey: userKey.signingPublicKey,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n if (verified.value.eventHash !== eventHash) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n `${input.label} event hash mismatch`,\n );\n }\n\n return verified.value;\n}\n\nexport function verifyAccessEventBundle(input: {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly label: string;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}) {\n return verifyStandaloneAccessEventBundle({\n bundle: input.bundle.event,\n label: input.label,\n resolveUserKey: input.resolveUserKey,\n });\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyingVerificationError, } from "../../internal/crypto/index.js";
|
|
2
|
-
import { readCanonicalRecord } from "../
|
|
2
|
+
import { readCanonicalRecord } from "../keying/canonicalJson.js";
|
|
3
3
|
import { readKeyingVerificationShape } from "./error.js";
|
|
4
4
|
import { readRecordNullableString } from "./readers.js";
|
|
5
5
|
function bundleContainerId(bundle, label) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerAncestorCitations.js","sourceRoot":"","sources":["containerAncestorCitations.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type VerifiedAccessEvent,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWireResponse } from \"@tearleads/validators/response\";\nimport { readCanonicalRecord } from \"../keyingCanonicalJson\";\nimport { readKeyingVerificationShape } from \"./error\";\nimport { readRecordNullableString } from \"./readers\";\n\n/**\n * A container manifest pins the parent manifest it was created or moved\n * under, and successors inherit that pin, so the pin says nothing about the\n * ancestor heads a later grant, revoke, or rekey was actually authorized\n * under. Those heads are in the event: every container event signs the\n * manifest hashes of the path it was committed against, and the API refuses\n * an event whose citations are not the current heads at commit time. So a\n * head's authorization path is rebuilt here from its citations, root to\n * parent, and the signer is checked against those heads rather than against\n * whatever path the server pairs with the manifest.\n *\n * A head must also cite, for every ancestor, a head that is or descends from\n * the head an earlier signed statement already established, so an ancestor\n * head one signed statement established can never be rolled back or forked\n * away for a later one.\n *\n * As with principal policies, a successor new to a device need not cite the\n * authority's served current head. An honest server serves a\n * child head citing the ancestor head that was current when it was\n * committed, signed by a member since revoked at that ancestor, and refusing\n * that shape would leave every device holding the child unable to supersede\n * it. What can be refused is the opposite disagreement: a served current\n * ancestor head that does not descend from a head the child's signed event\n * proves exists is a stale or forked ancestor, whatever the server calls\n * current.\n */\n\ninterface CitedAncestorResolutionInput {\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly label: string;\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n readonly verifyHistoryBundle: (\n bundle: AccessManifestBundleWireResponse,\n label: string,\n ) => Promise<VerifiedContainerAccessManifest>;\n}\n\nfunction bundleContainerId(\n bundle: AccessManifestBundleWireResponse,\n label: string,\n): string | null {\n return readKeyingVerificationShape(() =>\n readRecordNullableString(\n readCanonicalRecord(bundle.state, `${label} state`),\n \"containerId\",\n `${label} state`,\n ),\n );\n}\n\nfunction citedContainerId(\n input: CitedLineageInput,\n manifestHash: string,\n): string | null {\n const verified = input.verifiedByHash.get(manifestHash);\n if (verified) return verified.state.containerId;\n const bundle = input.bundlesByHash.get(manifestHash);\n return bundle ? bundleContainerId(bundle, input.label) : null;\n}\n\nfunction citedManifestHashForContainer(\n input: CitedAncestorResolutionInput,\n cited: readonly string[],\n containerId: string,\n): string {\n const hashes = cited.filter(\n (manifestHash) => citedContainerId(input, manifestHash) === containerId,\n );\n const [manifestHash] = hashes;\n if (manifestHash === undefined) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} does not cite a served head of its parent container ${containerId}`,\n );\n }\n if (hashes.length > 1) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `${input.label} cites more than one head of container ${containerId}`,\n );\n }\n return manifestHash;\n}\n\nasync function resolveCitedManifest(\n input: CitedAncestorResolutionInput,\n manifestHash: string,\n containerId: string,\n): Promise<VerifiedContainerAccessManifest> {\n const verified = input.verifiedByHash.get(manifestHash);\n if (verified) return verified;\n const bundle = input.bundlesByHash.get(manifestHash);\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} cites a head of container ${containerId} that the projection does not serve`,\n );\n }\n return input.verifyHistoryBundle(\n bundle,\n `${input.label} cited ancestor ${containerId}`,\n );\n}\n\n/**\n * The ancestor path, root first, that a container event cites, ending at the\n * head of `parentContainerId`. Empty for a root container.\n */\nexport async function resolveCitedAncestorPath(\n input: CitedAncestorResolutionInput & {\n readonly event: VerifiedAccessEvent;\n readonly parentContainerId: string | null;\n },\n): Promise<VerifiedContainerAccessManifest[]> {\n const cited = input.event.event.dependencyManifestHashes;\n const chain: VerifiedContainerAccessManifest[] = [];\n const seen = new Set<string>();\n let containerId = input.parentContainerId;\n while (containerId !== null) {\n if (seen.has(containerId)) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} cited ancestors form a cycle at ${containerId}`,\n );\n }\n seen.add(containerId);\n const ancestor = await resolveCitedManifest(\n input,\n citedManifestHashForContainer(input, cited, containerId),\n containerId,\n );\n chain.unshift(ancestor);\n containerId = ancestor.state.parentContainerId;\n }\n return chain;\n}\n\n/** What the lineage rules read: the served and the verified bundles. */\nexport type CitedLineageInput = Pick<\n CitedAncestorResolutionInput,\n \"bundlesByHash\" | \"label\" | \"verifiedByHash\"\n>;\n\n/**\n * The verified head of `containerId` among the cited hashes, if any. Reads\n * verified manifests only: a cited hash the pass has not verified is not a\n * head to reason about, and every caller runs after the cited ancestor path\n * resolved and verified the chain. An event cites one head per container,\n * so a second verified one is a served citation set that was tampered with,\n * not a choice to make.\n */\nexport function verifiedCitedHead(input: {\n readonly cited: readonly string[];\n readonly containerId: string;\n readonly label: string;\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): VerifiedContainerAccessManifest | undefined {\n let found: VerifiedContainerAccessManifest | undefined;\n for (const manifestHash of input.cited) {\n const verified = input.verifiedByHash.get(manifestHash);\n if (verified?.state.containerId !== input.containerId) continue;\n if (found && found.manifestHash !== verified.manifestHash) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `${input.label} cites more than one head of container ${input.containerId}`,\n );\n }\n found = verified;\n }\n return found;\n}\n\n/**\n * Whether `head` is `floor` or descends from it through verified\n * predecessors. Epochs alone would let a same-epoch fork signed under an\n * older head pass; lineage cannot be forged without the chain. Every\n * predecessor of a verified manifest was verified with it, so a hop that is\n * not in the verified set means the chain was not served.\n */\nfunction descendsFrom(\n verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>,\n head: VerifiedContainerAccessManifest,\n floor: VerifiedContainerAccessManifest,\n): boolean {\n let current: VerifiedContainerAccessManifest | undefined = head;\n while (current && current.state.epoch >= floor.state.epoch) {\n if (current.manifestHash === floor.manifestHash) return true;\n const previousHash: string | null = current.state.previousManifestHash;\n current =\n previousHash === null ? undefined : verifiedByHash.get(previousHash);\n }\n return false;\n}\n\n/** The cited head must be the established head or descend from it. */\nfunction assertCitedHeadDescendsFrom(\n input: CitedLineageInput,\n cited: VerifiedContainerAccessManifest,\n floor: VerifiedContainerAccessManifest,\n): void {\n if (descendsFrom(input.verifiedByHash, cited, floor)) return;\n throw new KeyingVerificationError(\n \"rollback\",\n `${input.label} cites a head of container ${cited.state.containerId} that does not descend from the head an earlier signed statement already proved current`,\n );\n}\n\n/**\n * A head must not cite a head of any ancestor that does not descend from the\n * head an earlier signed statement already established: the manifest before\n * it cited that ancestor, the previous manifest's own pin when this is its\n * parent, or a cited child of that ancestor was created or moved under it and\n * cited it. Ancestors no statement establishes are skipped.\n */\nexport function assertCitedAncestorsDoNotRegress(\n input: CitedLineageInput & {\n readonly citedAncestors: readonly VerifiedContainerAccessManifest[];\n readonly previousManifest: VerifiedContainerAccessManifest | null;\n },\n): void {\n const previous = input.previousManifest;\n const previousCited = previous?.event.event.dependencyManifestHashes ?? [];\n input.citedAncestors.forEach((ancestor, index) => {\n const containerId = ancestor.state.containerId;\n const citedChild = input.citedAncestors[index + 1] ?? previous;\n const floors = [\n verifiedCitedHead({\n cited: previousCited,\n containerId,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n }),\n ...(citedChild\n ? [\n input.verifiedByHash.get(citedChild.state.parentManifestHash ?? \"\"),\n verifiedCitedHead({\n cited: citedChild.event.event.dependencyManifestHashes,\n containerId,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n }),\n ]\n : []),\n ];\n for (const floor of floors) {\n if (floor && floor.state.containerId === containerId) {\n assertCitedHeadDescendsFrom(input, ancestor, floor);\n }\n }\n });\n}\n\n/**\n * Every served current ancestor head must be, or descend through verified\n * predecessors from, the head of that container the head's signed event\n * cites. A served head older than the cited one, or a same-epoch fork of it,\n * is a rollback the signature proves: the cited head exists. A served head\n * newer than the cited one is the ordinary lag of a descendant behind its\n * ancestors, and an ancestor the head does not cite at all joined the path\n * when an ancestor between them moved; neither is refused.\n */\nexport function assertServedAncestorsDescendFromCitations(input: {\n readonly head: VerifiedContainerAccessManifest;\n readonly label: string;\n readonly servedAncestors: readonly VerifiedContainerAccessManifest[];\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): void {\n const citations = input.head.event.event.dependencyManifestHashes;\n for (const served of input.servedAncestors) {\n const containerId = served.state.containerId;\n const cited = verifiedCitedHead({\n cited: citations,\n containerId,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n });\n if (!cited || descendsFrom(input.verifiedByHash, served, cited)) continue;\n throw new KeyingVerificationError(\n \"rollback\",\n `${input.label} cites a head of ancestor container ${containerId} that the served current head does not descend from`,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"containerAncestorCitations.js","sourceRoot":"","sources":["containerAncestorCitations.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type VerifiedAccessEvent,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWireResponse } from \"@tearleads/validators/response\";\nimport { readCanonicalRecord } from \"../keying/canonicalJson\";\nimport { readKeyingVerificationShape } from \"./error\";\nimport { readRecordNullableString } from \"./readers\";\n\n/**\n * A container manifest pins the parent manifest it was created or moved\n * under, and successors inherit that pin, so the pin says nothing about the\n * ancestor heads a later grant, revoke, or rekey was actually authorized\n * under. Those heads are in the event: every container event signs the\n * manifest hashes of the path it was committed against, and the API refuses\n * an event whose citations are not the current heads at commit time. So a\n * head's authorization path is rebuilt here from its citations, root to\n * parent, and the signer is checked against those heads rather than against\n * whatever path the server pairs with the manifest.\n *\n * A head must also cite, for every ancestor, a head that is or descends from\n * the head an earlier signed statement already established, so an ancestor\n * head one signed statement established can never be rolled back or forked\n * away for a later one.\n *\n * As with principal policies, a successor new to a device need not cite the\n * authority's served current head. An honest server serves a\n * child head citing the ancestor head that was current when it was\n * committed, signed by a member since revoked at that ancestor, and refusing\n * that shape would leave every device holding the child unable to supersede\n * it. What can be refused is the opposite disagreement: a served current\n * ancestor head that does not descend from a head the child's signed event\n * proves exists is a stale or forked ancestor, whatever the server calls\n * current.\n */\n\ninterface CitedAncestorResolutionInput {\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly label: string;\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n readonly verifyHistoryBundle: (\n bundle: AccessManifestBundleWireResponse,\n label: string,\n ) => Promise<VerifiedContainerAccessManifest>;\n}\n\nfunction bundleContainerId(\n bundle: AccessManifestBundleWireResponse,\n label: string,\n): string | null {\n return readKeyingVerificationShape(() =>\n readRecordNullableString(\n readCanonicalRecord(bundle.state, `${label} state`),\n \"containerId\",\n `${label} state`,\n ),\n );\n}\n\nfunction citedContainerId(\n input: CitedLineageInput,\n manifestHash: string,\n): string | null {\n const verified = input.verifiedByHash.get(manifestHash);\n if (verified) return verified.state.containerId;\n const bundle = input.bundlesByHash.get(manifestHash);\n return bundle ? bundleContainerId(bundle, input.label) : null;\n}\n\nfunction citedManifestHashForContainer(\n input: CitedAncestorResolutionInput,\n cited: readonly string[],\n containerId: string,\n): string {\n const hashes = cited.filter(\n (manifestHash) => citedContainerId(input, manifestHash) === containerId,\n );\n const [manifestHash] = hashes;\n if (manifestHash === undefined) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} does not cite a served head of its parent container ${containerId}`,\n );\n }\n if (hashes.length > 1) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `${input.label} cites more than one head of container ${containerId}`,\n );\n }\n return manifestHash;\n}\n\nasync function resolveCitedManifest(\n input: CitedAncestorResolutionInput,\n manifestHash: string,\n containerId: string,\n): Promise<VerifiedContainerAccessManifest> {\n const verified = input.verifiedByHash.get(manifestHash);\n if (verified) return verified;\n const bundle = input.bundlesByHash.get(manifestHash);\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} cites a head of container ${containerId} that the projection does not serve`,\n );\n }\n return input.verifyHistoryBundle(\n bundle,\n `${input.label} cited ancestor ${containerId}`,\n );\n}\n\n/**\n * The ancestor path, root first, that a container event cites, ending at the\n * head of `parentContainerId`. Empty for a root container.\n */\nexport async function resolveCitedAncestorPath(\n input: CitedAncestorResolutionInput & {\n readonly event: VerifiedAccessEvent;\n readonly parentContainerId: string | null;\n },\n): Promise<VerifiedContainerAccessManifest[]> {\n const cited = input.event.event.dependencyManifestHashes;\n const chain: VerifiedContainerAccessManifest[] = [];\n const seen = new Set<string>();\n let containerId = input.parentContainerId;\n while (containerId !== null) {\n if (seen.has(containerId)) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} cited ancestors form a cycle at ${containerId}`,\n );\n }\n seen.add(containerId);\n const ancestor = await resolveCitedManifest(\n input,\n citedManifestHashForContainer(input, cited, containerId),\n containerId,\n );\n chain.unshift(ancestor);\n containerId = ancestor.state.parentContainerId;\n }\n return chain;\n}\n\n/** What the lineage rules read: the served and the verified bundles. */\nexport type CitedLineageInput = Pick<\n CitedAncestorResolutionInput,\n \"bundlesByHash\" | \"label\" | \"verifiedByHash\"\n>;\n\n/**\n * The verified head of `containerId` among the cited hashes, if any. Reads\n * verified manifests only: a cited hash the pass has not verified is not a\n * head to reason about, and every caller runs after the cited ancestor path\n * resolved and verified the chain. An event cites one head per container,\n * so a second verified one is a served citation set that was tampered with,\n * not a choice to make.\n */\nexport function verifiedCitedHead(input: {\n readonly cited: readonly string[];\n readonly containerId: string;\n readonly label: string;\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): VerifiedContainerAccessManifest | undefined {\n let found: VerifiedContainerAccessManifest | undefined;\n for (const manifestHash of input.cited) {\n const verified = input.verifiedByHash.get(manifestHash);\n if (verified?.state.containerId !== input.containerId) continue;\n if (found && found.manifestHash !== verified.manifestHash) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `${input.label} cites more than one head of container ${input.containerId}`,\n );\n }\n found = verified;\n }\n return found;\n}\n\n/**\n * Whether `head` is `floor` or descends from it through verified\n * predecessors. Epochs alone would let a same-epoch fork signed under an\n * older head pass; lineage cannot be forged without the chain. Every\n * predecessor of a verified manifest was verified with it, so a hop that is\n * not in the verified set means the chain was not served.\n */\nfunction descendsFrom(\n verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>,\n head: VerifiedContainerAccessManifest,\n floor: VerifiedContainerAccessManifest,\n): boolean {\n let current: VerifiedContainerAccessManifest | undefined = head;\n while (current && current.state.epoch >= floor.state.epoch) {\n if (current.manifestHash === floor.manifestHash) return true;\n const previousHash: string | null = current.state.previousManifestHash;\n current =\n previousHash === null ? undefined : verifiedByHash.get(previousHash);\n }\n return false;\n}\n\n/** The cited head must be the established head or descend from it. */\nfunction assertCitedHeadDescendsFrom(\n input: CitedLineageInput,\n cited: VerifiedContainerAccessManifest,\n floor: VerifiedContainerAccessManifest,\n): void {\n if (descendsFrom(input.verifiedByHash, cited, floor)) return;\n throw new KeyingVerificationError(\n \"rollback\",\n `${input.label} cites a head of container ${cited.state.containerId} that does not descend from the head an earlier signed statement already proved current`,\n );\n}\n\n/**\n * A head must not cite a head of any ancestor that does not descend from the\n * head an earlier signed statement already established: the manifest before\n * it cited that ancestor, the previous manifest's own pin when this is its\n * parent, or a cited child of that ancestor was created or moved under it and\n * cited it. Ancestors no statement establishes are skipped.\n */\nexport function assertCitedAncestorsDoNotRegress(\n input: CitedLineageInput & {\n readonly citedAncestors: readonly VerifiedContainerAccessManifest[];\n readonly previousManifest: VerifiedContainerAccessManifest | null;\n },\n): void {\n const previous = input.previousManifest;\n const previousCited = previous?.event.event.dependencyManifestHashes ?? [];\n input.citedAncestors.forEach((ancestor, index) => {\n const containerId = ancestor.state.containerId;\n const citedChild = input.citedAncestors[index + 1] ?? previous;\n const floors = [\n verifiedCitedHead({\n cited: previousCited,\n containerId,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n }),\n ...(citedChild\n ? [\n input.verifiedByHash.get(citedChild.state.parentManifestHash ?? \"\"),\n verifiedCitedHead({\n cited: citedChild.event.event.dependencyManifestHashes,\n containerId,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n }),\n ]\n : []),\n ];\n for (const floor of floors) {\n if (floor && floor.state.containerId === containerId) {\n assertCitedHeadDescendsFrom(input, ancestor, floor);\n }\n }\n });\n}\n\n/**\n * Every served current ancestor head must be, or descend through verified\n * predecessors from, the head of that container the head's signed event\n * cites. A served head older than the cited one, or a same-epoch fork of it,\n * is a rollback the signature proves: the cited head exists. A served head\n * newer than the cited one is the ordinary lag of a descendant behind its\n * ancestors, and an ancestor the head does not cite at all joined the path\n * when an ancestor between them moved; neither is refused.\n */\nexport function assertServedAncestorsDescendFromCitations(input: {\n readonly head: VerifiedContainerAccessManifest;\n readonly label: string;\n readonly servedAncestors: readonly VerifiedContainerAccessManifest[];\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): void {\n const citations = input.head.event.event.dependencyManifestHashes;\n for (const served of input.servedAncestors) {\n const containerId = served.state.containerId;\n const cited = verifiedCitedHead({\n cited: citations,\n containerId,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n });\n if (!cited || descendsFrom(input.verifiedByHash, served, cited)) continue;\n throw new KeyingVerificationError(\n \"rollback\",\n `${input.label} cites a head of ancestor container ${containerId} that the served current head does not descend from`,\n );\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyingVerificationError, principalPolicyMatchesReference, verifyContainerAccessManifest, } from "../../internal/crypto/index.js";
|
|
2
|
-
import { readCanonicalJson, readCanonicalRecord } from "../
|
|
2
|
+
import { readCanonicalJson, readCanonicalRecord, } from "../keying/canonicalJson.js";
|
|
3
3
|
import { assertCanonicalEqual, verifyAccessEventBundle, } from "./bundleVerification.js";
|
|
4
4
|
import { assertCitedAncestorsDoNotRegress, resolveCitedAncestorPath, } from "./containerAncestorCitations.js";
|
|
5
5
|
import { readKeyingVerificationShape } from "./error.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerManifestVerification.js","sourceRoot":"","sources":["containerManifestVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyAuthorization } from \"@tearleads/crypto\";\nimport {\n KeyingVerificationError,\n principalPolicyMatchesReference,\n type VerifiedContainerAccessManifest,\n verifyContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWireResponse } from \"@tearleads/validators/response\";\nimport { readCanonicalJson, readCanonicalRecord } from \"../keyingCanonicalJson\";\nimport {\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport {\n assertCitedAncestorsDoNotRegress,\n type CitedLineageInput,\n resolveCitedAncestorPath,\n} from \"./containerAncestorCitations\";\nimport { readKeyingVerificationShape } from \"./error\";\nimport {\n loadManifestCheckpointVerification,\n verifyCachedManifestCheckpoint,\n} from \"./manifestCheckpointVerification\";\nimport { collectReferencedPrincipalPolicies } from \"./principalPolicyVerification\";\nimport { readAccessManifest, readRecordNullableString } from \"./readers\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\n\nasync function collectManifestAuthorizationPolicies(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly organizationId: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly referencedPrincipalHeads: Parameters<\n typeof principalPolicyMatchesReference\n >[0][\"reference\"][];\n readonly requireAuthorizationEvidence: boolean;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}) {\n const missingPrincipalHeads = input.referencedPrincipalHeads.filter(\n (reference) =>\n !input.authorizationEvidence.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n ),\n );\n if (input.requireAuthorizationEvidence && missingPrincipalHeads.length > 0) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Projection omits required principal policy evidence\",\n );\n }\n if (input.requireAuthorizationEvidence)\n return [...input.authorizationEvidence];\n return [\n ...input.authorizationEvidence,\n ...(await collectReferencedPrincipalPolicies({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n references: missingPrincipalHeads,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })),\n ];\n}\n\nexport async function verifyContainerManifestBundle(input: {\n readonly authorizationMembership?: \"current\" | \"referenced\" | undefined;\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundle: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly enforceLocalCheckpoint: boolean;\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly requireAuthorizationEvidence?: boolean | undefined;\n readonly verifiedByHash: Map<string, VerifiedContainerAccessManifest>;\n // Manifest hashes whose verification is in progress up the call stack.\n // Previous manifests, pinned parents, and cited ancestors all recurse\n // before a bundle's own hash is checked, so served bundles that refer to\n // each other under claimed hashes would otherwise recurse without end.\n readonly verifying?: Set<string> | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<VerifiedContainerAccessManifest> {\n const parentPath =\n await resolveContainerManifestVerificationParentPath(input);\n const cached = input.verifiedByHash.get(input.bundle.manifestHash);\n if (cached) {\n assertContainerParentPathMatches({\n label: input.label,\n parentPath,\n verifiedManifest: cached,\n });\n if (input.enforceLocalCheckpoint) {\n await verifyCachedManifestCheckpoint({\n current: cached,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n });\n }\n return cached;\n }\n\n const verifying = input.verifying ?? new Set<string>();\n if (verifying.has(input.bundle.manifestHash)) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} refers back to a manifest whose verification it is part of`,\n );\n }\n verifying.add(input.bundle.manifestHash);\n try {\n return await verifyFreshContainerManifestBundle(\n { ...input, verifying },\n parentPath,\n );\n } finally {\n verifying.delete(input.bundle.manifestHash);\n }\n}\n\ntype CitedAncestorInput = Parameters<typeof verifyContainerManifestBundle>[0];\n\nasync function verifyFreshContainerManifestBundle(\n input: CitedAncestorInput,\n parentPath: readonly VerifiedContainerAccessManifest[],\n): Promise<VerifiedContainerAccessManifest> {\n const event = await verifyAccessEventBundle(input);\n const manifest = readAccessManifest(\n input.bundle.manifest,\n `${input.label} manifest`,\n );\n const authorization = await resolveContainerManifestAuthorization(\n input,\n event,\n parentPath,\n );\n const { citedAncestors, previousManifest, sourceAncestors } = authorization;\n const principalPolicies = await collectManifestAuthorizationPolicies({\n authorizationEvidence: input.authorizationEvidence ?? [],\n checkpointContext: input.checkpointContext,\n organizationId: event.event.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n referencedPrincipalHeads: [\n ...authorization.referencedPrincipalHeads,\n ...manifest.referencedPrincipalHeads,\n ],\n requireAuthorizationEvidence: input.requireAuthorizationEvidence ?? false,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const checkpointVerification = input.enforceLocalCheckpoint\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n })\n : null;\n\n const verified = await verifyContainerAccessManifest({\n // Served manifests were committed under their signed policy references.\n // Current membership still gates new writes in the API verifier.\n authorizationMembership: input.authorizationMembership ?? \"referenced\",\n destinationParentContainerPath: citedAncestors,\n event,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n parentContainerPath: citedAncestors,\n principalPolicies,\n ...(checkpointVerification ?? {}),\n ...(previousManifest\n ? {\n previousContainerPath: [...sourceAncestors, previousManifest],\n previousManifest,\n }\n : { previousManifest: null }),\n });\n if (!verified.ok) {\n throw new KeyingVerificationError(\n verified.error.code,\n `${input.label} manifest verification failed: ${verified.error.message}`,\n );\n }\n\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(verified.value.state, `${input.label} state`),\n label: `${input.label} state`,\n });\n input.verifiedByHash.set(input.bundle.manifestHash, verified.value);\n\n return verified.value;\n}\n\n/**\n * The paths a container event is authorized against: its previous manifest\n * and the ancestor heads its signed event cites, root to parent.\n */\nasync function resolveContainerManifestAuthorization(\n input: CitedAncestorInput,\n event: VerifiedContainerAccessManifest[\"event\"],\n parentPath: readonly VerifiedContainerAccessManifest[],\n) {\n const previousManifest =\n event.event.previousManifestHash === null\n ? null\n : await verifyPreviousContainerManifest({\n ...input,\n parentPath,\n previousManifestHash: event.event.previousManifestHash,\n });\n // Resolve the signed placement lineage, never the server-supplied wire state.\n // Rotations also resolve their new epoch's exact signed parent citation via\n // cited-ancestor verification below; that can differ from this previous path.\n const eventType = event.event.eventType;\n const { parentContainerId, parentManifestHash } =\n previousManifest && eventType !== \"container.move\"\n ? previousManifest.state\n : readContainerEventBodyParentReference(event, input.label);\n if (\n previousManifest === null &&\n parentManifestHash !== null &&\n !event.event.dependencyManifestHashes.includes(parentManifestHash)\n ) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} does not cite the parent manifest it was created under`,\n );\n }\n const lineage: CitedLineageInput = {\n bundlesByHash: input.bundlesByHash,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n };\n const citedAncestors = await resolveCitedAncestors(input, event, {\n parentContainerId,\n });\n assertCitedAncestorsDoNotRegress({\n ...lineage,\n citedAncestors,\n previousManifest,\n });\n // A move's source path leads to the previous manifest's parent, and the\n // move event cites that path too; the destination path is the one above.\n // The source path is held to the same no-regression rule.\n const sourceAncestors =\n eventType === \"container.move\" && previousManifest\n ? await resolveCitedAncestors(input, event, {\n parentContainerId: previousManifest.state.parentContainerId,\n })\n : citedAncestors;\n if (sourceAncestors !== citedAncestors) {\n assertCitedAncestorsDoNotRegress({\n ...lineage,\n citedAncestors: sourceAncestors,\n previousManifest,\n });\n }\n const ancestors = [\n ...parentPath,\n ...citedAncestors,\n ...(sourceAncestors === citedAncestors ? [] : sourceAncestors),\n ];\n return {\n citedAncestors,\n previousManifest,\n referencedPrincipalHeads: [\n ...ancestors.flatMap(\n (ancestor) => ancestor.state.referencedPrincipalHeads,\n ),\n ...(previousManifest?.state.referencedPrincipalHeads ?? []),\n ],\n sourceAncestors,\n };\n}\n\nfunction citedAncestorResolutionInput(input: CitedAncestorInput) {\n return {\n bundlesByHash: input.bundlesByHash,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n // A cited head older than the served one is history: authorize it at the\n // membership it referenced, as the previous manifest is.\n verifyHistoryBundle: (\n bundle: AccessManifestBundleWireResponse,\n label: string,\n ) =>\n verifyContainerManifestBundle({\n ...input,\n authorizationMembership: \"referenced\",\n bundle,\n enforceLocalCheckpoint: false,\n label,\n }),\n };\n}\n\nfunction resolveCitedAncestors(\n input: CitedAncestorInput,\n event: VerifiedContainerAccessManifest[\"event\"],\n reference: { readonly parentContainerId: string | null },\n): Promise<VerifiedContainerAccessManifest[]> {\n return resolveCitedAncestorPath({\n ...citedAncestorResolutionInput(input),\n event,\n parentContainerId: reference.parentContainerId,\n });\n}\n\nfunction assertContainerParentPathMatches(input: {\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly verifiedManifest: VerifiedContainerAccessManifest;\n}): void {\n const actualParentManifestHash =\n input.parentPath.at(-1)?.manifestHash ?? null;\n if (\n actualParentManifestHash !== input.verifiedManifest.state.parentManifestHash\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} parent path mismatch`,\n );\n }\n}\n\ninterface ContainerParentReference {\n parentContainerId: string | null;\n parentManifestHash: string | null;\n}\n\nfunction readParentReference(\n value: unknown,\n label: string,\n): ContainerParentReference {\n return readKeyingVerificationShape(() => {\n const record = readCanonicalRecord(value, label);\n\n return {\n parentContainerId: readRecordNullableString(\n record,\n \"parentContainerId\",\n label,\n ),\n parentManifestHash: readRecordNullableString(\n record,\n \"parentManifestHash\",\n label,\n ),\n };\n });\n}\n\nfunction readContainerManifestParentReference(\n bundle: AccessManifestBundleWireResponse,\n label: string,\n): ContainerParentReference {\n return readParentReference(bundle.state, `${label} state`);\n}\n\n/** The parent a create or move body pins, read from the signed body. */\nfunction readContainerEventBodyParentReference(\n event: VerifiedContainerAccessManifest[\"event\"],\n label: string,\n): ContainerParentReference {\n return readParentReference(event.body, `${label} event body`);\n}\n\nasync function resolveContainerManifestVerificationParentPath(input: {\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundle: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly verifiedByHash: Map<string, VerifiedContainerAccessManifest>;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<readonly VerifiedContainerAccessManifest[]> {\n // Descendants keep the parent manifest hash they were created or moved under;\n // a later parent share/rekey must not require rewriting descendant manifests.\n const { parentContainerId, parentManifestHash } =\n readContainerManifestParentReference(input.bundle, input.label);\n if (parentContainerId === null || parentManifestHash === null) {\n return [];\n }\n\n const parentPathIndex = input.parentPath.findIndex(\n (manifest) =>\n manifest.state.containerId === parentContainerId &&\n manifest.manifestHash === parentManifestHash,\n );\n if (parentPathIndex >= 0) {\n return input.parentPath.slice(0, parentPathIndex + 1);\n }\n\n const parentBundle = input.bundlesByHash.get(parentManifestHash);\n if (!parentBundle) {\n return input.parentPath;\n }\n\n const parentParentPath = await resolveContainerManifestVerificationParentPath(\n {\n ...input,\n bundle: parentBundle,\n label: `${input.label} parent manifest`,\n },\n );\n const verifiedParent = await verifyContainerManifestBundle({\n ...input,\n bundle: parentBundle,\n enforceLocalCheckpoint: false,\n label: `${input.label} parent manifest`,\n parentPath: parentParentPath,\n });\n if (verifiedParent.state.containerId !== parentContainerId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} parent manifest container mismatch`,\n );\n }\n\n return [...parentParentPath, verifiedParent];\n}\n\nasync function verifyPreviousContainerManifest(input: {\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly previousManifestHash: string;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly requireAuthorizationEvidence?: boolean | undefined;\n readonly verifiedByHash: Map<string, VerifiedContainerAccessManifest>;\n readonly verifying?: Set<string> | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<VerifiedContainerAccessManifest> {\n const previousBundle = input.bundlesByHash.get(input.previousManifestHash);\n if (!previousBundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} previous manifest ${input.previousManifestHash} is missing`,\n );\n }\n const parentPath = await resolveContainerManifestVerificationParentPath({\n ...input,\n bundle: previousBundle,\n });\n\n return verifyContainerManifestBundle({\n authorizationMembership: \"referenced\",\n authorizationEvidence: input.authorizationEvidence,\n bundle: previousBundle,\n bundlesByHash: input.bundlesByHash,\n checkpointContext: input.checkpointContext,\n enforceLocalCheckpoint: false,\n label: `${input.label} previous manifest`,\n parentPath,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: input.requireAuthorizationEvidence,\n verifiedByHash: input.verifiedByHash,\n verifying: input.verifying,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"containerManifestVerification.js","sourceRoot":"","sources":["containerManifestVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyAuthorization } from \"@tearleads/crypto\";\nimport {\n KeyingVerificationError,\n principalPolicyMatchesReference,\n type VerifiedContainerAccessManifest,\n verifyContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWireResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../keying/canonicalJson\";\nimport {\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport {\n assertCitedAncestorsDoNotRegress,\n type CitedLineageInput,\n resolveCitedAncestorPath,\n} from \"./containerAncestorCitations\";\nimport { readKeyingVerificationShape } from \"./error\";\nimport {\n loadManifestCheckpointVerification,\n verifyCachedManifestCheckpoint,\n} from \"./manifestCheckpointVerification\";\nimport { collectReferencedPrincipalPolicies } from \"./principalPolicyVerification\";\nimport { readAccessManifest, readRecordNullableString } from \"./readers\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\n\nasync function collectManifestAuthorizationPolicies(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly organizationId: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly referencedPrincipalHeads: Parameters<\n typeof principalPolicyMatchesReference\n >[0][\"reference\"][];\n readonly requireAuthorizationEvidence: boolean;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}) {\n const missingPrincipalHeads = input.referencedPrincipalHeads.filter(\n (reference) =>\n !input.authorizationEvidence.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n ),\n );\n if (input.requireAuthorizationEvidence && missingPrincipalHeads.length > 0) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Projection omits required principal policy evidence\",\n );\n }\n if (input.requireAuthorizationEvidence)\n return [...input.authorizationEvidence];\n return [\n ...input.authorizationEvidence,\n ...(await collectReferencedPrincipalPolicies({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n references: missingPrincipalHeads,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })),\n ];\n}\n\nexport async function verifyContainerManifestBundle(input: {\n readonly authorizationMembership?: \"current\" | \"referenced\" | undefined;\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundle: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly enforceLocalCheckpoint: boolean;\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly requireAuthorizationEvidence?: boolean | undefined;\n readonly verifiedByHash: Map<string, VerifiedContainerAccessManifest>;\n // Manifest hashes whose verification is in progress up the call stack.\n // Previous manifests, pinned parents, and cited ancestors all recurse\n // before a bundle's own hash is checked, so served bundles that refer to\n // each other under claimed hashes would otherwise recurse without end.\n readonly verifying?: Set<string> | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<VerifiedContainerAccessManifest> {\n const parentPath =\n await resolveContainerManifestVerificationParentPath(input);\n const cached = input.verifiedByHash.get(input.bundle.manifestHash);\n if (cached) {\n assertContainerParentPathMatches({\n label: input.label,\n parentPath,\n verifiedManifest: cached,\n });\n if (input.enforceLocalCheckpoint) {\n await verifyCachedManifestCheckpoint({\n current: cached,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n });\n }\n return cached;\n }\n\n const verifying = input.verifying ?? new Set<string>();\n if (verifying.has(input.bundle.manifestHash)) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} refers back to a manifest whose verification it is part of`,\n );\n }\n verifying.add(input.bundle.manifestHash);\n try {\n return await verifyFreshContainerManifestBundle(\n { ...input, verifying },\n parentPath,\n );\n } finally {\n verifying.delete(input.bundle.manifestHash);\n }\n}\n\ntype CitedAncestorInput = Parameters<typeof verifyContainerManifestBundle>[0];\n\nasync function verifyFreshContainerManifestBundle(\n input: CitedAncestorInput,\n parentPath: readonly VerifiedContainerAccessManifest[],\n): Promise<VerifiedContainerAccessManifest> {\n const event = await verifyAccessEventBundle(input);\n const manifest = readAccessManifest(\n input.bundle.manifest,\n `${input.label} manifest`,\n );\n const authorization = await resolveContainerManifestAuthorization(\n input,\n event,\n parentPath,\n );\n const { citedAncestors, previousManifest, sourceAncestors } = authorization;\n const principalPolicies = await collectManifestAuthorizationPolicies({\n authorizationEvidence: input.authorizationEvidence ?? [],\n checkpointContext: input.checkpointContext,\n organizationId: event.event.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n referencedPrincipalHeads: [\n ...authorization.referencedPrincipalHeads,\n ...manifest.referencedPrincipalHeads,\n ],\n requireAuthorizationEvidence: input.requireAuthorizationEvidence ?? false,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const checkpointVerification = input.enforceLocalCheckpoint\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n })\n : null;\n\n const verified = await verifyContainerAccessManifest({\n // Served manifests were committed under their signed policy references.\n // Current membership still gates new writes in the API verifier.\n authorizationMembership: input.authorizationMembership ?? \"referenced\",\n destinationParentContainerPath: citedAncestors,\n event,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n parentContainerPath: citedAncestors,\n principalPolicies,\n ...(checkpointVerification ?? {}),\n ...(previousManifest\n ? {\n previousContainerPath: [...sourceAncestors, previousManifest],\n previousManifest,\n }\n : { previousManifest: null }),\n });\n if (!verified.ok) {\n throw new KeyingVerificationError(\n verified.error.code,\n `${input.label} manifest verification failed: ${verified.error.message}`,\n );\n }\n\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(verified.value.state, `${input.label} state`),\n label: `${input.label} state`,\n });\n input.verifiedByHash.set(input.bundle.manifestHash, verified.value);\n\n return verified.value;\n}\n\n/**\n * The paths a container event is authorized against: its previous manifest\n * and the ancestor heads its signed event cites, root to parent.\n */\nasync function resolveContainerManifestAuthorization(\n input: CitedAncestorInput,\n event: VerifiedContainerAccessManifest[\"event\"],\n parentPath: readonly VerifiedContainerAccessManifest[],\n) {\n const previousManifest =\n event.event.previousManifestHash === null\n ? null\n : await verifyPreviousContainerManifest({\n ...input,\n parentPath,\n previousManifestHash: event.event.previousManifestHash,\n });\n // Resolve the signed placement lineage, never the server-supplied wire state.\n // Rotations also resolve their new epoch's exact signed parent citation via\n // cited-ancestor verification below; that can differ from this previous path.\n const eventType = event.event.eventType;\n const { parentContainerId, parentManifestHash } =\n previousManifest && eventType !== \"container.move\"\n ? previousManifest.state\n : readContainerEventBodyParentReference(event, input.label);\n if (\n previousManifest === null &&\n parentManifestHash !== null &&\n !event.event.dependencyManifestHashes.includes(parentManifestHash)\n ) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} does not cite the parent manifest it was created under`,\n );\n }\n const lineage: CitedLineageInput = {\n bundlesByHash: input.bundlesByHash,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n };\n const citedAncestors = await resolveCitedAncestors(input, event, {\n parentContainerId,\n });\n assertCitedAncestorsDoNotRegress({\n ...lineage,\n citedAncestors,\n previousManifest,\n });\n // A move's source path leads to the previous manifest's parent, and the\n // move event cites that path too; the destination path is the one above.\n // The source path is held to the same no-regression rule.\n const sourceAncestors =\n eventType === \"container.move\" && previousManifest\n ? await resolveCitedAncestors(input, event, {\n parentContainerId: previousManifest.state.parentContainerId,\n })\n : citedAncestors;\n if (sourceAncestors !== citedAncestors) {\n assertCitedAncestorsDoNotRegress({\n ...lineage,\n citedAncestors: sourceAncestors,\n previousManifest,\n });\n }\n const ancestors = [\n ...parentPath,\n ...citedAncestors,\n ...(sourceAncestors === citedAncestors ? [] : sourceAncestors),\n ];\n return {\n citedAncestors,\n previousManifest,\n referencedPrincipalHeads: [\n ...ancestors.flatMap(\n (ancestor) => ancestor.state.referencedPrincipalHeads,\n ),\n ...(previousManifest?.state.referencedPrincipalHeads ?? []),\n ],\n sourceAncestors,\n };\n}\n\nfunction citedAncestorResolutionInput(input: CitedAncestorInput) {\n return {\n bundlesByHash: input.bundlesByHash,\n label: input.label,\n verifiedByHash: input.verifiedByHash,\n // A cited head older than the served one is history: authorize it at the\n // membership it referenced, as the previous manifest is.\n verifyHistoryBundle: (\n bundle: AccessManifestBundleWireResponse,\n label: string,\n ) =>\n verifyContainerManifestBundle({\n ...input,\n authorizationMembership: \"referenced\",\n bundle,\n enforceLocalCheckpoint: false,\n label,\n }),\n };\n}\n\nfunction resolveCitedAncestors(\n input: CitedAncestorInput,\n event: VerifiedContainerAccessManifest[\"event\"],\n reference: { readonly parentContainerId: string | null },\n): Promise<VerifiedContainerAccessManifest[]> {\n return resolveCitedAncestorPath({\n ...citedAncestorResolutionInput(input),\n event,\n parentContainerId: reference.parentContainerId,\n });\n}\n\nfunction assertContainerParentPathMatches(input: {\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly verifiedManifest: VerifiedContainerAccessManifest;\n}): void {\n const actualParentManifestHash =\n input.parentPath.at(-1)?.manifestHash ?? null;\n if (\n actualParentManifestHash !== input.verifiedManifest.state.parentManifestHash\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} parent path mismatch`,\n );\n }\n}\n\ninterface ContainerParentReference {\n parentContainerId: string | null;\n parentManifestHash: string | null;\n}\n\nfunction readParentReference(\n value: unknown,\n label: string,\n): ContainerParentReference {\n return readKeyingVerificationShape(() => {\n const record = readCanonicalRecord(value, label);\n\n return {\n parentContainerId: readRecordNullableString(\n record,\n \"parentContainerId\",\n label,\n ),\n parentManifestHash: readRecordNullableString(\n record,\n \"parentManifestHash\",\n label,\n ),\n };\n });\n}\n\nfunction readContainerManifestParentReference(\n bundle: AccessManifestBundleWireResponse,\n label: string,\n): ContainerParentReference {\n return readParentReference(bundle.state, `${label} state`);\n}\n\n/** The parent a create or move body pins, read from the signed body. */\nfunction readContainerEventBodyParentReference(\n event: VerifiedContainerAccessManifest[\"event\"],\n label: string,\n): ContainerParentReference {\n return readParentReference(event.body, `${label} event body`);\n}\n\nasync function resolveContainerManifestVerificationParentPath(input: {\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundle: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly verifiedByHash: Map<string, VerifiedContainerAccessManifest>;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<readonly VerifiedContainerAccessManifest[]> {\n // Descendants keep the parent manifest hash they were created or moved under;\n // a later parent share/rekey must not require rewriting descendant manifests.\n const { parentContainerId, parentManifestHash } =\n readContainerManifestParentReference(input.bundle, input.label);\n if (parentContainerId === null || parentManifestHash === null) {\n return [];\n }\n\n const parentPathIndex = input.parentPath.findIndex(\n (manifest) =>\n manifest.state.containerId === parentContainerId &&\n manifest.manifestHash === parentManifestHash,\n );\n if (parentPathIndex >= 0) {\n return input.parentPath.slice(0, parentPathIndex + 1);\n }\n\n const parentBundle = input.bundlesByHash.get(parentManifestHash);\n if (!parentBundle) {\n return input.parentPath;\n }\n\n const parentParentPath = await resolveContainerManifestVerificationParentPath(\n {\n ...input,\n bundle: parentBundle,\n label: `${input.label} parent manifest`,\n },\n );\n const verifiedParent = await verifyContainerManifestBundle({\n ...input,\n bundle: parentBundle,\n enforceLocalCheckpoint: false,\n label: `${input.label} parent manifest`,\n parentPath: parentParentPath,\n });\n if (verifiedParent.state.containerId !== parentContainerId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n `${input.label} parent manifest container mismatch`,\n );\n }\n\n return [...parentParentPath, verifiedParent];\n}\n\nasync function verifyPreviousContainerManifest(input: {\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly label: string;\n readonly parentPath: readonly VerifiedContainerAccessManifest[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly previousManifestHash: string;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly requireAuthorizationEvidence?: boolean | undefined;\n readonly verifiedByHash: Map<string, VerifiedContainerAccessManifest>;\n readonly verifying?: Set<string> | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<VerifiedContainerAccessManifest> {\n const previousBundle = input.bundlesByHash.get(input.previousManifestHash);\n if (!previousBundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${input.label} previous manifest ${input.previousManifestHash} is missing`,\n );\n }\n const parentPath = await resolveContainerManifestVerificationParentPath({\n ...input,\n bundle: previousBundle,\n });\n\n return verifyContainerManifestBundle({\n authorizationMembership: \"referenced\",\n authorizationEvidence: input.authorizationEvidence,\n bundle: previousBundle,\n bundlesByHash: input.bundlesByHash,\n checkpointContext: input.checkpointContext,\n enforceLocalCheckpoint: false,\n label: `${input.label} previous manifest`,\n parentPath,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: input.requireAuthorizationEvidence,\n verifiedByHash: input.verifiedByHash,\n verifying: input.verifying,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyingVerificationError, verifyDocumentLinkSetManifest, } from "../../internal/crypto/index.js";
|
|
2
|
-
import { readCanonicalJson } from "../
|
|
2
|
+
import { readCanonicalJson } from "../keying/canonicalJson.js";
|
|
3
3
|
import { addBundleByHash, assertCanonicalEqual, verifyAccessEventBundle, } from "./bundleVerification.js";
|
|
4
4
|
import { resolveEventContainerPaths } from "./documentDependencyPaths.js";
|
|
5
5
|
import { collectDocumentManifestPrincipalPolicies, recordUsedDocumentContainerManifests, } from "./documentManifestPolicies.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentManifestVerification.js","sourceRoot":"","sources":["documentManifestVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyAuthorization } from \"@tearleads/crypto\";\nimport {\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n verifyDocumentLinkSetManifest,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalJson } from \"../keyingCanonicalJson\";\nimport {\n addBundleByHash,\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport { resolveEventContainerPaths } from \"./documentDependencyPaths\";\nimport {\n collectDocumentManifestPrincipalPolicies,\n recordUsedDocumentContainerManifests,\n type UsedDocumentContainerManifests,\n} from \"./documentManifestPolicies\";\nimport { requireVerifiedDocumentPredecessor } from \"./documentManifestPredecessor\";\nimport {\n loadManifestCheckpointVerification,\n verifyCachedManifestCheckpoint,\n} from \"./manifestCheckpointVerification\";\nimport { readAccessManifest, readDocumentAccessEventBody } from \"./readers\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\n\ntype PolicyWarmer = ReferencedPrincipalPolicyWarmer | undefined;\n\nexport async function verifyDocumentManifestBundle(input: {\n readonly authorizationMembership?: \"current\" | \"referenced\" | undefined;\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundle: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly enforceLocalCheckpoint: boolean;\n readonly label: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly requireAuthorizationEvidence?: boolean | undefined;\n readonly trustedPredecessorByHash?:\n | ReadonlyMap<string, VerifiedDocumentLinkSetSnapshot>\n | undefined;\n readonly usedContainerManifests?: UsedDocumentContainerManifests | undefined;\n readonly verifiedByHash: Map<string, VerifiedDocumentLinkSetManifest>;\n readonly warmReferencedPrincipalPolicies?: PolicyWarmer;\n}): Promise<VerifiedDocumentLinkSetManifest> {\n const cached = input.verifiedByHash.get(input.bundle.manifestHash);\n if (cached) {\n if (input.enforceLocalCheckpoint) {\n await verifyCachedManifestCheckpoint({\n current: cached,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n });\n }\n return cached;\n }\n\n const event = await verifyAccessEventBundle(input);\n const manifest = readAccessManifest(\n input.bundle.manifest,\n `${input.label} manifest`,\n );\n const previousManifest = requireVerifiedDocumentPredecessor({\n label: input.label,\n previousManifestHash: event.event.previousManifestHash,\n trustedPredecessorByHash: input.trustedPredecessorByHash,\n verifiedByHash: input.verifiedByHash,\n });\n const body = readDocumentAccessEventBody(\n event.body,\n `${input.label} event body`,\n );\n const { dependencyContainerPaths, targetContainerPath } =\n resolveEventContainerPaths({\n containerPathByManifestHash: input.containerPathByManifestHash,\n dependencyManifestHashes: event.event.dependencyManifestHashes,\n targetManifestHash: body.containerManifestHash,\n });\n const principalPolicies = await collectDocumentManifestPrincipalPolicies({\n authorizationEvidence: input.authorizationEvidence,\n checkpointContext: input.checkpointContext,\n organizationId: event.event.organizationId,\n paths: [...dependencyContainerPaths, targetContainerPath],\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: input.requireAuthorizationEvidence,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const checkpointVerification = input.enforceLocalCheckpoint\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n })\n : null;\n const verified = await verifyDocumentLinkSetManifest({\n // Served heads and history were committed under the group membership their\n // cited container heads referenced; a signer removed since must still\n // verify on a cold device. The API verifier gates new writes at current.\n authorizationMembership: input.authorizationMembership ?? \"referenced\",\n authorizingContainerPaths: dependencyContainerPaths,\n event,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n previousManifest,\n principalPolicies,\n ...(checkpointVerification ?? {}),\n ...(targetContainerPath ? { targetContainerPath } : {}),\n });\n if (!verified.ok) {\n throw new KeyingVerificationError(\n verified.error.code,\n `${input.label} manifest verification failed: ${verified.error.message}`,\n );\n }\n\n recordUsedDocumentContainerManifests({\n paths: [...dependencyContainerPaths, targetContainerPath],\n used: input.usedContainerManifests,\n });\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(verified.value.state, `${input.label} state`),\n label: `${input.label} state`,\n });\n input.verifiedByHash.set(input.bundle.manifestHash, verified.value);\n\n return verified.value;\n}\n\nexport async function verifyDocumentProjectionManifests(\n input: Omit<\n Parameters<typeof verifyDocumentManifestBundle>[0],\n | \"bundle\"\n | \"bundlesByHash\"\n | \"enforceLocalCheckpoint\"\n | \"label\"\n | \"verifiedByHash\"\n > & { readonly projection: DocumentWriterProjectionResponse },\n) {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n addBundleByHash(\n bundlesByHash,\n input.projection.documentManifest,\n \"Document writer projection manifest\",\n );\n const history = input.projection.documentManifestHistory;\n for (const [index, bundle] of history.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document writer projection manifest history[${index}]`,\n );\n }\n // An honest API never lists the head in its own history (it seeds the walk\n // with the head), so a repeat is a malformed or tampered projection and is\n // refused as such, rather than letting the head reach its verification\n // through the history cache and relying on the cached branch to re-run\n // every check the fresh path would.\n if (\n history.some(\n (bundle) =>\n bundle.manifestHash === input.projection.documentManifest.manifestHash,\n )\n ) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n \"Document writer projection history repeats the current head\",\n );\n }\n\n const verifiedByHash = new Map<string, VerifiedDocumentLinkSetManifest>();\n for (let index = history.length - 1; index >= 0; index -= 1) {\n const bundle = history[index];\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `Document writer projection manifest history[${index}] is missing`,\n );\n }\n await verifyDocumentManifestBundle({\n authorizationEvidence: input.authorizationEvidence,\n requireAuthorizationEvidence: true,\n bundle,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n containerPathByManifestHash: input.containerPathByManifestHash,\n enforceLocalCheckpoint: false,\n label: `Document writer projection manifest history[${index}]`,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n }\n\n const headManifest = await verifyDocumentManifestBundle({\n authorizationEvidence: input.authorizationEvidence,\n requireAuthorizationEvidence: true,\n bundle: input.projection.documentManifest,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n containerPathByManifestHash: input.containerPathByManifestHash,\n enforceLocalCheckpoint: true,\n label: \"Document writer projection\",\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n return { headManifest, verifiedByHash };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"documentManifestVerification.js","sourceRoot":"","sources":["documentManifestVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyAuthorization } from \"@tearleads/crypto\";\nimport {\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n verifyDocumentLinkSetManifest,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalJson } from \"../keying/canonicalJson\";\nimport {\n addBundleByHash,\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport { resolveEventContainerPaths } from \"./documentDependencyPaths\";\nimport {\n collectDocumentManifestPrincipalPolicies,\n recordUsedDocumentContainerManifests,\n type UsedDocumentContainerManifests,\n} from \"./documentManifestPolicies\";\nimport { requireVerifiedDocumentPredecessor } from \"./documentManifestPredecessor\";\nimport {\n loadManifestCheckpointVerification,\n verifyCachedManifestCheckpoint,\n} from \"./manifestCheckpointVerification\";\nimport { readAccessManifest, readDocumentAccessEventBody } from \"./readers\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\n\ntype PolicyWarmer = ReferencedPrincipalPolicyWarmer | undefined;\n\nexport async function verifyDocumentManifestBundle(input: {\n readonly authorizationMembership?: \"current\" | \"referenced\" | undefined;\n readonly authorizationEvidence?:\n | readonly PrincipalPolicyAuthorization[]\n | undefined;\n readonly bundle: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<string, AccessManifestBundleWireResponse>;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly enforceLocalCheckpoint: boolean;\n readonly label: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly requireAuthorizationEvidence?: boolean | undefined;\n readonly trustedPredecessorByHash?:\n | ReadonlyMap<string, VerifiedDocumentLinkSetSnapshot>\n | undefined;\n readonly usedContainerManifests?: UsedDocumentContainerManifests | undefined;\n readonly verifiedByHash: Map<string, VerifiedDocumentLinkSetManifest>;\n readonly warmReferencedPrincipalPolicies?: PolicyWarmer;\n}): Promise<VerifiedDocumentLinkSetManifest> {\n const cached = input.verifiedByHash.get(input.bundle.manifestHash);\n if (cached) {\n if (input.enforceLocalCheckpoint) {\n await verifyCachedManifestCheckpoint({\n current: cached,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n });\n }\n return cached;\n }\n\n const event = await verifyAccessEventBundle(input);\n const manifest = readAccessManifest(\n input.bundle.manifest,\n `${input.label} manifest`,\n );\n const previousManifest = requireVerifiedDocumentPredecessor({\n label: input.label,\n previousManifestHash: event.event.previousManifestHash,\n trustedPredecessorByHash: input.trustedPredecessorByHash,\n verifiedByHash: input.verifiedByHash,\n });\n const body = readDocumentAccessEventBody(\n event.body,\n `${input.label} event body`,\n );\n const { dependencyContainerPaths, targetContainerPath } =\n resolveEventContainerPaths({\n containerPathByManifestHash: input.containerPathByManifestHash,\n dependencyManifestHashes: event.event.dependencyManifestHashes,\n targetManifestHash: body.containerManifestHash,\n });\n const principalPolicies = await collectDocumentManifestPrincipalPolicies({\n authorizationEvidence: input.authorizationEvidence,\n checkpointContext: input.checkpointContext,\n organizationId: event.event.organizationId,\n paths: [...dependencyContainerPaths, targetContainerPath],\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: input.requireAuthorizationEvidence,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const checkpointVerification = input.enforceLocalCheckpoint\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: input.verifiedByHash,\n })\n : null;\n const verified = await verifyDocumentLinkSetManifest({\n // Served heads and history were committed under the group membership their\n // cited container heads referenced; a signer removed since must still\n // verify on a cold device. The API verifier gates new writes at current.\n authorizationMembership: input.authorizationMembership ?? \"referenced\",\n authorizingContainerPaths: dependencyContainerPaths,\n event,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n previousManifest,\n principalPolicies,\n ...(checkpointVerification ?? {}),\n ...(targetContainerPath ? { targetContainerPath } : {}),\n });\n if (!verified.ok) {\n throw new KeyingVerificationError(\n verified.error.code,\n `${input.label} manifest verification failed: ${verified.error.message}`,\n );\n }\n\n recordUsedDocumentContainerManifests({\n paths: [...dependencyContainerPaths, targetContainerPath],\n used: input.usedContainerManifests,\n });\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(verified.value.state, `${input.label} state`),\n label: `${input.label} state`,\n });\n input.verifiedByHash.set(input.bundle.manifestHash, verified.value);\n\n return verified.value;\n}\n\nexport async function verifyDocumentProjectionManifests(\n input: Omit<\n Parameters<typeof verifyDocumentManifestBundle>[0],\n | \"bundle\"\n | \"bundlesByHash\"\n | \"enforceLocalCheckpoint\"\n | \"label\"\n | \"verifiedByHash\"\n > & { readonly projection: DocumentWriterProjectionResponse },\n) {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n addBundleByHash(\n bundlesByHash,\n input.projection.documentManifest,\n \"Document writer projection manifest\",\n );\n const history = input.projection.documentManifestHistory;\n for (const [index, bundle] of history.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document writer projection manifest history[${index}]`,\n );\n }\n // An honest API never lists the head in its own history (it seeds the walk\n // with the head), so a repeat is a malformed or tampered projection and is\n // refused as such, rather than letting the head reach its verification\n // through the history cache and relying on the cached branch to re-run\n // every check the fresh path would.\n if (\n history.some(\n (bundle) =>\n bundle.manifestHash === input.projection.documentManifest.manifestHash,\n )\n ) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n \"Document writer projection history repeats the current head\",\n );\n }\n\n const verifiedByHash = new Map<string, VerifiedDocumentLinkSetManifest>();\n for (let index = history.length - 1; index >= 0; index -= 1) {\n const bundle = history[index];\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `Document writer projection manifest history[${index}] is missing`,\n );\n }\n await verifyDocumentManifestBundle({\n authorizationEvidence: input.authorizationEvidence,\n requireAuthorizationEvidence: true,\n bundle,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n containerPathByManifestHash: input.containerPathByManifestHash,\n enforceLocalCheckpoint: false,\n label: `Document writer projection manifest history[${index}]`,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n }\n\n const headManifest = await verifyDocumentManifestBundle({\n authorizationEvidence: input.authorizationEvidence,\n requireAuthorizationEvidence: true,\n bundle: input.projection.documentManifest,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n containerPathByManifestHash: input.containerPathByManifestHash,\n enforceLocalCheckpoint: true,\n label: \"Document writer projection\",\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n return { headManifest, verifiedByHash };\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyingVerificationError, verifyDocumentLinkSetSnapshot, } from "../../internal/crypto/index.js";
|
|
2
|
-
import { readCanonicalJson } from "../
|
|
2
|
+
import { readCanonicalJson } from "../keying/canonicalJson.js";
|
|
3
3
|
import { addBundleByHash, assertCanonicalEqual, verifyAccessEventBundle, } from "./bundleVerification.js";
|
|
4
4
|
import { observeAccessManifestCheckpoints, } from "./checkpointContext.js";
|
|
5
5
|
import { ProjectionDependencyUnavailableError } from "./dependencyUnavailable.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentPurgeDocumentChainVerification.js","sourceRoot":"","sources":["documentPurgeDocumentChainVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyAuthorization,\n type VerifiedAccessManifestSnapshot,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n verifyDocumentLinkSetSnapshot,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentPurgeProofResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalJson } from \"../keyingCanonicalJson\";\nimport {\n addBundleByHash,\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport {\n observeAccessManifestCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { verifyDocumentManifestBundle } from \"./documentManifestVerification\";\nimport { loadManifestCheckpointVerification } from \"./manifestCheckpointVerification\";\nimport { readAccessManifest, readDocumentAccessEventBody } from \"./readers\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\nasync function verifyPinnedChainEndpoint(input: {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly checkpointContext: ProjectionCheckpointContext;\n}): Promise<VerifiedDocumentLinkSetSnapshot> {\n const manifest = readAccessManifest(\n input.bundle.manifest,\n \"Document purge predecessor endpoint manifest\",\n );\n const checkpointVerification = await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: new Map(),\n });\n const localCheckpoint = checkpointVerification.localCheckpoint;\n if (!localCheckpoint) {\n throw new ProjectionDependencyUnavailableError(\n \"Document purge history needs a local checkpoint or signed genesis\",\n );\n }\n if (\n localCheckpoint.epoch !== manifest.epoch ||\n localCheckpoint.manifestHash !== input.bundle.manifestHash\n ) {\n throw new KeyingVerificationError(\n localCheckpoint.epoch > manifest.epoch ? \"rollback\" : \"stale_predecessor\",\n \"Document purge predecessor chain does not start at the local checkpoint\",\n );\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...checkpointVerification,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n state: input.bundle.state,\n });\n if (!verified.ok) throw verified.error;\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(\n verified.value.state,\n \"Document purge predecessor endpoint state\",\n ),\n label: \"Document purge predecessor endpoint state\",\n });\n return verified.value;\n}\n\nasync function recordSnapshotContainerEvidence(input: {\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly manifest: VerifiedDocumentLinkSetSnapshot;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<void> {\n if (!input.usedContainerManifests) return;\n const event = await verifyAccessEventBundle({\n bundle: input.proof.documentManifest,\n label: \"Document purge manifest snapshot\",\n resolveUserKey: input.resolveUserKey,\n });\n if (event.eventHash !== input.manifest.manifest.eventHash) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"Document purge manifest snapshot event is not bound to its manifest\",\n );\n }\n const body = readDocumentAccessEventBody(\n event.body,\n \"Document purge manifest snapshot event body\",\n );\n const manifestHashes = [\n ...event.event.dependencyManifestHashes,\n body.containerManifestHash,\n ];\n for (const manifestHash of manifestHashes) {\n for (const containerManifest of input.containerPathByManifestHash.get(\n manifestHash,\n ) ?? []) {\n input.usedContainerManifests.set(\n containerManifest.manifestHash,\n containerManifest,\n );\n }\n }\n}\n\nasync function verifyPurgeChainEndpoint(\n input: Parameters<typeof verifySignedPurgeDocumentManifestChain>[0] & {\n readonly endpoint: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<\n string,\n AccessManifestBundleWireResponse\n >;\n readonly verifiedByHash: Map<string, VerifiedDocumentLinkSetManifest>;\n },\n): Promise<VerifiedDocumentLinkSetSnapshot | null> {\n const endpointManifest = readAccessManifest(\n input.endpoint.manifest,\n \"Document purge chain endpoint\",\n );\n if (endpointManifest.previousManifestHash === null) {\n await verifyDocumentManifestBundle({\n ...input,\n authorizationMembership: \"referenced\",\n bundle: input.endpoint,\n enforceLocalCheckpoint: false,\n label: \"Document purge genesis\",\n requireAuthorizationEvidence: true,\n });\n return null;\n }\n if (!input.enforceLocalCheckpoints) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Initial document purge history does not reach signed genesis\",\n );\n }\n return verifyPinnedChainEndpoint({\n bundle: input.endpoint,\n checkpointContext: input.checkpointContext,\n });\n}\n\nasync function verifySignedPurgeDocumentManifestChain(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n addBundleByHash(\n bundlesByHash,\n input.proof.documentManifest,\n \"Document purge manifest\",\n );\n for (const [\n index,\n bundle,\n ] of input.proof.documentManifestPredecessors.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge predecessor[${index}]`,\n );\n }\n\n const endpoint =\n input.proof.documentManifestPredecessors.at(-1) ??\n input.proof.documentManifest;\n const verifiedByHash = new Map<string, VerifiedDocumentLinkSetManifest>();\n const trustedPredecessorByHash = new Map<\n string,\n VerifiedDocumentLinkSetSnapshot\n >();\n const verifiedEndpoint = await verifyPurgeChainEndpoint({\n ...input,\n endpoint,\n bundlesByHash,\n verifiedByHash,\n });\n if (verifiedEndpoint) {\n trustedPredecessorByHash.set(\n verifiedEndpoint.manifestHash,\n verifiedEndpoint,\n );\n }\n\n const verificationInput = {\n ...input,\n authorizationMembership: \"referenced\" as const,\n bundlesByHash,\n requireAuthorizationEvidence: true,\n trustedPredecessorByHash,\n verifiedByHash,\n };\n for (\n let index = input.proof.documentManifestPredecessors.length - 2;\n index >= 0;\n index -= 1\n ) {\n const bundle = input.proof.documentManifestPredecessors[index];\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `Document purge predecessor[${index}] is missing`,\n );\n }\n await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle,\n enforceLocalCheckpoint: false,\n label: `Document purge predecessor[${index}]`,\n });\n }\n const head = await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle: input.proof.documentManifest,\n enforceLocalCheckpoint: input.enforceLocalCheckpoints,\n label: \"Document purge manifest\",\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [head],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return head;\n}\n\nexport async function verifyPurgeDocumentManifest(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest | VerifiedDocumentLinkSetSnapshot> {\n const verifiedByHash = new Map<string, VerifiedAccessManifestSnapshot>();\n const manifest = readAccessManifest(\n input.proof.documentManifest.manifest,\n \"Document purge manifest snapshot\",\n );\n const checkpointVerification = input.enforceLocalCheckpoints\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: verifiedByHash,\n })\n : undefined;\n const localCheckpoint = checkpointVerification?.localCheckpoint;\n const isPinnedHead =\n localCheckpoint?.epoch === manifest.epoch &&\n localCheckpoint.manifestHash === input.proof.documentManifest.manifestHash;\n // Baseline inspection may read a hash-only snapshot. Committing a purge\n // requires an exact existing pin or verified signed transitions from\n // that pin (or signed genesis for a fresh device).\n if (\n input.proof.documentManifestPredecessors.length > 0 ||\n (input.enforceLocalCheckpoints && !isPinnedHead)\n ) {\n return verifySignedPurgeDocumentManifestChain(input);\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...(checkpointVerification ?? {}),\n expectedManifestHash: input.proof.documentManifest.manifestHash,\n manifest,\n state: input.proof.documentManifest.state,\n });\n if (!verified.ok) throw verified.error;\n const documentManifest = verified.value;\n await recordSnapshotContainerEvidence({\n containerPathByManifestHash: input.containerPathByManifestHash,\n manifest: documentManifest,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n usedContainerManifests: input.usedContainerManifests,\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [documentManifest],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return documentManifest;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"documentPurgeDocumentChainVerification.js","sourceRoot":"","sources":["documentPurgeDocumentChainVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyAuthorization,\n type VerifiedAccessManifestSnapshot,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n verifyDocumentLinkSetSnapshot,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentPurgeProofResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalJson } from \"../keying/canonicalJson\";\nimport {\n addBundleByHash,\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport {\n observeAccessManifestCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { verifyDocumentManifestBundle } from \"./documentManifestVerification\";\nimport { loadManifestCheckpointVerification } from \"./manifestCheckpointVerification\";\nimport { readAccessManifest, readDocumentAccessEventBody } from \"./readers\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\nasync function verifyPinnedChainEndpoint(input: {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly checkpointContext: ProjectionCheckpointContext;\n}): Promise<VerifiedDocumentLinkSetSnapshot> {\n const manifest = readAccessManifest(\n input.bundle.manifest,\n \"Document purge predecessor endpoint manifest\",\n );\n const checkpointVerification = await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: new Map(),\n });\n const localCheckpoint = checkpointVerification.localCheckpoint;\n if (!localCheckpoint) {\n throw new ProjectionDependencyUnavailableError(\n \"Document purge history needs a local checkpoint or signed genesis\",\n );\n }\n if (\n localCheckpoint.epoch !== manifest.epoch ||\n localCheckpoint.manifestHash !== input.bundle.manifestHash\n ) {\n throw new KeyingVerificationError(\n localCheckpoint.epoch > manifest.epoch ? \"rollback\" : \"stale_predecessor\",\n \"Document purge predecessor chain does not start at the local checkpoint\",\n );\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...checkpointVerification,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n state: input.bundle.state,\n });\n if (!verified.ok) throw verified.error;\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(\n verified.value.state,\n \"Document purge predecessor endpoint state\",\n ),\n label: \"Document purge predecessor endpoint state\",\n });\n return verified.value;\n}\n\nasync function recordSnapshotContainerEvidence(input: {\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly manifest: VerifiedDocumentLinkSetSnapshot;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<void> {\n if (!input.usedContainerManifests) return;\n const event = await verifyAccessEventBundle({\n bundle: input.proof.documentManifest,\n label: \"Document purge manifest snapshot\",\n resolveUserKey: input.resolveUserKey,\n });\n if (event.eventHash !== input.manifest.manifest.eventHash) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"Document purge manifest snapshot event is not bound to its manifest\",\n );\n }\n const body = readDocumentAccessEventBody(\n event.body,\n \"Document purge manifest snapshot event body\",\n );\n const manifestHashes = [\n ...event.event.dependencyManifestHashes,\n body.containerManifestHash,\n ];\n for (const manifestHash of manifestHashes) {\n for (const containerManifest of input.containerPathByManifestHash.get(\n manifestHash,\n ) ?? []) {\n input.usedContainerManifests.set(\n containerManifest.manifestHash,\n containerManifest,\n );\n }\n }\n}\n\nasync function verifyPurgeChainEndpoint(\n input: Parameters<typeof verifySignedPurgeDocumentManifestChain>[0] & {\n readonly endpoint: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<\n string,\n AccessManifestBundleWireResponse\n >;\n readonly verifiedByHash: Map<string, VerifiedDocumentLinkSetManifest>;\n },\n): Promise<VerifiedDocumentLinkSetSnapshot | null> {\n const endpointManifest = readAccessManifest(\n input.endpoint.manifest,\n \"Document purge chain endpoint\",\n );\n if (endpointManifest.previousManifestHash === null) {\n await verifyDocumentManifestBundle({\n ...input,\n authorizationMembership: \"referenced\",\n bundle: input.endpoint,\n enforceLocalCheckpoint: false,\n label: \"Document purge genesis\",\n requireAuthorizationEvidence: true,\n });\n return null;\n }\n if (!input.enforceLocalCheckpoints) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Initial document purge history does not reach signed genesis\",\n );\n }\n return verifyPinnedChainEndpoint({\n bundle: input.endpoint,\n checkpointContext: input.checkpointContext,\n });\n}\n\nasync function verifySignedPurgeDocumentManifestChain(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n addBundleByHash(\n bundlesByHash,\n input.proof.documentManifest,\n \"Document purge manifest\",\n );\n for (const [\n index,\n bundle,\n ] of input.proof.documentManifestPredecessors.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge predecessor[${index}]`,\n );\n }\n\n const endpoint =\n input.proof.documentManifestPredecessors.at(-1) ??\n input.proof.documentManifest;\n const verifiedByHash = new Map<string, VerifiedDocumentLinkSetManifest>();\n const trustedPredecessorByHash = new Map<\n string,\n VerifiedDocumentLinkSetSnapshot\n >();\n const verifiedEndpoint = await verifyPurgeChainEndpoint({\n ...input,\n endpoint,\n bundlesByHash,\n verifiedByHash,\n });\n if (verifiedEndpoint) {\n trustedPredecessorByHash.set(\n verifiedEndpoint.manifestHash,\n verifiedEndpoint,\n );\n }\n\n const verificationInput = {\n ...input,\n authorizationMembership: \"referenced\" as const,\n bundlesByHash,\n requireAuthorizationEvidence: true,\n trustedPredecessorByHash,\n verifiedByHash,\n };\n for (\n let index = input.proof.documentManifestPredecessors.length - 2;\n index >= 0;\n index -= 1\n ) {\n const bundle = input.proof.documentManifestPredecessors[index];\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `Document purge predecessor[${index}] is missing`,\n );\n }\n await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle,\n enforceLocalCheckpoint: false,\n label: `Document purge predecessor[${index}]`,\n });\n }\n const head = await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle: input.proof.documentManifest,\n enforceLocalCheckpoint: input.enforceLocalCheckpoints,\n label: \"Document purge manifest\",\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [head],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return head;\n}\n\nexport async function verifyPurgeDocumentManifest(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest | VerifiedDocumentLinkSetSnapshot> {\n const verifiedByHash = new Map<string, VerifiedAccessManifestSnapshot>();\n const manifest = readAccessManifest(\n input.proof.documentManifest.manifest,\n \"Document purge manifest snapshot\",\n );\n const checkpointVerification = input.enforceLocalCheckpoints\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: verifiedByHash,\n })\n : undefined;\n const localCheckpoint = checkpointVerification?.localCheckpoint;\n const isPinnedHead =\n localCheckpoint?.epoch === manifest.epoch &&\n localCheckpoint.manifestHash === input.proof.documentManifest.manifestHash;\n // Baseline inspection may read a hash-only snapshot. Committing a purge\n // requires an exact existing pin or verified signed transitions from\n // that pin (or signed genesis for a fresh device).\n if (\n input.proof.documentManifestPredecessors.length > 0 ||\n (input.enforceLocalCheckpoints && !isPinnedHead)\n ) {\n return verifySignedPurgeDocumentManifestChain(input);\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...(checkpointVerification ?? {}),\n expectedManifestHash: input.proof.documentManifest.manifestHash,\n manifest,\n state: input.proof.documentManifest.state,\n });\n if (!verified.ok) throw verified.error;\n const documentManifest = verified.value;\n await recordSnapshotContainerEvidence({\n containerPathByManifestHash: input.containerPathByManifestHash,\n manifest: documentManifest,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n usedContainerManifests: input.usedContainerManifests,\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [documentManifest],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return documentManifest;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyingVerificationError } from "../../internal/crypto/index.js";
|
|
2
|
-
import { errorMessage } from "../errorMessage.js";
|
|
2
|
+
import { errorMessage } from "../shared/errorMessage.js";
|
|
3
3
|
import { isDatabaseUnavailableError } from "../sync/databaseUnavailable.js";
|
|
4
4
|
import { ProjectionDependencyUnavailableError } from "./dependencyUnavailable.js";
|
|
5
5
|
import { rethrowProjectionVerificationCancelled } from "./types.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["error.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { errorMessage } from \"../shared/errorMessage\";\nimport type {\n SecurityIncidentContext,\n SecurityIncidentReporter,\n} from \"../shared/securityIncidents\";\nimport { isDatabaseUnavailableError } from \"../sync/databaseUnavailable\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { rethrowProjectionVerificationCancelled } from \"./types\";\n\nconst KEYING_VERIFICATION_CONTEXT_LIMIT = 16;\nconst KEYING_VERIFICATION_CAUSE_LIMIT = 16;\n\n/** Use only for synchronous parsing of received protocol material. */\nexport function readKeyingVerificationShape<T>(read: () => T): T {\n try {\n return read();\n } catch (error) {\n if (error instanceof KeyingVerificationError) throw error;\n throw new KeyingVerificationError(\"invalid_shape\", errorMessage(error));\n }\n}\n\n/**\n * Preserve identity and projection verification failures across workflow\n * boundaries that intentionally soften ordinary transport or availability\n * errors. These failures are terminal: retrying or falling back could continue\n * with an untrusted identity.\n */\nexport function isKeyingVerificationError(\n error: unknown,\n): error is Error & { readonly code?: unknown } {\n return (\n error instanceof KeyingVerificationError ||\n (error instanceof Error && error.name === \"KeyingVerificationError\")\n );\n}\n\nexport function rethrowKeyingVerificationError(error: unknown): void {\n if (isKeyingVerificationError(error)) {\n throw error;\n }\n}\n\nfunction keyingVerificationErrorInCauseChain(\n error: unknown,\n): (Error & { readonly code?: unknown }) | null {\n let current = error;\n const seen = new Set<unknown>();\n for (let depth = 0; depth < KEYING_VERIFICATION_CAUSE_LIMIT; depth += 1) {\n if (isKeyingVerificationError(current)) return current;\n if (!(current instanceof Error) || seen.has(current)) return null;\n seen.add(current);\n current = current.cause;\n }\n return null;\n}\n\nexport async function reportKeyingVerificationErrorInCauseChain(\n error: unknown,\n reporter: SecurityIncidentReporter | undefined,\n context: SecurityIncidentContext,\n): Promise<boolean> {\n const verificationError = keyingVerificationErrorInCauseChain(error);\n if (!verificationError) return false;\n try {\n await reporter?.(verificationError, context);\n } catch {\n // Incident reporting is best-effort at this boundary. It must never replace\n // the boundary behavior that stopped use of untrusted data.\n }\n return true;\n}\n\n/**\n * Persist a terminal integrity failure before preserving the boundary error.\n * Call only outside an open persistence transaction: the reporter serializes\n * its own write and awaiting it from that transaction would deadlock.\n */\nexport async function reportAndRethrowKeyingVerificationError(\n error: unknown,\n reporter: SecurityIncidentReporter | undefined,\n context: SecurityIncidentContext,\n): Promise<void> {\n const reported = await reportKeyingVerificationErrorInCauseChain(\n error,\n reporter,\n context,\n );\n if (!reported) return;\n throw error;\n}\n\nexport async function runWithSecurityIncidentReporting<T>(\n reporter: SecurityIncidentReporter | undefined,\n context: SecurityIncidentContext,\n operation: () => Promise<T>,\n): Promise<T> {\n try {\n return await operation();\n } catch (error) {\n await reportAndRethrowKeyingVerificationError(error, reporter, context);\n throw error;\n }\n}\n\nexport function rethrowDatabaseUnavailableError(error: unknown): void {\n if (isDatabaseUnavailableError(error)) {\n throw error;\n }\n}\n\nexport function rethrowProjectionVerificationBoundaryError(\n error: unknown,\n): void {\n rethrowDatabaseUnavailableError(error);\n rethrowProjectionVerificationCancelled(error);\n if (error instanceof ProjectionDependencyUnavailableError) throw error;\n}\n\n/**\n * The verification layer reports a shape or hash failure in received protocol\n * material with a plain `Error` (or a `SyntaxError` from decoding its JSON).\n * Anything more specific is not evidence about that material: a boundary error\n * is retryable, a `TypeError` or other typed runtime failure is a defect, and a\n * non-Error value is a foreign throw. Those keep their type so callers can\n * classify them instead of recording them as tampering.\n */\nfunction isReceivedMaterialShapeFailure(error: unknown): error is Error {\n return (\n error instanceof Error &&\n (Object.getPrototypeOf(error) === Error.prototype ||\n error instanceof SyntaxError)\n );\n}\n\n/** Classify the failure of an async verification pass; never returns. */\nexport function throwKeyingVerificationShapeFailure(error: unknown): never {\n rethrowProjectionVerificationBoundaryError(error);\n if (\n isKeyingVerificationError(error) ||\n !isReceivedMaterialShapeFailure(error)\n )\n throw error;\n throw new KeyingVerificationError(\"invalid_shape\", error.message);\n}\n\nexport function throwKeyingVerificationErrorWithContext(\n error: unknown,\n context: string,\n): never {\n // Availability and cancellation keep their retryable types across contexts.\n rethrowProjectionVerificationBoundaryError(error);\n if (isKeyingVerificationError(error)) {\n // Preserve identity so nested reporting boundaries persist one incident.\n // The incident's operation supplies boundary context without minting a new\n // verification error that could bypass identity-based deduplication. Keep\n // the boundary labels non-enumerably for host-side diagnostics.\n try {\n const previous = Reflect.get(error, \"keyingVerificationContexts\");\n const contexts = Array.isArray(previous)\n ? [...previous, context].slice(-KEYING_VERIFICATION_CONTEXT_LIMIT)\n : [context];\n Object.defineProperty(error, \"keyingVerificationContexts\", {\n configurable: true,\n enumerable: false,\n value: contexts,\n });\n } catch {\n // A frozen foreign error still preserves its identity and code.\n }\n throw error;\n }\n const message = errorMessage(error);\n throw new Error(`${context}: ${message}`);\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProjectionUserKeyResolver } from "./types.js";
|
|
2
|
+
export { resolveEventContainerPaths } from "./documentDependencyPaths.js";
|
|
3
|
+
export { readAccessEvent, readRecordString, readRequiredRecordValue, } from "./readers.js";
|
|
4
|
+
export type { PrincipalPolicyCache, ProjectionUserKeyResolver, ReferencedPrincipalPolicyWarmer, } from "./types.js";
|
|
5
|
+
export { isProjectionVerificationCancelledError, nullOnProjectionVerificationCancellation, } from "./types.js";
|
|
6
|
+
export declare function requireProjectionUserKeyResolver(resolveProjectionUserKey: ProjectionUserKeyResolver | null | undefined, label: string): ProjectionUserKeyResolver;
|
|
7
|
+
export { collectContainerWriterProjectionPrincipalPolicies, verifyContainerWriterProjection, } from "./containerProjectionVerification.js";
|
|
8
|
+
export { type DocumentWriterProjectionAuthorization, verifyDocumentWriterProjection, verifyDocumentWriterProjectionAuthorization, } from "./documentProjectionVerification.js";
|
|
9
|
+
export { verifyDocumentPurgeProof, verifyDocumentPurgeProofBaseline, } from "./documentPurgeProofVerification.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { requireTrustedUserIdentityResolver } from "
|
|
2
|
-
export { resolveEventContainerPaths } from "./
|
|
3
|
-
export { readAccessEvent, readRecordString, readRequiredRecordValue, } from "./
|
|
4
|
-
export { isProjectionVerificationCancelledError, nullOnProjectionVerificationCancellation, } from "./
|
|
1
|
+
import { requireTrustedUserIdentityResolver } from "../trustedUserIdentity/requiredResolver.js";
|
|
2
|
+
export { resolveEventContainerPaths } from "./documentDependencyPaths.js";
|
|
3
|
+
export { readAccessEvent, readRecordString, readRequiredRecordValue, } from "./readers.js";
|
|
4
|
+
export { isProjectionVerificationCancelledError, nullOnProjectionVerificationCancellation, } from "./types.js";
|
|
5
5
|
export function requireProjectionUserKeyResolver(resolveProjectionUserKey, label) {
|
|
6
6
|
if (!resolveProjectionUserKey) {
|
|
7
7
|
throw new Error(`${label} requires projection key verification`);
|
|
@@ -10,7 +10,7 @@ export function requireProjectionUserKeyResolver(resolveProjectionUserKey, label
|
|
|
10
10
|
// provides the untrusted-shape and wrong-user guards (with identity caching).
|
|
11
11
|
return requireTrustedUserIdentityResolver(resolveProjectionUserKey);
|
|
12
12
|
}
|
|
13
|
-
export { collectContainerWriterProjectionPrincipalPolicies, verifyContainerWriterProjection, } from "./
|
|
14
|
-
export { verifyDocumentWriterProjection, verifyDocumentWriterProjectionAuthorization, } from "./
|
|
15
|
-
export { verifyDocumentPurgeProof, verifyDocumentPurgeProofBaseline, } from "./
|
|
16
|
-
//# sourceMappingURL=
|
|
13
|
+
export { collectContainerWriterProjectionPrincipalPolicies, verifyContainerWriterProjection, } from "./containerProjectionVerification.js";
|
|
14
|
+
export { verifyDocumentWriterProjection, verifyDocumentWriterProjectionAuthorization, } from "./documentProjectionVerification.js";
|
|
15
|
+
export { verifyDocumentPurgeProof, verifyDocumentPurgeProofBaseline, } from "./documentPurgeProofVerification.js";
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,yCAAyC,CAAC;AAG7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAOnB,OAAO,EACL,sCAAsC,EACtC,wCAAwC,GACzC,MAAM,SAAS,CAAC;AAEjB,MAAM,UAAU,gCAAgC,CAC9C,wBAAsE,EACtE,KAAa;IAEb,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,uCAAuC,CAAC,CAAC;IACnE,CAAC;IAED,sEAAsE;IACtE,8EAA8E;IAC9E,OAAO,kCAAkC,CAAC,wBAAwB,CAAC,CAAC;AACtE,CAAC;AAED,OAAO,EACL,iDAAiD,EACjD,+BAA+B,GAChC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,8BAA8B,EAC9B,2CAA2C,GAC5C,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,kCAAkC,CAAC","sourcesContent":["import { requireTrustedUserIdentityResolver } from \"../trustedUserIdentity/requiredResolver\";\nimport type { ProjectionUserKeyResolver } from \"./types\";\n\nexport { resolveEventContainerPaths } from \"./documentDependencyPaths\";\nexport {\n readAccessEvent,\n readRecordString,\n readRequiredRecordValue,\n} from \"./readers\";\n\nexport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\nexport {\n isProjectionVerificationCancelledError,\n nullOnProjectionVerificationCancellation,\n} from \"./types\";\n\nexport function requireProjectionUserKeyResolver(\n resolveProjectionUserKey: ProjectionUserKeyResolver | null | undefined,\n label: string,\n): ProjectionUserKeyResolver {\n if (!resolveProjectionUserKey) {\n throw new Error(`${label} requires projection key verification`);\n }\n\n // A ProjectionUserKey is a TrustedUserIdentity, so the shared adapter\n // provides the untrusted-shape and wrong-user guards (with identity caching).\n return requireTrustedUserIdentityResolver(resolveProjectionUserKey);\n}\n\nexport {\n collectContainerWriterProjectionPrincipalPolicies,\n verifyContainerWriterProjection,\n} from \"./containerProjectionVerification\";\nexport {\n type DocumentWriterProjectionAuthorization,\n verifyDocumentWriterProjection,\n verifyDocumentWriterProjectionAuthorization,\n} from \"./documentProjectionVerification\";\nexport {\n verifyDocumentPurgeProof,\n verifyDocumentPurgeProofBaseline,\n} from \"./documentPurgeProofVerification\";\n"]}
|