@tearleads/client-sdk 0.1.58 → 0.1.59
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 +2 -2
- package/Tearleads.js +1 -1
- package/Tearleads.js.map +1 -1
- package/client/blobs.d.ts +1 -1
- package/client/blobs.js.map +1 -1
- package/client/deviceFirst.js.map +1 -1
- package/client/identity.js +1 -1
- package/client/identity.js.map +1 -1
- package/client/index.d.ts +1 -1
- package/client/index.js +1 -1
- package/client/index.js.map +1 -1
- package/client/organizations/organizationAccessRestoration.js.map +1 -1
- package/client/organizations/organizationDataUsage.js.map +1 -1
- package/client/organizations/organizationGroupNameHydration.js.map +1 -1
- package/client/organizations/organizationMetadataProfileSync.js +1 -1
- package/client/organizations/organizationMetadataProfileSync.js.map +1 -1
- package/client/organizations/organizationReadModels.js.map +1 -1
- package/client/organizations/organizationWorkflowRuntime.js.map +1 -1
- package/client/rootContainerAdoption.js.map +1 -1
- package/client/securityIncidents.d.ts +1 -1
- package/client/securityIncidents.js.map +1 -1
- package/client/session/sessionLoginRefusal.js.map +1 -1
- package/client/session/sessionRootAuthority.js.map +1 -1
- package/client/session/sessionTypes.d.ts +1 -1
- package/client/session/sessionTypes.js.map +1 -1
- package/client/userIdentities.d.ts +1 -1
- package/client/userIdentities.js.map +1 -1
- package/client/workflowRuntime.d.ts +2 -2
- package/client/workflowRuntime.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/data/keyingCanonicalJson.js.map +0 -1
- package/data/keyingProjectionVerification.d.ts +0 -9
- package/data/keyingProjectionVerification.js.map +0 -1
- /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,4 +1,4 @@
|
|
|
1
|
-
import { collectContainerWriterProjectionPrincipalPolicies, } from "../../keyingProjectionVerification.js";
|
|
1
|
+
import { collectContainerWriterProjectionPrincipalPolicies, } from "../../keyingProjectionVerification/index.js";
|
|
2
2
|
import { resolveProjectionVerifier } from "./types.js";
|
|
3
3
|
export async function verifyContainerKekPathProjection(input) {
|
|
4
4
|
if (input.projection.path.length !== input.projection.containerKeks.length) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { computeAccessEventBodyHash, computeAccessEventHash, computeAccessManifestHash, computeDocumentContentKeyTargetHash, deriveDocumentLinkSetManifest, signAccessEvent, } from "../../../internal/crypto/index.js";
|
|
2
|
-
import { readCanonicalJson, readCanonicalRecord, } from "../../
|
|
2
|
+
import { readCanonicalJson, readCanonicalRecord, } from "../../keying/canonicalJson.js";
|
|
3
3
|
import { authorizingContainerPathRefsForLinkSet, containerPathRefs, deriveDocumentCreateTargets, mergeTargetEnvelopes, } from "./projection.js";
|
|
4
4
|
import { sortDocumentTargets, uniqueSortedStrings } from "./readers.js";
|
|
5
5
|
export async function buildDocumentCreatePlan({ author, containerProjection, contentKeyEpoch = 1, documentId = crypto.randomUUID(), eventId = crypto.randomUUID(), signedAt = new Date().toISOString(), targetEnvelopes, }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["events.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,mCAAmC,EAGnC,6BAA6B,EAC7B,eAAe,GAEhB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,sCAAsC,EACtC,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAWrE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,EAC5C,MAAM,EACN,mBAAmB,EACnB,eAAe,GAAG,CAAC,EACnB,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,EAChC,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,EAC7B,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EACnC,eAAe,GACc;IAC7B,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,cAAc,GAAG,mBAAmB,CAAC,cAAc,CAAC;IAE1D,MAAM,OAAO,GAAG,2BAA2B,CAAC,mBAAmB,CAAC,CAAC;IACjE,MAAM,yBAAyB,GAAG,oBAAoB,CACpD,OAAO,EACP,eAAe,CAChB,CAAC;IACF,MAAM,2BAA2B,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,qBAAqB,CAAC;IACtE,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;IAClD,IAAI,CAAC,2BAA2B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,GAAgC;QACxC,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,eAAe;QAC1B,WAAW,EAAE,iBAAiB;QAC9B,qBAAqB,EAAE,2BAA2B;KACnD,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAC/C,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAChD,CAAC;IACF,MAAM,aAAa,GAAwB;QACzC,OAAO,EAAE,CAAC;QACV,OAAO;QACP,SAAS,EAAE,eAAe;QAC1B,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,UAAU;QACpB,cAAc;QACd,oBAAoB,EAAE,IAAI;QAC1B,wBAAwB,EAAE,mBAAmB,CAC3C,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAC9D;QACD,QAAQ;QACR,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;QACjD,QAAQ;KACT,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,KAAK,GAAiC;QAC1C,OAAO,EAAE,CAAC;QACV,UAAU;QACV,cAAc;QACd,KAAK,EAAE,CAAC;QACR,oBAAoB,EAAE,IAAI;QAC1B,SAAS;QACT,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;KACxC,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,6BAA6B,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,MAAM,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,MAAM,mCAAmC,CAAC,OAAO,CAAC,CAAC;IAEtE,OAAO;QACL,IAAI;QACJ,UAAU;QACV,KAAK;QACL,SAAS;QACT,QAAQ;QACR,YAAY;QACZ,OAAO,EAAE;YACP,KAAK,EAAE,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,CAAC;YAC1D,IAAI,EAAE,mBAAmB,CAAC,IAAI,EAAE,sBAAsB,CAAC;YACvD,oBAAoB,EAAE,YAAY;YAClC,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,EAAE,0BAA0B,CAAC;YACnE,uBAAuB,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,IAAI,CAAC;YACpE,gBAAgB,EAAE;gBAChB,eAAe;gBACf,mBAAmB,EAAE,YAAY;gBACjC,UAAU;gBACV,OAAO,EAAE,yBAAyB;aACnC;SACF;QACD,KAAK;QACL,UAAU;QACV,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,KAanD;IACC,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACnE,MAAM,IAAI,GAAgC;QACxC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS;QACT,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW;QACjD,qBAAqB,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,qBAAqB;KACtE,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAC/C,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAClD,CAAC;IACF,MAAM,4BAA4B,GAAG,sCAAsC,CAAC;QAC1E,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,iBAAiB,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW;QACvD,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;KACzC,CAAC,CAAC;IACH,MAAM,wBAAwB,GAAG,mBAAmB,CAClD;QACE,GAAG,KAAK,CAAC,uBAAuB;QAChC,GAAG,4BAA4B,CAAC,IAAI,EAAE;KACvC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CACjC,CAAC;IACF,MAAM,aAAa,GAAwB;QACzC,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS;QACT,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,UAAU;QAC3C,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,oBAAoB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,YAAY;QAC1E,wBAAwB;QACxB,QAAQ;QACR,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;QACvC,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;QAC3C,oBAAoB,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB;QACvD,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,eAAe,CACjC,aAAa,EACb,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAC9B,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAEtD,OAAO;QACL,4BAA4B;QAC5B,IAAI;QACJ,KAAK;QACL,SAAS;KACV,CAAC;AACJ,CAAC","sourcesContent":["import {\n computeAccessEventBodyHash,\n computeAccessEventHash,\n computeAccessManifestHash,\n computeDocumentContentKeyTargetHash,\n type DocumentLinkAccessEventBody,\n type DocumentLinkSetManifestState,\n deriveDocumentLinkSetManifest,\n signAccessEvent,\n type UnsignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { ContainerManifestRef } from \"@tearleads/validators/request\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../keyingCanonicalJson\";\nimport {\n authorizingContainerPathRefsForLinkSet,\n containerPathRefs,\n deriveDocumentCreateTargets,\n mergeTargetEnvelopes,\n} from \"./projection\";\nimport { sortDocumentTargets, uniqueSortedStrings } from \"./readers\";\nimport type {\n BuildDocumentCreatePlanInput,\n DocumentCreateAuthor,\n DocumentCreatePlan,\n DocumentLinkSetEventPlan,\n DocumentLinkSetMutationBody,\n DocumentLinkSetMutationOperation,\n DocumentLinkSetTargetState,\n} from \"./types\";\n\nexport async function buildDocumentCreatePlan({\n author,\n containerProjection,\n contentKeyEpoch = 1,\n documentId = crypto.randomUUID(),\n eventId = crypto.randomUUID(),\n signedAt = new Date().toISOString(),\n targetEnvelopes,\n}: BuildDocumentCreatePlanInput): Promise<DocumentCreatePlan> {\n // The document belongs to its container's organization, not the author's. A\n // member authoring a document under another org's shared container creates a\n // document owned by that org; the author supplies only the signer identity.\n const organizationId = containerProjection.organizationId;\n\n const targets = deriveDocumentCreateTargets(containerProjection);\n const targetEnvelopesForRequest = mergeTargetEnvelopes(\n targets,\n targetEnvelopes,\n );\n const targetContainerManifestHash = targets[0]?.containerManifestHash;\n const targetContainerId = targets[0]?.containerId;\n if (!targetContainerManifestHash || !targetContainerId) {\n throw new Error(\"Document create target is unavailable\");\n }\n\n const body: DocumentLinkAccessEventBody = {\n blobRewraps: [],\n eventType: \"document.link\",\n containerId: targetContainerId,\n containerManifestHash: targetContainerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document create body\"),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId,\n eventType: \"document.link\",\n objectKind: \"document\",\n objectId: documentId,\n organizationId,\n previousManifestHash: null,\n dependencyManifestHashes: uniqueSortedStrings(\n containerProjection.path.map((bundle) => bundle.manifestHash),\n ),\n bodyHash,\n signerUserId: author.signerUserId,\n signerDeviceId: author.signerDeviceId,\n signerKeyFingerprint: author.signerKeyFingerprint,\n signedAt,\n };\n const event = await signAccessEvent(unsignedEvent, author.signerPrivateKey);\n const eventHash = await computeAccessEventHash(event);\n const state: DocumentLinkSetManifestState = {\n version: 1,\n documentId,\n organizationId,\n epoch: 1,\n previousManifestHash: null,\n eventHash,\n linkedContainerIds: [targetContainerId],\n };\n const manifest = await deriveDocumentLinkSetManifest(state);\n const manifestHash = await computeAccessManifestHash(manifest);\n const targetHash = await computeDocumentContentKeyTargetHash(targets);\n\n return {\n body,\n documentId,\n event,\n eventHash,\n manifest,\n manifestHash,\n request: {\n event: readCanonicalRecord(event, \"Document create event\"),\n body: readCanonicalRecord(body, \"Document create body\"),\n expectedManifestHash: manifestHash,\n manifest: readCanonicalRecord(manifest, \"Document create manifest\"),\n targetContainerPathRefs: containerPathRefs(containerProjection.path),\n contentKeyBundle: {\n contentKeyEpoch,\n linkSetManifestHash: manifestHash,\n targetHash,\n targets: targetEnvelopesForRequest,\n },\n },\n state,\n targetHash,\n targets: sortDocumentTargets(targets),\n };\n}\n\nexport async function buildDocumentLinkSetEventPlan(input: {\n blobRewraps: DocumentLinkAccessEventBody[\"blobRewraps\"];\n author: DocumentCreateAuthor;\n eventId: string;\n operation: DocumentLinkSetMutationOperation;\n // The document's existing organization (from its manifest). Link/unlink does\n // not change ownership, so the event keeps the document's org, which is the\n // container's org — never the acting member's personal org.\n organizationId: string;\n signedAt: string;\n targetContainerPathRefs: readonly ContainerManifestRef[];\n targetState: DocumentLinkSetTargetState;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<DocumentLinkSetEventPlan> {\n const eventType =\n input.operation === \"link\" ? \"document.link\" : \"document.unlink\";\n const body: DocumentLinkSetMutationBody = {\n blobRewraps: input.blobRewraps,\n eventType,\n containerId: input.targetState.target.containerId,\n containerManifestHash: input.targetState.target.containerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document link-set body\"),\n );\n const authorizingContainerPathRefs = authorizingContainerPathRefsForLinkSet({\n operation: input.operation,\n targetContainerId: input.targetState.target.containerId,\n writerProjection: input.writerProjection,\n });\n const dependencyManifestHashes = uniqueSortedStrings(\n [\n ...input.targetContainerPathRefs,\n ...authorizingContainerPathRefs.flat(),\n ].map((ref) => ref.manifestHash),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId,\n eventType,\n objectKind: \"document\",\n objectId: input.writerProjection.documentId,\n organizationId: input.organizationId,\n previousManifestHash: input.writerProjection.documentManifest.manifestHash,\n dependencyManifestHashes,\n bodyHash,\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n };\n const event = await signAccessEvent(\n unsignedEvent,\n input.author.signerPrivateKey,\n );\n const eventHash = await computeAccessEventHash(event);\n\n return {\n authorizingContainerPathRefs,\n body,\n event,\n eventHash,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["events.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeAccessEventBodyHash,\n computeAccessEventHash,\n computeAccessManifestHash,\n computeDocumentContentKeyTargetHash,\n type DocumentLinkAccessEventBody,\n type DocumentLinkSetManifestState,\n deriveDocumentLinkSetManifest,\n signAccessEvent,\n type UnsignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { ContainerManifestRef } from \"@tearleads/validators/request\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../keying/canonicalJson\";\nimport {\n authorizingContainerPathRefsForLinkSet,\n containerPathRefs,\n deriveDocumentCreateTargets,\n mergeTargetEnvelopes,\n} from \"./projection\";\nimport { sortDocumentTargets, uniqueSortedStrings } from \"./readers\";\nimport type {\n BuildDocumentCreatePlanInput,\n DocumentCreateAuthor,\n DocumentCreatePlan,\n DocumentLinkSetEventPlan,\n DocumentLinkSetMutationBody,\n DocumentLinkSetMutationOperation,\n DocumentLinkSetTargetState,\n} from \"./types\";\n\nexport async function buildDocumentCreatePlan({\n author,\n containerProjection,\n contentKeyEpoch = 1,\n documentId = crypto.randomUUID(),\n eventId = crypto.randomUUID(),\n signedAt = new Date().toISOString(),\n targetEnvelopes,\n}: BuildDocumentCreatePlanInput): Promise<DocumentCreatePlan> {\n // The document belongs to its container's organization, not the author's. A\n // member authoring a document under another org's shared container creates a\n // document owned by that org; the author supplies only the signer identity.\n const organizationId = containerProjection.organizationId;\n\n const targets = deriveDocumentCreateTargets(containerProjection);\n const targetEnvelopesForRequest = mergeTargetEnvelopes(\n targets,\n targetEnvelopes,\n );\n const targetContainerManifestHash = targets[0]?.containerManifestHash;\n const targetContainerId = targets[0]?.containerId;\n if (!targetContainerManifestHash || !targetContainerId) {\n throw new Error(\"Document create target is unavailable\");\n }\n\n const body: DocumentLinkAccessEventBody = {\n blobRewraps: [],\n eventType: \"document.link\",\n containerId: targetContainerId,\n containerManifestHash: targetContainerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document create body\"),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId,\n eventType: \"document.link\",\n objectKind: \"document\",\n objectId: documentId,\n organizationId,\n previousManifestHash: null,\n dependencyManifestHashes: uniqueSortedStrings(\n containerProjection.path.map((bundle) => bundle.manifestHash),\n ),\n bodyHash,\n signerUserId: author.signerUserId,\n signerDeviceId: author.signerDeviceId,\n signerKeyFingerprint: author.signerKeyFingerprint,\n signedAt,\n };\n const event = await signAccessEvent(unsignedEvent, author.signerPrivateKey);\n const eventHash = await computeAccessEventHash(event);\n const state: DocumentLinkSetManifestState = {\n version: 1,\n documentId,\n organizationId,\n epoch: 1,\n previousManifestHash: null,\n eventHash,\n linkedContainerIds: [targetContainerId],\n };\n const manifest = await deriveDocumentLinkSetManifest(state);\n const manifestHash = await computeAccessManifestHash(manifest);\n const targetHash = await computeDocumentContentKeyTargetHash(targets);\n\n return {\n body,\n documentId,\n event,\n eventHash,\n manifest,\n manifestHash,\n request: {\n event: readCanonicalRecord(event, \"Document create event\"),\n body: readCanonicalRecord(body, \"Document create body\"),\n expectedManifestHash: manifestHash,\n manifest: readCanonicalRecord(manifest, \"Document create manifest\"),\n targetContainerPathRefs: containerPathRefs(containerProjection.path),\n contentKeyBundle: {\n contentKeyEpoch,\n linkSetManifestHash: manifestHash,\n targetHash,\n targets: targetEnvelopesForRequest,\n },\n },\n state,\n targetHash,\n targets: sortDocumentTargets(targets),\n };\n}\n\nexport async function buildDocumentLinkSetEventPlan(input: {\n blobRewraps: DocumentLinkAccessEventBody[\"blobRewraps\"];\n author: DocumentCreateAuthor;\n eventId: string;\n operation: DocumentLinkSetMutationOperation;\n // The document's existing organization (from its manifest). Link/unlink does\n // not change ownership, so the event keeps the document's org, which is the\n // container's org — never the acting member's personal org.\n organizationId: string;\n signedAt: string;\n targetContainerPathRefs: readonly ContainerManifestRef[];\n targetState: DocumentLinkSetTargetState;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<DocumentLinkSetEventPlan> {\n const eventType =\n input.operation === \"link\" ? \"document.link\" : \"document.unlink\";\n const body: DocumentLinkSetMutationBody = {\n blobRewraps: input.blobRewraps,\n eventType,\n containerId: input.targetState.target.containerId,\n containerManifestHash: input.targetState.target.containerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document link-set body\"),\n );\n const authorizingContainerPathRefs = authorizingContainerPathRefsForLinkSet({\n operation: input.operation,\n targetContainerId: input.targetState.target.containerId,\n writerProjection: input.writerProjection,\n });\n const dependencyManifestHashes = uniqueSortedStrings(\n [\n ...input.targetContainerPathRefs,\n ...authorizingContainerPathRefs.flat(),\n ].map((ref) => ref.manifestHash),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId,\n eventType,\n objectKind: \"document\",\n objectId: input.writerProjection.documentId,\n organizationId: input.organizationId,\n previousManifestHash: input.writerProjection.documentManifest.manifestHash,\n dependencyManifestHashes,\n bodyHash,\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n };\n const event = await signAccessEvent(\n unsignedEvent,\n input.author.signerPrivateKey,\n );\n const eventHash = await computeAccessEventHash(event);\n\n return {\n authorizingContainerPathRefs,\n body,\n event,\n eventHash,\n };\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { computeAccessEventHash, computeAccessManifestHash, deriveDocumentLinkSetManifest, } from "../../../internal/crypto/index.js";
|
|
2
2
|
import { isPlainObject as isPlainRecord } from "../../../internal/validators/isPlainObject.js";
|
|
3
|
-
import { canonicalKeyingJsonString, readCanonicalRecord, } from "../../
|
|
3
|
+
import { canonicalKeyingJsonString, readCanonicalRecord, } from "../../keying/canonicalJson.js";
|
|
4
4
|
import { readAccessEvent, readAccessManifest, } from "../../keyingProjectionVerification/readers.js";
|
|
5
|
-
import { readRecordInteger, readRecordNullableString, readRecordPositiveInteger, readRecordString, readRecordValue, readStringArray, } from "../../recordReaders.js";
|
|
5
|
+
import { readRecordInteger, readRecordNullableString, readRecordPositiveInteger, readRecordString, readRecordValue, readStringArray, } from "../../shared/recordReaders.js";
|
|
6
6
|
function readDocumentLinkSetManifestState(value, label) {
|
|
7
7
|
const record = readCanonicalRecord(value, label);
|
|
8
8
|
if (readRecordInteger(record, "version", label) !== 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifestBundleReaders.js","sourceRoot":"","sources":["manifestBundleReaders.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EAEzB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAErF,OAAO,EACL,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,
|
|
1
|
+
{"version":3,"file":"manifestBundleReaders.js","sourceRoot":"","sources":["manifestBundleReaders.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeAccessEventHash,\n computeAccessManifestHash,\n type DocumentLinkSetManifestState,\n deriveDocumentLinkSetManifest,\n} from \"@tearleads/crypto\";\nimport { isPlainObject as isPlainRecord } from \"@tearleads/validators/isPlainObject\";\nimport type { DocumentCreateResponse } from \"@tearleads/validators/response\";\nimport {\n canonicalKeyingJsonString,\n readCanonicalRecord,\n} from \"../../keying/canonicalJson\";\nimport {\n readAccessEvent,\n readAccessManifest,\n} from \"../../keyingProjectionVerification/readers\";\nimport {\n readRecordInteger,\n readRecordNullableString,\n readRecordPositiveInteger,\n readRecordString,\n readRecordValue,\n readStringArray,\n} from \"../../shared/recordReaders\";\n\nfunction readDocumentLinkSetManifestState(\n value: unknown,\n label: string,\n): DocumentLinkSetManifestState {\n const record = readCanonicalRecord(value, label);\n if (readRecordInteger(record, \"version\", label) !== 1) {\n throw new Error(`${label}.version must be 1`);\n }\n\n return {\n version: 1,\n documentId: readRecordString(record, \"documentId\", label),\n organizationId: readRecordString(record, \"organizationId\", label),\n epoch: readRecordPositiveInteger(record, \"epoch\", label),\n previousManifestHash: readRecordNullableString(\n record,\n \"previousManifestHash\",\n label,\n ),\n eventHash: readRecordString(record, \"eventHash\", label),\n linkedContainerIds: readStringArray(\n readRecordValue(record, \"linkedContainerIds\"),\n `${label}.linkedContainerIds`,\n ),\n };\n}\n\nexport function serializeCanonical(value: unknown, label: string): string {\n if (\n value === undefined ||\n typeof value === \"function\" ||\n typeof value === \"symbol\"\n ) {\n throw new Error(`Document create response ${label} is invalid`);\n }\n\n return canonicalKeyingJsonString(value, `Document create response ${label}`);\n}\n\nexport async function assertDocumentManifestBundleConsistent(input: {\n bundle: DocumentCreateResponse[\"accessManifest\"];\n label: string;\n}): Promise<{ documentId: string; organizationId: string }> {\n const manifestHash = await computeAccessManifestHash(\n readAccessManifest(input.bundle.manifest, `${input.label} manifest`),\n );\n if (manifestHash !== input.bundle.manifestHash) {\n throw new Error(`${input.label} manifest hash mismatch`);\n }\n\n const eventBundle = input.bundle.event;\n if (!isPlainRecord(eventBundle)) {\n throw new Error(`${input.label} event bundle is invalid`);\n }\n const eventHash = readRecordString(eventBundle, \"eventHash\", input.label);\n const event = Reflect.get(eventBundle, \"event\");\n const accessEvent = readAccessEvent(event, `${input.label} signed event`);\n const computedEventHash = await computeAccessEventHash(accessEvent);\n if (computedEventHash !== eventHash) {\n throw new Error(`${input.label} event hash mismatch`);\n }\n\n const state = readDocumentLinkSetManifestState(\n input.bundle.state,\n `${input.label} state`,\n );\n if (state.eventHash !== eventHash) {\n throw new Error(`${input.label} state event hash mismatch`);\n }\n const derivedManifest = await deriveDocumentLinkSetManifest(state);\n if (\n serializeCanonical(input.bundle.manifest, \"manifest\") !==\n serializeCanonical(derivedManifest, \"manifest\")\n ) {\n throw new Error(`${input.label} manifest state mismatch`);\n }\n\n return {\n documentId: state.documentId,\n organizationId: state.organizationId,\n };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DocumentContentKeyTarget, VerifiedContainerAccessManifest } from "../../../internal/crypto/index.js";
|
|
2
2
|
import type { DocumentWriterProjectionResponse } from "../../../internal/validators/response/index.js";
|
|
3
|
-
import { type DocumentWriterProjectionAuthorization, type PrincipalPolicyCache } from "../../keyingProjectionVerification.js";
|
|
3
|
+
import { type DocumentWriterProjectionAuthorization, type PrincipalPolicyCache } from "../../keyingProjectionVerification/index.js";
|
|
4
4
|
import type { ExecSql } from "../../sqlite/sqlSchema.js";
|
|
5
5
|
export { unwrapContainerKekPath } from "./containerKekPath.js";
|
|
6
6
|
export { ContainerKekHistoryUnavailableError } from "./containerKekPathHistory.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { computeDocumentContentKeyTargetHash } from "../../../internal/crypto/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import { verifyDocumentWriterProjectionAuthorization, } from "../../keyingProjectionVerification.js";
|
|
2
|
+
import { verifyDocumentWriterProjectionAuthorization, } from "../../keyingProjectionVerification/index.js";
|
|
4
3
|
import { throwKeyingVerificationShapeFailure } from "../../keyingProjectionVerification/error.js";
|
|
4
|
+
import { errorMessage } from "../../shared/errorMessage.js";
|
|
5
5
|
import { currentDocumentTargets, deriveDocumentTargetFromProjection, readLinkedContainerIdsFromDocumentManifest, } from "./projectionTargets.js";
|
|
6
6
|
import { assertDocumentManifestBundleConsistent, normalizeDocumentKekTargetResponse, sortDocumentTargets, targetEnvelopeReference, targetKey, uniqueSortedStrings, } from "./readers.js";
|
|
7
7
|
export { unwrapContainerKekPath } from "./containerKekPath.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projection.js","sourceRoot":"","sources":["projection.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n DocumentContentKeyTarget,\n VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport { computeDocumentContentKeyTargetHash } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { errorMessage } from \"../../errorMessage\";\nimport {\n type DocumentWriterProjectionAuthorization,\n type PrincipalPolicyCache,\n verifyDocumentWriterProjectionAuthorization,\n} from \"../../keyingProjectionVerification\";\nimport { throwKeyingVerificationShapeFailure } from \"../../keyingProjectionVerification/error\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport {\n currentDocumentTargets,\n deriveDocumentTargetFromProjection,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"./projectionTargets\";\nimport {\n assertDocumentManifestBundleConsistent,\n normalizeDocumentKekTargetResponse,\n sortDocumentTargets,\n targetEnvelopeReference,\n targetKey,\n uniqueSortedStrings,\n} from \"./readers\";\n\nexport { unwrapContainerKekPath } from \"./containerKekPath\";\nexport { ContainerKekHistoryUnavailableError } from \"./containerKekPathHistory\";\nexport {\n buildRotatedDocumentContentKeyBundle,\n collectContainerKeksForDocumentSync,\n DocumentContentKeyUnavailableError,\n DocumentHistoryUnavailableError,\n unwrapDocumentContentKeyFromBundle,\n unwrapDocumentContentKeyFromWriterProjection,\n unwrapDocumentContentKeyTarget,\n wrapDocumentContentKeyForCreate,\n} from \"./projectionContentKeys\";\nexport {\n authorizingContainerPathRefs,\n authorizingContainerPathRefsForLinkSet,\n containerPathRefs,\n currentDocumentTargets,\n deriveDocumentCreateTargets,\n deriveDocumentTargetFromProjection,\n mergeTargetEnvelopes,\n readLinkedContainerIdsFromDocumentManifest,\n verifiedDocumentWrapTargets,\n} from \"./projectionTargets\";\n\nimport type { ProjectionVerificationOptions } from \"./types\";\nimport { resolveProjectionVerifier } from \"./types\";\n\nfunction assertSortedStringsEqual(\n left: readonly string[],\n right: readonly string[],\n message: string,\n): void {\n if (\n left.length !== right.length ||\n left.some((value, index) => value !== right[index])\n ) {\n throw new Error(message);\n }\n}\n\nfunction assertAuthorizingContainerPathsMatchDocumentTargets(input: {\n targets: readonly DocumentContentKeyTarget[];\n writerProjection: DocumentWriterProjectionResponse;\n}): void {\n if (input.writerProjection.authorizingContainerPaths.length === 0) {\n throw new Error(\"Document writer projection authorization paths missing\");\n }\n\n const targetKeys = new Set(input.targets.map(targetKey));\n for (const [\n index,\n projection,\n ] of input.writerProjection.authorizingContainerPaths.entries()) {\n let projectionTarget: DocumentContentKeyTarget;\n try {\n projectionTarget = deriveDocumentTargetFromProjection(projection);\n } catch (error) {\n throw new Error(\n `Document writer projection authorization path[${index}] is invalid: ${errorMessage(error)}`,\n );\n }\n\n if (targetKeys.has(targetKey(projectionTarget))) {\n continue;\n }\n\n // Bind server-supplied KEK paths to committed document targets before\n // using any unwrapped path KEK for document content-key material.\n throw new Error(\n `Document writer projection authorization path[${index}] is not a document target`,\n );\n }\n}\n\nfunction assertDocumentTargetsCoverLinkedContainers(\n targets: readonly DocumentContentKeyTarget[],\n writerProjection: DocumentWriterProjectionResponse,\n): void {\n // One target per linked container: a second epoch for the same container\n // would let a re-wrap land on a KEK a revoked member still holds.\n if (\n new Set(targets.map((target) => target.containerId)).size !== targets.length\n ) {\n throw new Error(\n \"Document writer projection targets name a linked container more than once\",\n );\n }\n assertSortedStringsEqual(\n uniqueSortedStrings(targets.map((target) => target.containerId)),\n readLinkedContainerIdsFromDocumentManifest(writerProjection),\n \"Document writer projection targets do not match linked containers\",\n );\n assertSortedStringsEqual(\n uniqueSortedStrings(\n writerProjection.documentKekTargets.linkedContainerManifestHashes,\n ),\n uniqueSortedStrings(targets.map((target) => target.containerManifestHash)),\n \"Document writer projection target manifest summary mismatch\",\n );\n assertSortedStringsEqual(\n uniqueSortedStrings(\n writerProjection.documentKekTargets.linkedContainerKeyEpochIds,\n ),\n uniqueSortedStrings(targets.map((target) => target.containerKeyEpochId)),\n \"Document writer projection target KEK summary mismatch\",\n );\n}\n\nasync function assertProjectionContentKeyBundleConsistent(\n writerProjection: DocumentWriterProjectionResponse,\n staleContentKeyBundle: boolean,\n): Promise<void> {\n const { manifestHash } = writerProjection.documentManifest;\n if (writerProjection.contentKeyBundle.linkSetManifestHash !== manifestHash) {\n // A stale bundle may lag the link-set head, but it must still descend\n // from this document's manifest chain.\n if (\n !staleContentKeyBundle ||\n !writerProjection.documentManifestHistory.some(\n (bundle) =>\n bundle.manifestHash ===\n writerProjection.contentKeyBundle.linkSetManifestHash,\n )\n ) {\n throw new Error(\"Document writer projection link manifest mismatch\");\n }\n }\n\n if (!staleContentKeyBundle) {\n if (\n writerProjection.documentKekTargets.documentKeyTargetHash !==\n writerProjection.contentKeyBundle.targetHash\n ) {\n throw new Error(\"Document writer projection target hash mismatch\");\n }\n return;\n }\n\n // The stale bundle cannot match the current targets; pin it to its own\n // canonical hash instead so a tampered envelope set still fails closed.\n const staleBundleTargetHash = await computeDocumentContentKeyTargetHash(\n sortDocumentTargets(\n writerProjection.contentKeyBundle.targets.map(targetEnvelopeReference),\n ),\n );\n if (staleBundleTargetHash !== writerProjection.contentKeyBundle.targetHash) {\n throw new Error(\n \"Document writer projection stale bundle target hash is not canonical\",\n );\n }\n}\n\nasync function assertDocumentWriterProjectionConsistentInternal(\n writerProjection: DocumentWriterProjectionResponse,\n input: ProjectionVerificationOptions & {\n /**\n * Accept a projection whose content-key bundle is marked stale (wrapped\n * to superseded KEK targets after e.g. a revoke rotation). Document sync\n * opts in to heal the bundle. Attachment reads opt in because their DEK\n * is independent and opens through verified retained container KEKs.\n */\n allowStaleContentKeyBundle?: boolean | undefined;\n execSql?: ExecSql | undefined;\n persistVerificationCheckpoints?: boolean | undefined;\n onVerifiedAuthorization?:\n | ((authorization: DocumentWriterProjectionAuthorization) => void)\n | undefined;\n principalPolicyCache?: PrincipalPolicyCache | undefined;\n stillCurrent?: (() => boolean) | undefined;\n verifiedByHash?: Map<string, VerifiedContainerAccessManifest> | undefined;\n },\n): Promise<DocumentContentKeyTarget[]> {\n const resolveProjectionUserKey = resolveProjectionVerifier(\n input,\n \"Document writer projection\",\n );\n if (\n input.trustedLocalProjection !== true &&\n resolveProjectionUserKey !== null\n ) {\n const authorization = await verifyDocumentWriterProjectionAuthorization({\n execSql: input.execSql,\n persistVerificationCheckpoints: input.persistVerificationCheckpoints,\n principalPolicyCache: input.principalPolicyCache,\n projection: writerProjection,\n resolveUserKey: resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n verifiedByHash: input.verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n input.onVerifiedAuthorization?.(authorization);\n }\n\n const staleContentKeyBundle = writerProjection.contentKeyBundleStale === true;\n if (staleContentKeyBundle && input.allowStaleContentKeyBundle !== true) {\n throw new Error(\"Document writer projection content-key bundle is stale\");\n }\n\n const manifestIdentity = await assertDocumentManifestBundleConsistent({\n bundle: writerProjection.documentManifest,\n label: \"Document writer projection manifest\",\n });\n const { documentId } = manifestIdentity;\n if (\n writerProjection.documentId !== documentId ||\n writerProjection.documentKekTargets.documentId !== documentId ||\n writerProjection.contentKeyBundle.documentId !== documentId\n ) {\n throw new Error(\"Document writer projection document id mismatch\");\n }\n if (\n writerProjection.documentKekTargets.linkSetManifestHash !==\n writerProjection.documentManifest.manifestHash\n ) {\n throw new Error(\"Document writer projection link manifest mismatch\");\n }\n await assertProjectionContentKeyBundleConsistent(\n writerProjection,\n staleContentKeyBundle,\n );\n\n const targets = staleContentKeyBundle\n ? normalizeDocumentKekTargetResponse(writerProjection.documentKekTargets)\n : currentDocumentTargets(writerProjection);\n const canonicalTargetHash =\n await computeDocumentContentKeyTargetHash(targets);\n if (\n canonicalTargetHash !==\n writerProjection.documentKekTargets.documentKeyTargetHash\n ) {\n throw new Error(\"Document writer projection target hash is not canonical\");\n }\n\n assertDocumentTargetsCoverLinkedContainers(targets, writerProjection);\n assertAuthorizingContainerPathsMatchDocumentTargets({\n targets,\n writerProjection,\n });\n\n return targets;\n}\n\nexport async function assertDocumentWriterProjectionConsistent(\n ...input: Parameters<typeof assertDocumentWriterProjectionConsistentInternal>\n): ReturnType<typeof assertDocumentWriterProjectionConsistentInternal> {\n try {\n return await assertDocumentWriterProjectionConsistentInternal(...input);\n } catch (error) {\n throwKeyingVerificationShapeFailure(error);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"projection.js","sourceRoot":"","sources":["projection.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n DocumentContentKeyTarget,\n VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport { computeDocumentContentKeyTargetHash } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n type DocumentWriterProjectionAuthorization,\n type PrincipalPolicyCache,\n verifyDocumentWriterProjectionAuthorization,\n} from \"../../keyingProjectionVerification\";\nimport { throwKeyingVerificationShapeFailure } from \"../../keyingProjectionVerification/error\";\nimport { errorMessage } from \"../../shared/errorMessage\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport {\n currentDocumentTargets,\n deriveDocumentTargetFromProjection,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"./projectionTargets\";\nimport {\n assertDocumentManifestBundleConsistent,\n normalizeDocumentKekTargetResponse,\n sortDocumentTargets,\n targetEnvelopeReference,\n targetKey,\n uniqueSortedStrings,\n} from \"./readers\";\n\nexport { unwrapContainerKekPath } from \"./containerKekPath\";\nexport { ContainerKekHistoryUnavailableError } from \"./containerKekPathHistory\";\nexport {\n buildRotatedDocumentContentKeyBundle,\n collectContainerKeksForDocumentSync,\n DocumentContentKeyUnavailableError,\n DocumentHistoryUnavailableError,\n unwrapDocumentContentKeyFromBundle,\n unwrapDocumentContentKeyFromWriterProjection,\n unwrapDocumentContentKeyTarget,\n wrapDocumentContentKeyForCreate,\n} from \"./projectionContentKeys\";\nexport {\n authorizingContainerPathRefs,\n authorizingContainerPathRefsForLinkSet,\n containerPathRefs,\n currentDocumentTargets,\n deriveDocumentCreateTargets,\n deriveDocumentTargetFromProjection,\n mergeTargetEnvelopes,\n readLinkedContainerIdsFromDocumentManifest,\n verifiedDocumentWrapTargets,\n} from \"./projectionTargets\";\n\nimport type { ProjectionVerificationOptions } from \"./types\";\nimport { resolveProjectionVerifier } from \"./types\";\n\nfunction assertSortedStringsEqual(\n left: readonly string[],\n right: readonly string[],\n message: string,\n): void {\n if (\n left.length !== right.length ||\n left.some((value, index) => value !== right[index])\n ) {\n throw new Error(message);\n }\n}\n\nfunction assertAuthorizingContainerPathsMatchDocumentTargets(input: {\n targets: readonly DocumentContentKeyTarget[];\n writerProjection: DocumentWriterProjectionResponse;\n}): void {\n if (input.writerProjection.authorizingContainerPaths.length === 0) {\n throw new Error(\"Document writer projection authorization paths missing\");\n }\n\n const targetKeys = new Set(input.targets.map(targetKey));\n for (const [\n index,\n projection,\n ] of input.writerProjection.authorizingContainerPaths.entries()) {\n let projectionTarget: DocumentContentKeyTarget;\n try {\n projectionTarget = deriveDocumentTargetFromProjection(projection);\n } catch (error) {\n throw new Error(\n `Document writer projection authorization path[${index}] is invalid: ${errorMessage(error)}`,\n );\n }\n\n if (targetKeys.has(targetKey(projectionTarget))) {\n continue;\n }\n\n // Bind server-supplied KEK paths to committed document targets before\n // using any unwrapped path KEK for document content-key material.\n throw new Error(\n `Document writer projection authorization path[${index}] is not a document target`,\n );\n }\n}\n\nfunction assertDocumentTargetsCoverLinkedContainers(\n targets: readonly DocumentContentKeyTarget[],\n writerProjection: DocumentWriterProjectionResponse,\n): void {\n // One target per linked container: a second epoch for the same container\n // would let a re-wrap land on a KEK a revoked member still holds.\n if (\n new Set(targets.map((target) => target.containerId)).size !== targets.length\n ) {\n throw new Error(\n \"Document writer projection targets name a linked container more than once\",\n );\n }\n assertSortedStringsEqual(\n uniqueSortedStrings(targets.map((target) => target.containerId)),\n readLinkedContainerIdsFromDocumentManifest(writerProjection),\n \"Document writer projection targets do not match linked containers\",\n );\n assertSortedStringsEqual(\n uniqueSortedStrings(\n writerProjection.documentKekTargets.linkedContainerManifestHashes,\n ),\n uniqueSortedStrings(targets.map((target) => target.containerManifestHash)),\n \"Document writer projection target manifest summary mismatch\",\n );\n assertSortedStringsEqual(\n uniqueSortedStrings(\n writerProjection.documentKekTargets.linkedContainerKeyEpochIds,\n ),\n uniqueSortedStrings(targets.map((target) => target.containerKeyEpochId)),\n \"Document writer projection target KEK summary mismatch\",\n );\n}\n\nasync function assertProjectionContentKeyBundleConsistent(\n writerProjection: DocumentWriterProjectionResponse,\n staleContentKeyBundle: boolean,\n): Promise<void> {\n const { manifestHash } = writerProjection.documentManifest;\n if (writerProjection.contentKeyBundle.linkSetManifestHash !== manifestHash) {\n // A stale bundle may lag the link-set head, but it must still descend\n // from this document's manifest chain.\n if (\n !staleContentKeyBundle ||\n !writerProjection.documentManifestHistory.some(\n (bundle) =>\n bundle.manifestHash ===\n writerProjection.contentKeyBundle.linkSetManifestHash,\n )\n ) {\n throw new Error(\"Document writer projection link manifest mismatch\");\n }\n }\n\n if (!staleContentKeyBundle) {\n if (\n writerProjection.documentKekTargets.documentKeyTargetHash !==\n writerProjection.contentKeyBundle.targetHash\n ) {\n throw new Error(\"Document writer projection target hash mismatch\");\n }\n return;\n }\n\n // The stale bundle cannot match the current targets; pin it to its own\n // canonical hash instead so a tampered envelope set still fails closed.\n const staleBundleTargetHash = await computeDocumentContentKeyTargetHash(\n sortDocumentTargets(\n writerProjection.contentKeyBundle.targets.map(targetEnvelopeReference),\n ),\n );\n if (staleBundleTargetHash !== writerProjection.contentKeyBundle.targetHash) {\n throw new Error(\n \"Document writer projection stale bundle target hash is not canonical\",\n );\n }\n}\n\nasync function assertDocumentWriterProjectionConsistentInternal(\n writerProjection: DocumentWriterProjectionResponse,\n input: ProjectionVerificationOptions & {\n /**\n * Accept a projection whose content-key bundle is marked stale (wrapped\n * to superseded KEK targets after e.g. a revoke rotation). Document sync\n * opts in to heal the bundle. Attachment reads opt in because their DEK\n * is independent and opens through verified retained container KEKs.\n */\n allowStaleContentKeyBundle?: boolean | undefined;\n execSql?: ExecSql | undefined;\n persistVerificationCheckpoints?: boolean | undefined;\n onVerifiedAuthorization?:\n | ((authorization: DocumentWriterProjectionAuthorization) => void)\n | undefined;\n principalPolicyCache?: PrincipalPolicyCache | undefined;\n stillCurrent?: (() => boolean) | undefined;\n verifiedByHash?: Map<string, VerifiedContainerAccessManifest> | undefined;\n },\n): Promise<DocumentContentKeyTarget[]> {\n const resolveProjectionUserKey = resolveProjectionVerifier(\n input,\n \"Document writer projection\",\n );\n if (\n input.trustedLocalProjection !== true &&\n resolveProjectionUserKey !== null\n ) {\n const authorization = await verifyDocumentWriterProjectionAuthorization({\n execSql: input.execSql,\n persistVerificationCheckpoints: input.persistVerificationCheckpoints,\n principalPolicyCache: input.principalPolicyCache,\n projection: writerProjection,\n resolveUserKey: resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n verifiedByHash: input.verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n input.onVerifiedAuthorization?.(authorization);\n }\n\n const staleContentKeyBundle = writerProjection.contentKeyBundleStale === true;\n if (staleContentKeyBundle && input.allowStaleContentKeyBundle !== true) {\n throw new Error(\"Document writer projection content-key bundle is stale\");\n }\n\n const manifestIdentity = await assertDocumentManifestBundleConsistent({\n bundle: writerProjection.documentManifest,\n label: \"Document writer projection manifest\",\n });\n const { documentId } = manifestIdentity;\n if (\n writerProjection.documentId !== documentId ||\n writerProjection.documentKekTargets.documentId !== documentId ||\n writerProjection.contentKeyBundle.documentId !== documentId\n ) {\n throw new Error(\"Document writer projection document id mismatch\");\n }\n if (\n writerProjection.documentKekTargets.linkSetManifestHash !==\n writerProjection.documentManifest.manifestHash\n ) {\n throw new Error(\"Document writer projection link manifest mismatch\");\n }\n await assertProjectionContentKeyBundleConsistent(\n writerProjection,\n staleContentKeyBundle,\n );\n\n const targets = staleContentKeyBundle\n ? normalizeDocumentKekTargetResponse(writerProjection.documentKekTargets)\n : currentDocumentTargets(writerProjection);\n const canonicalTargetHash =\n await computeDocumentContentKeyTargetHash(targets);\n if (\n canonicalTargetHash !==\n writerProjection.documentKekTargets.documentKeyTargetHash\n ) {\n throw new Error(\"Document writer projection target hash is not canonical\");\n }\n\n assertDocumentTargetsCoverLinkedContainers(targets, writerProjection);\n assertAuthorizingContainerPathsMatchDocumentTargets({\n targets,\n writerProjection,\n });\n\n return targets;\n}\n\nexport async function assertDocumentWriterProjectionConsistent(\n ...input: Parameters<typeof assertDocumentWriterProjectionConsistentInternal>\n): ReturnType<typeof assertDocumentWriterProjectionConsistentInternal> {\n try {\n return await assertDocumentWriterProjectionConsistentInternal(...input);\n } catch (error) {\n throwKeyingVerificationShapeFailure(error);\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ContentKeyEnvelopeKind, type VerifiedContainerAccessManifest } from "../../../internal/crypto/index.js";
|
|
2
2
|
import type { DocumentContentKeyTargetEnvelope } from "../../../internal/validators/request/index.js";
|
|
3
3
|
import type { ContainerWriterProjectionResponse, DocumentContentKeyBundleResponse, DocumentWriterProjectionResponse } from "../../../internal/validators/response/index.js";
|
|
4
|
-
import type { PrincipalPolicyCache } from "../../keyingProjectionVerification.js";
|
|
4
|
+
import type { PrincipalPolicyCache } from "../../keyingProjectionVerification/index.js";
|
|
5
5
|
import type { ExecSql } from "../../sqlite/sqlSchema.js";
|
|
6
6
|
import type { ProjectionVerificationOptions } from "./types.js";
|
|
7
7
|
export declare function wrapDocumentContentKeyForCreate(input: {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { readRecordNullableString, readRecordPositiveInteger, readRecordString, } from "../../recordReaders.js";
|
|
1
|
+
export { readRecordNullableString, readRecordPositiveInteger, readRecordString, } from "../../shared/recordReaders.js";
|
|
2
2
|
import { CONTENT_RECORD_ENCRYPTION_SUITE, compareCanonicalStrings, } from "../../../internal/crypto/index.js";
|
|
3
3
|
import { isPlainObject as isPlainRecord } from "../../../internal/validators/isPlainObject.js";
|
|
4
|
-
import { readCanonicalRecord } from "../../
|
|
5
|
-
import { readRecordInteger, readRecordPositiveInteger, readRecordString, readRecordValue, readStringArray, } from "../../recordReaders.js";
|
|
4
|
+
import { readCanonicalRecord } from "../../keying/canonicalJson.js";
|
|
5
|
+
import { readRecordInteger, readRecordPositiveInteger, readRecordString, readRecordValue, readStringArray, } from "../../shared/recordReaders.js";
|
|
6
6
|
export { assertDocumentManifestBundleConsistent, serializeCanonical, } from "./manifestBundleReaders.js";
|
|
7
7
|
function isContentObjectKind(value) {
|
|
8
8
|
return value === "blob" || value === "document";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readers.js","sourceRoot":"","sources":["readers.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n readRecordNullableString,\n readRecordPositiveInteger,\n readRecordString,\n} from \"../../recordReaders\";\n\nimport {\n CONTENT_RECORD_ENCRYPTION_SUITE,\n type ContainerKeyWrap,\n compareCanonicalStrings,\n type DocumentContentKeyTarget,\n type WriteHeader,\n} from \"@tearleads/crypto\";\nimport { isPlainObject as isPlainRecord } from \"@tearleads/validators/isPlainObject\";\nimport type {\n ContainerWriterProjectionResponse,\n DocumentCreateResponse,\n DocumentSyncResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalRecord } from \"../../keyingCanonicalJson\";\nimport {\n readRecordInteger,\n readRecordPositiveInteger,\n readRecordString,\n readRecordValue,\n readStringArray,\n} from \"../../recordReaders\";\n\nexport {\n assertDocumentManifestBundleConsistent,\n serializeCanonical,\n} from \"./manifestBundleReaders\";\n\nfunction isContentObjectKind(\n value: unknown,\n): value is WriteHeader[\"objectKind\"] {\n return value === \"blob\" || value === \"document\";\n}\n\nexport function readWriteHeader(value: unknown, label: string): WriteHeader {\n const record = readCanonicalRecord(value, label);\n const objectKind = readRecordValue(record, \"objectKind\");\n if (!isContentObjectKind(objectKind)) {\n throw new Error(`${label}.objectKind is invalid`);\n }\n if (readRecordInteger(record, \"version\", label) !== 1) {\n throw new Error(`${label}.version must be 1`);\n }\n const encryptionSuite = readRecordValue(record, \"encryptionSuite\");\n if (encryptionSuite !== CONTENT_RECORD_ENCRYPTION_SUITE) {\n throw new Error(`${label}.encryptionSuite is invalid`);\n }\n\n return {\n version: 1,\n dependencyManifestHashes: readStringArray(\n readRecordValue(record, \"dependencyManifestHashes\"),\n `${label}.dependencyManifestHashes`,\n ),\n organizationId: readRecordString(record, \"organizationId\", label),\n objectKind,\n objectId: readRecordString(record, \"objectId\", label),\n accessManifestHash: readRecordString(record, \"accessManifestHash\", label),\n contentKeyEpoch: readRecordPositiveInteger(\n record,\n \"contentKeyEpoch\",\n label,\n ),\n targetHash: readRecordString(record, \"targetHash\", label),\n encryptionSuite,\n contentRecordId: readRecordString(record, \"contentRecordId\", label),\n nonceDomainHash: readRecordString(record, \"nonceDomainHash\", label),\n metadataHash: readRecordString(record, \"metadataHash\", label),\n ciphertextHash: readRecordString(record, \"ciphertextHash\", label),\n writerUserId: readRecordString(record, \"writerUserId\", label),\n writerDeviceId: readRecordString(record, \"writerDeviceId\", label),\n writerKeyFingerprint: readRecordString(\n record,\n \"writerKeyFingerprint\",\n label,\n ),\n signedAt: readRecordString(record, \"signedAt\", label),\n signature: readRecordString(record, \"signature\", label),\n };\n}\n\nexport function readManifestContainerId(\n bundle: ContainerWriterProjectionResponse[\"path\"][number],\n): string | null {\n const containerId = isPlainRecord(bundle.state)\n ? Reflect.get(bundle.state, \"containerId\")\n : undefined;\n\n return typeof containerId === \"string\" && containerId.length > 0\n ? containerId\n : null;\n}\n\nexport function targetKey(target: DocumentContentKeyTarget): string {\n return [\n target.containerId,\n target.containerManifestHash,\n target.containerKeyEpochId,\n String(target.containerKeyEpoch),\n ].join(\":\");\n}\n\nexport function sortTargets<T>(\n targets: readonly T[],\n keyOf: (target: T) => string,\n): T[] {\n return [...targets].sort((left, right) =>\n compareCanonicalStrings(keyOf(left), keyOf(right)),\n );\n}\n\nexport function sortDocumentTargets<T extends DocumentContentKeyTarget>(\n targets: readonly T[],\n): T[] {\n return sortTargets(targets, targetKey);\n}\n\nexport function describeDocumentTargetKek(\n target: DocumentContentKeyTarget,\n): string {\n return `container ${target.containerId} epoch ${target.containerKeyEpochId}`;\n}\n\nexport function uniqueSortedStrings(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nexport function asWebCryptoBytes(bytes: Uint8Array): Uint8Array<ArrayBuffer> {\n const buffer = bytes.buffer;\n if (!(buffer instanceof ArrayBuffer)) {\n throw new Error(\"Document byte material must be ArrayBuffer-backed\");\n }\n return new Uint8Array(buffer, bytes.byteOffset, bytes.byteLength);\n}\n\nexport function assertOnlyRecordKeys(\n record: Record<string, unknown>,\n allowedKeys: ReadonlySet<string>,\n label: string,\n): void {\n const unexpectedKeys = Object.keys(record).filter(\n (key) => !allowedKeys.has(key),\n );\n if (unexpectedKeys.length === 0) return;\n const named = unexpectedKeys\n .slice(0, 3)\n .map((key) => JSON.stringify(key.slice(0, 32)))\n .join(\",\");\n const remaining = unexpectedKeys.length - 3;\n throw new Error(\n `${label} has unexpected keys: ${named}${remaining > 0 ? ` and ${remaining} more` : \"\"}`,\n );\n}\n\nexport function normalizeContainerKeyWrap(value: unknown): ContainerKeyWrap {\n if (!isPlainRecord(value)) {\n throw new Error(\"Container writer projection KEK wrap is invalid\");\n }\n\n const recipientKind = readRecordString(\n value,\n \"recipientKind\",\n \"container KEK wrap\",\n );\n if (\n recipientKind !== \"user\" &&\n recipientKind !== \"group\" &&\n recipientKind !== \"container\"\n ) {\n throw new Error(\n \"Container writer projection KEK wrap recipient is invalid\",\n );\n }\n\n return {\n containerKeyEpochId: readRecordString(\n value,\n \"containerKeyEpochId\",\n \"container KEK wrap\",\n ),\n recipientKind,\n recipientId: readRecordString(value, \"recipientId\", \"container KEK wrap\"),\n recipientKeyEpochId: readRecordString(\n value,\n \"recipientKeyEpochId\",\n \"container KEK wrap\",\n ),\n recipientKeyFingerprint: readRecordString(\n value,\n \"recipientKeyFingerprint\",\n \"container KEK wrap\",\n ),\n kemCipherText: readRecordString(\n value,\n \"kemCipherText\",\n \"container KEK wrap\",\n ),\n wrappedKey: readRecordString(value, \"wrappedKey\", \"container KEK wrap\"),\n wrapManifestHash: readRecordString(\n value,\n \"wrapManifestHash\",\n \"container KEK wrap\",\n ),\n };\n}\n\nexport function assertEqualBytes(\n left: Uint8Array,\n right: Uint8Array,\n message: string,\n): void {\n let mismatch = left.byteLength ^ right.byteLength;\n const length = Math.max(left.byteLength, right.byteLength);\n for (let index = 0; index < length; index += 1) {\n mismatch |= (left[index] ?? 0) ^ (right[index] ?? 0);\n }\n\n if (mismatch !== 0) {\n throw new Error(message);\n }\n}\n\nfunction readDocumentTarget(\n value: Record<string, unknown>,\n label: string,\n): DocumentContentKeyTarget {\n return {\n containerId: readRecordString(value, \"containerId\", label),\n containerManifestHash: readRecordString(\n value,\n \"containerManifestHash\",\n label,\n ),\n containerKeyEpochId: readRecordString(value, \"containerKeyEpochId\", label),\n containerKeyEpoch: readRecordPositiveInteger(\n value,\n \"containerKeyEpoch\",\n label,\n ),\n };\n}\n\nexport function normalizeDocumentKekTargetResponse(\n targets: DocumentSyncResponse[\"documentKekTargets\"],\n): DocumentContentKeyTarget[] {\n return sortDocumentTargets(\n targets.targets.map((target, index) => {\n if (!isPlainRecord(target)) {\n throw new Error(`Document KEK target[${index}] is invalid`);\n }\n return readDocumentTarget(target, `Document KEK target[${index}]`);\n }),\n );\n}\n\nexport function targetEnvelopeReference(\n envelope: DocumentCreateResponse[\"contentKeyBundle\"][\"targets\"][number],\n): DocumentContentKeyTarget {\n return {\n containerId: envelope.containerId,\n containerManifestHash: envelope.containerManifestHash,\n containerKeyEpochId: envelope.containerKeyEpochId,\n containerKeyEpoch: envelope.containerKeyEpoch,\n };\n}\n\nfunction serializeState(value: unknown): string {\n return JSON.stringify(value);\n}\n\nexport function serializedPersistedDocumentState(input: {\n contentKeyBundle: unknown;\n documentId: string;\n documentKekTargets: unknown;\n documentManifestBundle: unknown;\n}): {\n contentKeyBundle: string;\n documentId: string;\n documentKekTargets: string;\n documentManifestBundle: string;\n} {\n return {\n documentId: input.documentId,\n contentKeyBundle: serializeState(input.contentKeyBundle),\n documentKekTargets: serializeState(input.documentKekTargets),\n documentManifestBundle: serializeState(input.documentManifestBundle),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"readers.js","sourceRoot":"","sources":["readers.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n readRecordNullableString,\n readRecordPositiveInteger,\n readRecordString,\n} from \"../../shared/recordReaders\";\n\nimport {\n CONTENT_RECORD_ENCRYPTION_SUITE,\n type ContainerKeyWrap,\n compareCanonicalStrings,\n type DocumentContentKeyTarget,\n type WriteHeader,\n} from \"@tearleads/crypto\";\nimport { isPlainObject as isPlainRecord } from \"@tearleads/validators/isPlainObject\";\nimport type {\n ContainerWriterProjectionResponse,\n DocumentCreateResponse,\n DocumentSyncResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalRecord } from \"../../keying/canonicalJson\";\nimport {\n readRecordInteger,\n readRecordPositiveInteger,\n readRecordString,\n readRecordValue,\n readStringArray,\n} from \"../../shared/recordReaders\";\n\nexport {\n assertDocumentManifestBundleConsistent,\n serializeCanonical,\n} from \"./manifestBundleReaders\";\n\nfunction isContentObjectKind(\n value: unknown,\n): value is WriteHeader[\"objectKind\"] {\n return value === \"blob\" || value === \"document\";\n}\n\nexport function readWriteHeader(value: unknown, label: string): WriteHeader {\n const record = readCanonicalRecord(value, label);\n const objectKind = readRecordValue(record, \"objectKind\");\n if (!isContentObjectKind(objectKind)) {\n throw new Error(`${label}.objectKind is invalid`);\n }\n if (readRecordInteger(record, \"version\", label) !== 1) {\n throw new Error(`${label}.version must be 1`);\n }\n const encryptionSuite = readRecordValue(record, \"encryptionSuite\");\n if (encryptionSuite !== CONTENT_RECORD_ENCRYPTION_SUITE) {\n throw new Error(`${label}.encryptionSuite is invalid`);\n }\n\n return {\n version: 1,\n dependencyManifestHashes: readStringArray(\n readRecordValue(record, \"dependencyManifestHashes\"),\n `${label}.dependencyManifestHashes`,\n ),\n organizationId: readRecordString(record, \"organizationId\", label),\n objectKind,\n objectId: readRecordString(record, \"objectId\", label),\n accessManifestHash: readRecordString(record, \"accessManifestHash\", label),\n contentKeyEpoch: readRecordPositiveInteger(\n record,\n \"contentKeyEpoch\",\n label,\n ),\n targetHash: readRecordString(record, \"targetHash\", label),\n encryptionSuite,\n contentRecordId: readRecordString(record, \"contentRecordId\", label),\n nonceDomainHash: readRecordString(record, \"nonceDomainHash\", label),\n metadataHash: readRecordString(record, \"metadataHash\", label),\n ciphertextHash: readRecordString(record, \"ciphertextHash\", label),\n writerUserId: readRecordString(record, \"writerUserId\", label),\n writerDeviceId: readRecordString(record, \"writerDeviceId\", label),\n writerKeyFingerprint: readRecordString(\n record,\n \"writerKeyFingerprint\",\n label,\n ),\n signedAt: readRecordString(record, \"signedAt\", label),\n signature: readRecordString(record, \"signature\", label),\n };\n}\n\nexport function readManifestContainerId(\n bundle: ContainerWriterProjectionResponse[\"path\"][number],\n): string | null {\n const containerId = isPlainRecord(bundle.state)\n ? Reflect.get(bundle.state, \"containerId\")\n : undefined;\n\n return typeof containerId === \"string\" && containerId.length > 0\n ? containerId\n : null;\n}\n\nexport function targetKey(target: DocumentContentKeyTarget): string {\n return [\n target.containerId,\n target.containerManifestHash,\n target.containerKeyEpochId,\n String(target.containerKeyEpoch),\n ].join(\":\");\n}\n\nexport function sortTargets<T>(\n targets: readonly T[],\n keyOf: (target: T) => string,\n): T[] {\n return [...targets].sort((left, right) =>\n compareCanonicalStrings(keyOf(left), keyOf(right)),\n );\n}\n\nexport function sortDocumentTargets<T extends DocumentContentKeyTarget>(\n targets: readonly T[],\n): T[] {\n return sortTargets(targets, targetKey);\n}\n\nexport function describeDocumentTargetKek(\n target: DocumentContentKeyTarget,\n): string {\n return `container ${target.containerId} epoch ${target.containerKeyEpochId}`;\n}\n\nexport function uniqueSortedStrings(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nexport function asWebCryptoBytes(bytes: Uint8Array): Uint8Array<ArrayBuffer> {\n const buffer = bytes.buffer;\n if (!(buffer instanceof ArrayBuffer)) {\n throw new Error(\"Document byte material must be ArrayBuffer-backed\");\n }\n return new Uint8Array(buffer, bytes.byteOffset, bytes.byteLength);\n}\n\nexport function assertOnlyRecordKeys(\n record: Record<string, unknown>,\n allowedKeys: ReadonlySet<string>,\n label: string,\n): void {\n const unexpectedKeys = Object.keys(record).filter(\n (key) => !allowedKeys.has(key),\n );\n if (unexpectedKeys.length === 0) return;\n const named = unexpectedKeys\n .slice(0, 3)\n .map((key) => JSON.stringify(key.slice(0, 32)))\n .join(\",\");\n const remaining = unexpectedKeys.length - 3;\n throw new Error(\n `${label} has unexpected keys: ${named}${remaining > 0 ? ` and ${remaining} more` : \"\"}`,\n );\n}\n\nexport function normalizeContainerKeyWrap(value: unknown): ContainerKeyWrap {\n if (!isPlainRecord(value)) {\n throw new Error(\"Container writer projection KEK wrap is invalid\");\n }\n\n const recipientKind = readRecordString(\n value,\n \"recipientKind\",\n \"container KEK wrap\",\n );\n if (\n recipientKind !== \"user\" &&\n recipientKind !== \"group\" &&\n recipientKind !== \"container\"\n ) {\n throw new Error(\n \"Container writer projection KEK wrap recipient is invalid\",\n );\n }\n\n return {\n containerKeyEpochId: readRecordString(\n value,\n \"containerKeyEpochId\",\n \"container KEK wrap\",\n ),\n recipientKind,\n recipientId: readRecordString(value, \"recipientId\", \"container KEK wrap\"),\n recipientKeyEpochId: readRecordString(\n value,\n \"recipientKeyEpochId\",\n \"container KEK wrap\",\n ),\n recipientKeyFingerprint: readRecordString(\n value,\n \"recipientKeyFingerprint\",\n \"container KEK wrap\",\n ),\n kemCipherText: readRecordString(\n value,\n \"kemCipherText\",\n \"container KEK wrap\",\n ),\n wrappedKey: readRecordString(value, \"wrappedKey\", \"container KEK wrap\"),\n wrapManifestHash: readRecordString(\n value,\n \"wrapManifestHash\",\n \"container KEK wrap\",\n ),\n };\n}\n\nexport function assertEqualBytes(\n left: Uint8Array,\n right: Uint8Array,\n message: string,\n): void {\n let mismatch = left.byteLength ^ right.byteLength;\n const length = Math.max(left.byteLength, right.byteLength);\n for (let index = 0; index < length; index += 1) {\n mismatch |= (left[index] ?? 0) ^ (right[index] ?? 0);\n }\n\n if (mismatch !== 0) {\n throw new Error(message);\n }\n}\n\nfunction readDocumentTarget(\n value: Record<string, unknown>,\n label: string,\n): DocumentContentKeyTarget {\n return {\n containerId: readRecordString(value, \"containerId\", label),\n containerManifestHash: readRecordString(\n value,\n \"containerManifestHash\",\n label,\n ),\n containerKeyEpochId: readRecordString(value, \"containerKeyEpochId\", label),\n containerKeyEpoch: readRecordPositiveInteger(\n value,\n \"containerKeyEpoch\",\n label,\n ),\n };\n}\n\nexport function normalizeDocumentKekTargetResponse(\n targets: DocumentSyncResponse[\"documentKekTargets\"],\n): DocumentContentKeyTarget[] {\n return sortDocumentTargets(\n targets.targets.map((target, index) => {\n if (!isPlainRecord(target)) {\n throw new Error(`Document KEK target[${index}] is invalid`);\n }\n return readDocumentTarget(target, `Document KEK target[${index}]`);\n }),\n );\n}\n\nexport function targetEnvelopeReference(\n envelope: DocumentCreateResponse[\"contentKeyBundle\"][\"targets\"][number],\n): DocumentContentKeyTarget {\n return {\n containerId: envelope.containerId,\n containerManifestHash: envelope.containerManifestHash,\n containerKeyEpochId: envelope.containerKeyEpochId,\n containerKeyEpoch: envelope.containerKeyEpoch,\n };\n}\n\nfunction serializeState(value: unknown): string {\n return JSON.stringify(value);\n}\n\nexport function serializedPersistedDocumentState(input: {\n contentKeyBundle: unknown;\n documentId: string;\n documentKekTargets: unknown;\n documentManifestBundle: unknown;\n}): {\n contentKeyBundle: string;\n documentId: string;\n documentKekTargets: string;\n documentManifestBundle: string;\n} {\n return {\n documentId: input.documentId,\n contentKeyBundle: serializeState(input.contentKeyBundle),\n documentKekTargets: serializeState(input.documentKekTargets),\n documentManifestBundle: serializeState(input.documentManifestBundle),\n };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deriveStableUuidV4Shaped } from "../../stableUuid.js";
|
|
1
|
+
import { deriveStableUuidV4Shaped } from "../../keying/stableUuid.js";
|
|
2
2
|
// A namespace distinct from every other stable-id namespace (e.g. the system
|
|
3
3
|
// container namespace) so a document id derived from a local id never collides
|
|
4
4
|
// with an id derived from the same string in another domain.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stableDocumentId.js","sourceRoot":"","sources":["stableDocumentId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"stableDocumentId.js","sourceRoot":"","sources":["stableDocumentId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,6EAA6E;AAC7E,+EAA+E;AAC/E,6DAA6D;AAC7D,MAAM,kCAAkC,GAAG,IAAI,UAAU,CAAC;IACxD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC5E,IAAI,EAAE,IAAI,EAAE,IAAI;CACjB,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,OAAO,wBAAwB,CAAC,kCAAkC,EAAE,OAAO,CAAC,CAAC;AAC/E,CAAC","sourcesContent":["import { deriveStableUuidV4Shaped } from \"../../keying/stableUuid\";\n\n// A namespace distinct from every other stable-id namespace (e.g. the system\n// container namespace) so a document id derived from a local id never collides\n// with an id derived from the same string in another domain.\nconst STABLE_DOCUMENT_ID_NAMESPACE_BYTES = new Uint8Array([\n 0x7a, 0x1c, 0x94, 0xe0, 0x5b, 0x63, 0x4e, 0x11, 0x9f, 0x2d, 0xa8, 0x74, 0x36,\n 0xc1, 0x0e, 0x52,\n]);\n\n/**\n * Derives the remote document id for a local document from its stable `localId`.\n *\n * Deriving (rather than generating a fresh `crypto.randomUUID()` per attempt)\n * makes the first remote create idempotent: if the server commits the create but\n * the response is lost, the retry re-sends the same id and the server reports a\n * conflict the client can adopt, instead of creating a second orphan document.\n */\nexport function deriveStableDocumentId(localId: string): Promise<string> {\n return deriveStableUuidV4Shaped(STABLE_DOCUMENT_ID_NAMESPACE_BYTES, localId);\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import type { AccessEvent, AccessManifest, DocumentContentKeyTarget, DocumentLin
|
|
|
3
3
|
import type { ContainerManifestRef, DocumentContentKeyTargetEnvelope, DocumentCreateRequest, DocumentLinkSetMutationRequest, DocumentOutgoingUpdate, DocumentSyncRequest } from "../../../internal/validators/request/index.js";
|
|
4
4
|
import type { ContainerWriterProjectionResponse, DocumentCreateResponse, DocumentLinkSetMutationResponse, DocumentPurgeProofResponse, DocumentSyncResponse, DocumentWriterProjectionResponse, ListDocumentAttachmentsResponse } from "../../../internal/validators/response/index.js";
|
|
5
5
|
import type { ContainerMutationAuthor, ContainerRekeyApi } from "../../containers/shared/types.js";
|
|
6
|
-
import type { ProjectionUserKeyResolver, ReferencedPrincipalPolicyWarmer, DocumentWriterProjectionAuthorization as WriterAuthorization } from "../../keyingProjectionVerification.js";
|
|
6
|
+
import type { ProjectionUserKeyResolver, ReferencedPrincipalPolicyWarmer, DocumentWriterProjectionAuthorization as WriterAuthorization } from "../../keyingProjectionVerification/index.js";
|
|
7
7
|
import type { DocumentRecord } from "../../sqlite/documentPersistence.js";
|
|
8
8
|
import type { ExecSql } from "../../sqlite/sqlSchema.js";
|
|
9
9
|
import type { DocumentSyncSubmitFailure } from "./syncSubmitFailure.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { requireProjectionUserKeyResolver } from "../../keyingProjectionVerification.js";
|
|
1
|
+
import { requireProjectionUserKeyResolver } from "../../keyingProjectionVerification/index.js";
|
|
2
2
|
export const DOCUMENT_ENCRYPTED_LORO_UPDATE_FORMAT = "tearleads.document.loro-update";
|
|
3
3
|
export const DOCUMENT_CONTENT_RECORD_KEY_INFO_DOMAIN = "tearleads.document.content-record-key-info";
|
|
4
4
|
export const DOCUMENT_CONTENT_RECORD_PLAINTEXT_HASH_KEY_INFO_DOMAIN = "tearleads.document.content-record-plaintext-hash-key-info";
|
|
@@ -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";
|