@tearleads/client-sdk 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/Tearleads.d.ts +2 -0
- package/client/Tearleads.js +1 -0
- package/client/Tearleads.js.map +1 -1
- package/client/containerContents.js +2 -1
- package/client/containerContents.js.map +1 -1
- package/client/index.d.ts +1 -1
- package/client/index.js.map +1 -1
- package/client/organizations/index.d.ts +4 -42
- package/client/organizations/index.js +13 -0
- package/client/organizations/index.js.map +1 -1
- package/client/organizations/organizationGroupNameHydration.js +8 -1
- package/client/organizations/organizationGroupNameHydration.js.map +1 -1
- package/client/organizations/organizationsTypes.d.ts +47 -0
- package/client/organizations/organizationsTypes.js +2 -0
- package/client/organizations/organizationsTypes.js.map +1 -0
- package/client/organizations/principalMutationRecovery.d.ts +16 -0
- package/client/organizations/principalMutationRecovery.js +23 -0
- package/client/organizations/principalMutationRecovery.js.map +1 -0
- package/client/organizations/principalMutationScope.js +7 -2
- package/client/organizations/principalMutationScope.js.map +1 -1
- package/client/principalMutationApi.d.ts +24 -0
- package/client/principalMutationApi.js +108 -0
- package/client/principalMutationApi.js.map +1 -0
- package/client/principalMutationDeadline.js +23 -0
- package/client/principalMutationDeadline.js.map +1 -0
- package/client/workflowRuntime.d.ts +3 -1
- package/client/workflowRuntime.js +44 -5
- package/client/workflowRuntime.js.map +1 -1
- package/data/documents/blob/shared/types.d.ts +4 -0
- package/data/documents/blob/shared/types.js.map +1 -1
- package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js +2 -0
- package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js.map +1 -1
- package/data/keyingProjectionVerification/checkpointContext.d.ts +2 -1
- package/data/keyingProjectionVerification/checkpointContext.js +22 -0
- package/data/keyingProjectionVerification/checkpointContext.js.map +1 -1
- package/data/keyingProjectionVerification/containerDestinationVerification.js +11 -1
- package/data/keyingProjectionVerification/containerDestinationVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerManifestVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerPathVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerProjectionVerification.d.ts +3 -2
- package/data/keyingProjectionVerification/containerProjectionVerification.js +10 -11
- package/data/keyingProjectionVerification/containerProjectionVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentManifestPolicies.js.map +1 -1
- package/data/keyingProjectionVerification/documentManifestVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentProjectionVerification.d.ts +2 -3
- package/data/keyingProjectionVerification/documentProjectionVerification.js +4 -0
- package/data/keyingProjectionVerification/documentProjectionVerification.js.map +1 -1
- package/data/keyingProjectionVerification/mergeProjectionPolicyEvidence.js +14 -12
- package/data/keyingProjectionVerification/mergeProjectionPolicyEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/organizationFounderBinding.js.map +1 -1
- package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js +33 -6
- package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/projectionLifetimes.js +13 -0
- package/data/keyingProjectionVerification/projectionLifetimes.js.map +1 -0
- package/data/keyingProjectionVerification/projectionPolicyEvidence.js +19 -66
- package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +13 -2
- package/data/keyingProjectionVerification/types.js +15 -0
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/keyingCheckpointAdvancePersistence.js +4 -1
- package/data/persistence/keyingCheckpointAdvancePersistence.js.map +1 -1
- package/data/persistence/organizationFounderPersistence.js +2 -2
- package/data/persistence/organizationFounderPersistence.js.map +1 -1
- package/data/persistence/principalAuthorizationCheckpoints.js +29 -0
- package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -0
- package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +27 -0
- package/data/persistence/principalCurrentAcknowledgementPersistence.js +109 -0
- package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -0
- package/data/persistence/principalGrantRetirementPersistence.d.ts +3 -3
- package/data/persistence/principalGrantRetirementPersistence.js +4 -1
- package/data/persistence/principalGrantRetirementPersistence.js.map +1 -1
- package/data/persistence/principalHistoryEvidencePersistence.d.ts +30 -0
- package/data/persistence/principalHistoryPrefixPersistence.d.ts +24 -0
- package/data/persistence/principalHistoryPrefixPersistence.js +6 -2
- package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
- package/data/persistence/principalHistoryStagePersistence.d.ts +21 -0
- package/data/persistence/principalKeyEnvelopeCandidates.js +12 -1
- package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
- package/data/persistence/principalMutationJournalPersistence.d.ts +19 -0
- package/data/persistence/principalMutationJournalPersistence.js +53 -0
- package/data/persistence/principalMutationJournalPersistence.js.map +1 -0
- package/data/persistence/verifiedPrincipalPolicyBundle.js +7 -51
- package/data/persistence/verifiedPrincipalPolicyBundle.js.map +1 -1
- package/data/persistence/verifiedPrincipalPolicyCurrent.js +56 -0
- package/data/persistence/verifiedPrincipalPolicyCurrent.js.map +1 -0
- package/data/principals/principalHistoryRuntime.js +12 -0
- package/data/principals/principalHistoryRuntime.js.map +1 -0
- package/data/principals/principalHistoryStageProtection.js +2 -12
- package/data/principals/principalHistoryStageProtection.js.map +1 -1
- package/data/principals/principalMutationJournal.d.ts +26 -0
- package/data/principals/principalMutationJournal.js +90 -0
- package/data/principals/principalMutationJournal.js.map +1 -0
- package/data/principals/principalMutationJournalRecord.d.ts +8 -0
- package/data/principals/principalMutationJournalRecord.js +25 -0
- package/data/principals/principalMutationJournalRecord.js.map +1 -0
- package/data/principals/principalPolicyEvidence.d.ts +2 -2
- package/data/principals/principalPolicyEvidence.js.map +1 -1
- package/data/sqlite/principalHistoryEvidenceSchema.d.ts +308 -0
- package/data/sqlite/principalHistoryStageSchema.d.ts +119 -0
- package/data/sqlite/principalHistoryStageSchema.js +3 -0
- package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
- package/data/sqlite/principalMutationJournalSchema.d.ts +85 -0
- package/data/sqlite/principalMutationJournalSchema.js +13 -0
- package/data/sqlite/principalMutationJournalSchema.js.map +1 -0
- package/data/sqlite/schema.d.ts +83 -0
- package/data/sqlite/schema.js +3 -0
- package/data/sqlite/schema.js.map +1 -1
- package/index.d.ts +5 -5
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/internal/api-client/ApiCache.d.ts +54 -0
- package/internal/api-client/ApiClient.d.ts +255 -309
- package/internal/api-client/ApiClient.js +15 -6
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/index.d.ts +1 -0
- package/internal/api-client/index.js.map +1 -1
- package/internal/api-client/principalHistoryDeadline.js +20 -0
- package/internal/api-client/principalHistoryDeadline.js.map +1 -0
- package/internal/api-client/principalHistoryRequest.js +59 -22
- package/internal/api-client/principalHistoryRequest.js.map +1 -1
- package/internal/api-client/principalHistoryRequestContext.js +18 -5
- package/internal/api-client/principalHistoryRequestContext.js.map +1 -1
- package/internal/api-client/principalPolicyRequests.d.ts +799 -0
- package/internal/api-client/principalPolicyRequests.js +9 -4
- package/internal/api-client/principalPolicyRequests.js.map +1 -1
- package/internal/api-client/projectionPolicyHistoryPages.d.ts +9 -0
- package/internal/api-client/projectionPolicyHistoryPages.js +88 -0
- package/internal/api-client/projectionPolicyHistoryPages.js.map +1 -0
- package/internal/api-client/writerProjectionRequests.js +26 -0
- package/internal/api-client/writerProjectionRequests.js.map +1 -0
- package/internal/crypto/index.d.ts +1 -1
- package/internal/crypto/index.js +1 -1
- package/internal/crypto/index.js.map +1 -1
- package/internal/crypto/keying/index.d.ts +2 -0
- package/internal/crypto/keying/index.js +2 -0
- package/internal/crypto/keying/index.js.map +1 -1
- package/internal/crypto/keying/principalPolicyCurrent.d.ts +1 -1
- package/internal/crypto/keying/principalPolicyCurrent.js +3 -3
- package/internal/crypto/keying/principalPolicyCurrent.js.map +1 -1
- package/internal/crypto/keying/principalPolicyCurrentEvidence.js +16 -0
- package/internal/crypto/keying/principalPolicyCurrentEvidence.js.map +1 -0
- package/internal/crypto/keying/principalPolicyCurrentMutation.d.ts +10 -0
- package/internal/crypto/keying/principalPolicyCurrentMutation.js +51 -0
- package/internal/crypto/keying/principalPolicyCurrentMutation.js.map +1 -0
- package/internal/crypto/keying/principalPolicyCurrentSuccessor.d.ts +10 -0
- package/internal/crypto/keying/principalPolicyCurrentSuccessor.js +60 -0
- package/internal/crypto/keying/principalPolicyCurrentSuccessor.js.map +1 -0
- package/internal/crypto/keying/principalPolicyHistory.js +8 -1
- package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistoryReferences.js +1 -1
- package/internal/crypto/keying/principalPolicyHistoryReferences.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +7 -2
- package/internal/crypto/keying/principalPolicyHistoryTypes.js +6 -3
- package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
- package/internal/crypto/projectionHistorySlots.js +0 -4
- package/internal/crypto/projectionHistorySlots.js.map +1 -1
- package/internal/validators/operation/index.d.ts +1 -0
- package/internal/validators/operation/index.js +1 -0
- package/internal/validators/operation/index.js.map +1 -1
- package/internal/validators/operation/principals.d.ts +38 -16
- package/internal/validators/operation/principals.js +11 -5
- package/internal/validators/operation/principals.js.map +1 -1
- package/internal/validators/operation/projectionPolicyHistory.d.ts +512 -0
- package/internal/validators/operation/projectionPolicyHistory.js +37 -0
- package/internal/validators/operation/projectionPolicyHistory.js.map +1 -0
- package/internal/validators/operation/registry.d.ts +2 -0
- package/internal/validators/operation/registry.js +2 -0
- package/internal/validators/operation/registry.js.map +1 -1
- package/internal/validators/operation/writerProjections.d.ts +178 -1224
- package/internal/validators/operation/writerProjections.js +9 -2
- package/internal/validators/operation/writerProjections.js.map +1 -1
- package/internal/validators/response/container.d.ts +84 -612
- package/internal/validators/response/documentMutation.d.ts +84 -612
- package/internal/validators/response/index.d.ts +1 -0
- package/internal/validators/response/index.js +1 -0
- package/internal/validators/response/index.js.map +1 -1
- package/internal/validators/response/organizationBilling.d.ts +1 -0
- package/internal/validators/response/organizationBilling.js +1 -1
- package/internal/validators/response/organizationBilling.js.map +1 -1
- package/internal/validators/response/principalHistoryPreparation.js +28 -1
- package/internal/validators/response/principalHistoryPreparation.js.map +1 -1
- package/internal/validators/response/principalPolicySnapshotPage.d.ts +388 -0
- package/internal/validators/response/principalPolicySnapshotPage.js +24 -0
- package/internal/validators/response/principalPolicySnapshotPage.js.map +1 -0
- package/internal/validators/response/projectionPolicyEvidence.d.ts +85 -613
- package/internal/validators/response/projectionPolicyEvidence.js +10 -5
- package/internal/validators/response/projectionPolicyEvidence.js.map +1 -1
- package/package.json +1 -1
- package/stores/documents/documentStore/attachmentHydration.js +3 -0
- package/stores/documents/documentStore/attachmentHydration.js.map +1 -1
- package/stores/documents/documentStore/syncDetachedAttachments.js +3 -0
- package/stores/documents/documentStore/syncDetachedAttachments.js.map +1 -1
- package/workflows/blobs/decrypt.d.ts +1 -1
- package/workflows/blobs/decrypt.js +3 -1
- package/workflows/blobs/decrypt.js.map +1 -1
- package/workflows/blobs/detach.js +6 -1
- package/workflows/blobs/detach.js.map +1 -1
- package/workflows/blobs/hydrate.d.ts +3 -1
- package/workflows/blobs/hydrate.js +2 -0
- package/workflows/blobs/hydrate.js.map +1 -1
- package/workflows/blobs/retainedAttachmentVerification.js +2 -0
- package/workflows/blobs/retainedAttachmentVerification.js.map +1 -1
- package/workflows/container-contents/container-state/createAdoption.js +2 -0
- package/workflows/container-contents/container-state/createAdoption.js.map +1 -1
- package/workflows/container-contents/container-state/createWithMetadata.js +7 -39
- package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
- package/workflows/container-contents/container-state/createWithMetadataPlan.js +68 -0
- package/workflows/container-contents/container-state/createWithMetadataPlan.js.map +1 -0
- package/workflows/container-contents/remoteContainerState.js +3 -1
- package/workflows/container-contents/remoteContainerState.js.map +1 -1
- package/workflows/container-contents/remoteHydration/verifiedDestination.js +3 -0
- package/workflows/container-contents/remoteHydration/verifiedDestination.js.map +1 -1
- package/workflows/container-contents/runtime.d.ts +3 -0
- package/workflows/container-contents/runtime.js +7 -6
- package/workflows/container-contents/runtime.js.map +1 -1
- package/workflows/containers/child/share.js +4 -0
- package/workflows/containers/child/share.js.map +1 -1
- package/workflows/containers/child/sharePrincipalPolicy.d.ts +1 -0
- package/workflows/containers/child/sharePrincipalPolicy.js.map +1 -1
- package/workflows/documents/create.d.ts +2 -15
- package/workflows/documents/create.js +9 -64
- package/workflows/documents/create.js.map +1 -1
- package/workflows/documents/createProjection.d.ts +14 -0
- package/workflows/documents/createProjection.js +26 -0
- package/workflows/documents/createProjection.js.map +1 -0
- package/workflows/documents/createResponse.js +49 -0
- package/workflows/documents/createResponse.js.map +1 -0
- package/workflows/documents/linkSetBlobRewraps.js +2 -0
- package/workflows/documents/linkSetBlobRewraps.js.map +1 -1
- package/workflows/documents/runtime.d.ts +3 -0
- package/workflows/documents/runtime.js +3 -2
- package/workflows/documents/runtime.js.map +1 -1
- package/workflows/documents/syncFailureClassification.js +3 -1
- package/workflows/documents/syncFailureClassification.js.map +1 -1
- package/workflows/organizations/acknowledgedDirectoryBindings.js +18 -0
- package/workflows/organizations/acknowledgedDirectoryBindings.js.map +1 -0
- package/workflows/organizations/currentGroupMetadataAuthority.js +32 -0
- package/workflows/organizations/currentGroupMetadataAuthority.js.map +1 -0
- package/workflows/organizations/currentOrganizationAuthority.js +88 -0
- package/workflows/organizations/currentOrganizationAuthority.js.map +1 -0
- package/workflows/organizations/currentOrganizationGroupNames.js +68 -0
- package/workflows/organizations/currentOrganizationGroupNames.js.map +1 -0
- package/workflows/organizations/currentPolicyMutationAcknowledgement.js +65 -0
- package/workflows/organizations/currentPolicyMutationAcknowledgement.js.map +1 -0
- package/workflows/organizations/deleteOrganizationGroup.js +1 -0
- package/workflows/organizations/deleteOrganizationGroup.js.map +1 -1
- package/workflows/organizations/groupCreation.js +1 -0
- package/workflows/organizations/groupCreation.js.map +1 -1
- package/workflows/organizations/groupMetadataAccess.d.ts +2 -2
- package/workflows/organizations/groupMetadataAccess.js +1 -1
- package/workflows/organizations/groupMetadataAccess.js.map +1 -1
- package/workflows/organizations/groupMetadataBinding.js.map +1 -1
- package/workflows/organizations/groupMetadataContainerAuthority.js +2 -47
- package/workflows/organizations/groupMetadataContainerAuthority.js.map +1 -1
- package/workflows/organizations/groupMetadataRootBinding.js +51 -0
- package/workflows/organizations/groupMetadataRootBinding.js.map +1 -0
- package/workflows/organizations/groupMetadataRuntime.js +20 -9
- package/workflows/organizations/groupMetadataRuntime.js.map +1 -1
- package/workflows/organizations/groupMutationAuthorization.js.map +1 -1
- package/workflows/organizations/groupPolicyMutationAcknowledgement.js +9 -75
- package/workflows/organizations/groupPolicyMutationAcknowledgement.js.map +1 -1
- package/workflows/organizations/groupPolicyMutationContext.d.ts +5 -13
- package/workflows/organizations/groupPolicyMutationContext.js +1 -0
- package/workflows/organizations/groupPolicyMutationContext.js.map +1 -1
- package/workflows/organizations/groupPolicyMutationEvidence.d.ts +26 -0
- package/workflows/organizations/groupPolicyMutationEvidence.js +64 -0
- package/workflows/organizations/groupPolicyMutationEvidence.js.map +1 -0
- package/workflows/organizations/groupPolicyMutationHead.js.map +1 -1
- package/workflows/organizations/groupPolicyRequests.js +69 -63
- package/workflows/organizations/groupPolicyRequests.js.map +1 -1
- package/workflows/organizations/index.d.ts +6 -0
- package/workflows/organizations/index.js +5 -0
- package/workflows/organizations/index.js.map +1 -1
- package/workflows/organizations/organizationGroupNames.js +7 -0
- package/workflows/organizations/organizationGroupNames.js.map +1 -1
- package/workflows/organizations/principalCurrentPublicationSeal.js +51 -0
- package/workflows/organizations/principalCurrentPublicationSeal.js.map +1 -0
- package/workflows/organizations/principalMutationJournalLane.js +26 -0
- package/workflows/organizations/principalMutationJournalLane.js.map +1 -0
- package/workflows/organizations/principalMutationJournalManagement.d.ts +26 -0
- package/workflows/organizations/principalMutationJournalManagement.js +104 -0
- package/workflows/organizations/principalMutationJournalManagement.js.map +1 -0
- package/workflows/organizations/principalMutationJournalSession.d.ts +26 -0
- package/workflows/organizations/principalMutationJournalSession.js +85 -0
- package/workflows/organizations/principalMutationJournalSession.js.map +1 -0
- package/workflows/organizations/principalMutationReceipt.js +21 -0
- package/workflows/organizations/principalMutationReceipt.js.map +1 -0
- package/workflows/organizations/principalPolicyReceiptArtifacts.js +74 -0
- package/workflows/organizations/principalPolicyReceiptArtifacts.js.map +1 -0
- package/workflows/organizations/principalPolicyRequest.d.ts +5 -4
- package/workflows/organizations/principalPolicyRequest.js.map +1 -1
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.d.ts +21 -0
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +155 -0
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -0
- package/workflows/principals/index.d.ts +2 -0
- package/workflows/principals/index.js +1 -0
- package/workflows/principals/index.js.map +1 -1
- package/workflows/principals/policyVerification.js.map +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js +14 -0
- package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -0
- package/workflows/principals/principalHistoryRecoveryAuthority.js +20 -0
- package/workflows/principals/principalHistoryRecoveryAuthority.js.map +1 -0
- package/workflows/principals/principalHistoryRecoveryStage.js +1 -1
- package/workflows/principals/principalHistoryRecoveryStage.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryTypes.d.ts +3 -3
- package/workflows/principals/principalHistoryRecoveryTypes.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryVerification.js +6 -1
- package/workflows/principals/principalHistoryRecoveryVerification.js.map +1 -1
- package/workflows/principals/principalRecoveryDirectory.d.ts +1 -1
- package/workflows/principals/principalRecoveryDirectory.js +29 -4
- package/workflows/principals/principalRecoveryDirectory.js.map +1 -1
- package/workflows/principals/principalRecoveryDiscoveryPage.js +36 -0
- package/workflows/principals/principalRecoveryDiscoveryPage.js.map +1 -0
- package/workflows/principals/principalRecoveryLocalPreference.js +28 -0
- package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -0
- package/workflows/principals/principalRecoveryMemo.d.ts +16 -0
- package/workflows/principals/principalRecoveryMemo.js +88 -16
- package/workflows/principals/principalRecoveryMemo.js.map +1 -1
- package/workflows/principals/principalRecoveryOutage.js +1 -1
- package/workflows/principals/principalRecoveryOutage.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryAuthority.js +60 -0
- package/workflows/principals/publicPrincipalHistoryAuthority.js.map +1 -0
- package/workflows/principals/publicPrincipalHistoryPage.js +87 -0
- package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -0
- package/workflows/principals/publicPrincipalHistoryProgress.js +178 -0
- package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -0
- package/workflows/principals/publicPrincipalHistoryTypes.d.ts +39 -0
- package/workflows/principals/publicPrincipalHistoryTypes.js +2 -0
- package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -0
- package/workflows/principals/publicProjectionDirectory.js +40 -0
- package/workflows/principals/publicProjectionDirectory.js.map +1 -0
- package/workflows/principals/publicProjectionPrincipal.js +53 -0
- package/workflows/principals/publicProjectionPrincipal.js.map +1 -0
- package/workflows/principals/recoverCurrentOrganizationPolicy.js +33 -0
- package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -0
- package/workflows/principals/recoverPrincipalPolicyHistory.js +4 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverProjectionPolicyHistory.d.ts +9 -0
- package/workflows/principals/recoverProjectionPolicyHistory.js +98 -0
- package/workflows/principals/recoverProjectionPolicyHistory.js.map +1 -0
- package/workflows/principals/recoverPublicPrincipalHistory.js +176 -0
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -0
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +2 -1
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +15 -20
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +16 -9
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/runtimePolicyWarmer.js +2 -0
- package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
- package/workflows/principals/runtimeProjectionPolicyRecovery.js +56 -0
- package/workflows/principals/runtimeProjectionPolicyRecovery.js.map +1 -0
- package/workflows/principals/selectPublicPrincipalHistory.js +90 -0
- package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -0
- package/workflows/registration/provisioningBootstrapBuilders.d.ts +21 -153
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { KeyingVerificationError } from "../../internal/crypto/index.js";
|
|
2
|
+
import { canonicalKeyingJsonString } from "../../data/keyingCanonicalJson.js";
|
|
3
|
+
import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
|
|
4
|
+
import { clearPrincipalMutationJournal, loadPrincipalMutationJournal, } from "../../data/persistence/principalMutationJournalPersistence.js";
|
|
5
|
+
import { openPrincipalMutation, principalMutationJournalScopeId, } from "../../data/principals/principalMutationJournal.js";
|
|
6
|
+
import { principalMutationJournalRecordId, UnreadablePrincipalMutationError, } from "../../data/principals/principalMutationJournalRecord.js";
|
|
7
|
+
import { runPrincipalMutationJournalOperation } from "./principalMutationJournalLane.js";
|
|
8
|
+
async function loadAuthenticatedMutation(input) {
|
|
9
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
10
|
+
const row = await loadPrincipalMutationJournal(input.execSql, await principalMutationJournalScopeId(input.scope));
|
|
11
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
12
|
+
if (!row)
|
|
13
|
+
return null;
|
|
14
|
+
let mutation;
|
|
15
|
+
try {
|
|
16
|
+
mutation = await openPrincipalMutation({
|
|
17
|
+
scope: input.scope,
|
|
18
|
+
row,
|
|
19
|
+
signingPublicKey: input.signingKeyPair.signingPublicKey,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
24
|
+
if (!(error instanceof KeyingVerificationError))
|
|
25
|
+
throw error;
|
|
26
|
+
const recordId = await principalMutationJournalRecordId(row);
|
|
27
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
28
|
+
throw new UnreadablePrincipalMutationError(recordId, error.code === "invalid_shape" ? "format" : "authentication");
|
|
29
|
+
}
|
|
30
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
31
|
+
return { row, mutation };
|
|
32
|
+
}
|
|
33
|
+
/** Discard only the inspected unreadable bytes; never parse them for submission. */
|
|
34
|
+
export async function discardUnreadableJournaledPrincipalMutation(input) {
|
|
35
|
+
if (input.acknowledgeUnknownOutcome !== true)
|
|
36
|
+
throw new Error("Discarding unreadable work requires acknowledging its unknown outcome");
|
|
37
|
+
const expected = input.recordId;
|
|
38
|
+
return runPrincipalMutationJournalOperation(input.execSql, input.scope, async () => {
|
|
39
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
40
|
+
const row = await loadPrincipalMutationJournal(input.execSql, await principalMutationJournalScopeId(input.scope));
|
|
41
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
42
|
+
if (!row)
|
|
43
|
+
return false;
|
|
44
|
+
if ((await principalMutationJournalRecordId(row)) !== expected)
|
|
45
|
+
throw new Error("The unreadable principal mutation changed after inspection");
|
|
46
|
+
let unreadable = false;
|
|
47
|
+
try {
|
|
48
|
+
await openPrincipalMutation({
|
|
49
|
+
scope: input.scope,
|
|
50
|
+
row,
|
|
51
|
+
signingPublicKey: input.signingKeyPair.signingPublicKey,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (!(error instanceof KeyingVerificationError))
|
|
56
|
+
throw error;
|
|
57
|
+
unreadable = true;
|
|
58
|
+
}
|
|
59
|
+
if (!unreadable)
|
|
60
|
+
throw new Error("Readable principal mutations require ordinary abandonment");
|
|
61
|
+
const removed = await clearPrincipalMutationJournal({
|
|
62
|
+
execSql: input.execSql,
|
|
63
|
+
row,
|
|
64
|
+
stillCurrent: input.stillCurrent,
|
|
65
|
+
});
|
|
66
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
67
|
+
if (!removed)
|
|
68
|
+
throw new Error("The unreadable principal mutation changed during discard");
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** Inspect authenticated authored work without retrying it or changing checkpoints. */
|
|
73
|
+
export async function readJournaledPrincipalMutation(input) {
|
|
74
|
+
// Inspection may observe an owned dispatch; all mutations still use the lane.
|
|
75
|
+
return (await loadAuthenticatedMutation(input))?.mutation ?? null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* An explicit host/user choice to stop retries, not a claim that the write failed.
|
|
79
|
+
* The exact inspected request must still own the lane; ordinary recovery never
|
|
80
|
+
* calls this. Future authoring must still verify the latest policy state.
|
|
81
|
+
*/
|
|
82
|
+
export async function abandonJournaledPrincipalMutation(input) {
|
|
83
|
+
if (input.acknowledgeUnknownOutcome !== true)
|
|
84
|
+
throw new Error("Abandoning authored work requires acknowledging its unknown outcome");
|
|
85
|
+
const expected = canonicalKeyingJsonString(JSON.parse(JSON.stringify(input.mutation)), "inspected authored mutation");
|
|
86
|
+
return runPrincipalMutationJournalOperation(input.execSql, input.scope, async () => {
|
|
87
|
+
const saved = await loadAuthenticatedMutation(input);
|
|
88
|
+
if (!saved)
|
|
89
|
+
return false;
|
|
90
|
+
if (canonicalKeyingJsonString(saved.mutation, "saved authored mutation") !==
|
|
91
|
+
expected)
|
|
92
|
+
throw new Error("The pending principal mutation changed after inspection");
|
|
93
|
+
const removed = await clearPrincipalMutationJournal({
|
|
94
|
+
execSql: input.execSql,
|
|
95
|
+
row: saved.row,
|
|
96
|
+
stillCurrent: input.stillCurrent,
|
|
97
|
+
});
|
|
98
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
99
|
+
if (!removed)
|
|
100
|
+
throw new Error("The pending principal mutation changed during abandonment");
|
|
101
|
+
return true;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=principalMutationJournalManagement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalMutationJournalManagement.js","sourceRoot":"","sources":["principalMutationJournalManagement.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { canonicalKeyingJsonString } from \"../../data/keyingCanonicalJson\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport {\n clearPrincipalMutationJournal,\n loadPrincipalMutationJournal,\n} from \"../../data/persistence/principalMutationJournalPersistence\";\nimport {\n type AuthoredPrincipalMutation,\n openPrincipalMutation,\n principalMutationJournalScopeId,\n} from \"../../data/principals/principalMutationJournal\";\nimport {\n principalMutationJournalRecordId,\n UnreadablePrincipalMutationError,\n} from \"../../data/principals/principalMutationJournalRecord\";\nimport { runPrincipalMutationJournalOperation } from \"./principalMutationJournalLane\";\nimport type { PrincipalMutationJournalContext } from \"./principalMutationJournalSession\";\n\nexport interface PrincipalMutationRecoveryApi {\n readonly readPendingPrincipalMutation: (\n organizationId: string,\n ) => Promise<AuthoredPrincipalMutation | null>;\n readonly recoverPendingPrincipalMutation: (\n organizationId: string,\n ) => Promise<void>;\n readonly abandonPendingPrincipalMutation: (\n organizationId: string,\n mutation: AuthoredPrincipalMutation,\n acknowledgeUnknownOutcome: true,\n ) => Promise<boolean>;\n readonly discardUnreadablePrincipalMutation: (\n organizationId: string,\n recordId: string,\n acknowledgeUnknownOutcome: true,\n ) => Promise<boolean>;\n}\n\ntype JournalIdentity = Pick<\n PrincipalMutationJournalContext,\n \"execSql\" | \"scope\" | \"signingKeyPair\" | \"stillCurrent\"\n>;\n\nasync function loadAuthenticatedMutation(input: JournalIdentity) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const row = await loadPrincipalMutationJournal(\n input.execSql,\n await principalMutationJournalScopeId(input.scope),\n );\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (!row) return null;\n let mutation: AuthoredPrincipalMutation;\n try {\n mutation = await openPrincipalMutation({\n scope: input.scope,\n row,\n signingPublicKey: input.signingKeyPair.signingPublicKey,\n });\n } catch (error) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (!(error instanceof KeyingVerificationError)) throw error;\n const recordId = await principalMutationJournalRecordId(row);\n assertProjectionVerificationCurrent(input.stillCurrent);\n throw new UnreadablePrincipalMutationError(\n recordId,\n error.code === \"invalid_shape\" ? \"format\" : \"authentication\",\n );\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n return { row, mutation };\n}\n\n/** Discard only the inspected unreadable bytes; never parse them for submission. */\nexport async function discardUnreadableJournaledPrincipalMutation(\n input: JournalIdentity & {\n readonly recordId: string;\n readonly acknowledgeUnknownOutcome: true;\n },\n): Promise<boolean> {\n if (input.acknowledgeUnknownOutcome !== true)\n throw new Error(\n \"Discarding unreadable work requires acknowledging its unknown outcome\",\n );\n const expected = input.recordId;\n return runPrincipalMutationJournalOperation(\n input.execSql,\n input.scope,\n async () => {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const row = await loadPrincipalMutationJournal(\n input.execSql,\n await principalMutationJournalScopeId(input.scope),\n );\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (!row) return false;\n if ((await principalMutationJournalRecordId(row)) !== expected)\n throw new Error(\n \"The unreadable principal mutation changed after inspection\",\n );\n let unreadable = false;\n try {\n await openPrincipalMutation({\n scope: input.scope,\n row,\n signingPublicKey: input.signingKeyPair.signingPublicKey,\n });\n } catch (error) {\n if (!(error instanceof KeyingVerificationError)) throw error;\n unreadable = true;\n }\n if (!unreadable)\n throw new Error(\n \"Readable principal mutations require ordinary abandonment\",\n );\n const removed = await clearPrincipalMutationJournal({\n execSql: input.execSql,\n row,\n stillCurrent: input.stillCurrent,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (!removed)\n throw new Error(\n \"The unreadable principal mutation changed during discard\",\n );\n return true;\n },\n );\n}\n\n/** Inspect authenticated authored work without retrying it or changing checkpoints. */\nexport async function readJournaledPrincipalMutation(\n input: JournalIdentity,\n): Promise<AuthoredPrincipalMutation | null> {\n // Inspection may observe an owned dispatch; all mutations still use the lane.\n return (await loadAuthenticatedMutation(input))?.mutation ?? null;\n}\n\n/**\n * An explicit host/user choice to stop retries, not a claim that the write failed.\n * The exact inspected request must still own the lane; ordinary recovery never\n * calls this. Future authoring must still verify the latest policy state.\n */\nexport async function abandonJournaledPrincipalMutation(\n input: JournalIdentity & {\n readonly mutation: AuthoredPrincipalMutation;\n readonly acknowledgeUnknownOutcome: true;\n },\n): Promise<boolean> {\n if (input.acknowledgeUnknownOutcome !== true)\n throw new Error(\n \"Abandoning authored work requires acknowledging its unknown outcome\",\n );\n const expected = canonicalKeyingJsonString(\n JSON.parse(JSON.stringify(input.mutation)),\n \"inspected authored mutation\",\n );\n return runPrincipalMutationJournalOperation(\n input.execSql,\n input.scope,\n async () => {\n const saved = await loadAuthenticatedMutation(input);\n if (!saved) return false;\n if (\n canonicalKeyingJsonString(saved.mutation, \"saved authored mutation\") !==\n expected\n )\n throw new Error(\n \"The pending principal mutation changed after inspection\",\n );\n const removed = await clearPrincipalMutationJournal({\n execSql: input.execSql,\n row: saved.row,\n stillCurrent: input.stillCurrent,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (!removed)\n throw new Error(\n \"The pending principal mutation changed during abandonment\",\n );\n return true;\n },\n );\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RequestResult } from "../../internal/api-client/index.js";
|
|
2
|
+
import type { SigningKeyPair } from "../../internal/crypto/index.js";
|
|
3
|
+
import type { CommitOrganizationGroupPolicyResponse } from "../../internal/validators/response/index.js";
|
|
4
|
+
import { type AuthoredPrincipalMutation, type PrincipalMutationJournalScope } from "../../data/principals/principalMutationJournal.js";
|
|
5
|
+
import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
|
|
6
|
+
type MutationResult = RequestResult<CommitOrganizationGroupPolicyResponse>;
|
|
7
|
+
export interface PrincipalMutationJournalContext {
|
|
8
|
+
readonly execSql: ExecSql;
|
|
9
|
+
readonly scope: PrincipalMutationJournalScope;
|
|
10
|
+
readonly signingKeyPair: SigningKeyPair;
|
|
11
|
+
readonly stillCurrent: () => boolean;
|
|
12
|
+
readonly submit: (mutation: AuthoredPrincipalMutation) => Promise<MutationResult>;
|
|
13
|
+
}
|
|
14
|
+
export declare class PrincipalMutationOutcomeUnknownError extends Error {
|
|
15
|
+
constructor(options?: ErrorOptions);
|
|
16
|
+
}
|
|
17
|
+
/** No HTTP begins until the exact authored request is durably claimed. */
|
|
18
|
+
export declare function submitJournaledPrincipalMutation(input: PrincipalMutationJournalContext & {
|
|
19
|
+
readonly mutation: AuthoredPrincipalMutation;
|
|
20
|
+
}): Promise<MutationResult>;
|
|
21
|
+
/** Retry only authenticated saved bytes, never an application mutation callback. */
|
|
22
|
+
export declare function recoverJournaledPrincipalMutation(input: PrincipalMutationJournalContext): Promise<{
|
|
23
|
+
readonly mutation: AuthoredPrincipalMutation;
|
|
24
|
+
readonly response: CommitOrganizationGroupPolicyResponse;
|
|
25
|
+
} | null>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
|
|
2
|
+
import { claimPrincipalMutationJournal, clearPrincipalMutationJournal, loadPrincipalMutationJournal, } from "../../data/persistence/principalMutationJournalPersistence.js";
|
|
3
|
+
import { openPrincipalMutation, principalMutationJournalScopeId, sealPrincipalMutation, } from "../../data/principals/principalMutationJournal.js";
|
|
4
|
+
import { runPrincipalMutationJournalOperation } from "./principalMutationJournalLane.js";
|
|
5
|
+
import { assertAuthoredPrincipalMutationReceipt } from "./principalMutationReceipt.js";
|
|
6
|
+
export class PrincipalMutationOutcomeUnknownError extends Error {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super("A saved policy request may have committed; resolve its outcome or explicitly abandon its retry before another mutation", options);
|
|
9
|
+
this.name = "PrincipalMutationOutcomeUnknownError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function knownInitialRefusal(result) {
|
|
13
|
+
if (result.ok)
|
|
14
|
+
return false;
|
|
15
|
+
// ApiClient separates pre-dispatch cancellation from an uncertain sent write.
|
|
16
|
+
if (result.kind === "cancelled")
|
|
17
|
+
return true;
|
|
18
|
+
if (result.kind !== "http")
|
|
19
|
+
return false;
|
|
20
|
+
return ([400, 401, 402, 403, 409].includes(result.status ?? 0) ||
|
|
21
|
+
(result.status === 503 &&
|
|
22
|
+
result.code === "principal_history_preparation_unavailable"));
|
|
23
|
+
}
|
|
24
|
+
async function submitSavedMutation(input, row, recovering) {
|
|
25
|
+
const mutation = await openPrincipalMutation({
|
|
26
|
+
scope: input.scope,
|
|
27
|
+
row,
|
|
28
|
+
signingPublicKey: input.signingKeyPair.signingPublicKey,
|
|
29
|
+
});
|
|
30
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
31
|
+
// Keep the authenticated copy for acknowledgement checks even if a transport
|
|
32
|
+
// mutates its argument while preparing or retrying the HTTP request.
|
|
33
|
+
let result;
|
|
34
|
+
try {
|
|
35
|
+
result = await input.submit(structuredClone(mutation));
|
|
36
|
+
}
|
|
37
|
+
catch (cause) {
|
|
38
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
39
|
+
throw new PrincipalMutationOutcomeUnknownError({ cause });
|
|
40
|
+
}
|
|
41
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
42
|
+
if (result.ok) {
|
|
43
|
+
await assertAuthoredPrincipalMutationReceipt(mutation.request, result.data);
|
|
44
|
+
}
|
|
45
|
+
else if (recovering || !knownInitialRefusal(result)) {
|
|
46
|
+
// A refusal today (including loss of admin access) cannot establish whether
|
|
47
|
+
// an earlier disconnected attempt committed. Preserve the original intent.
|
|
48
|
+
throw new PrincipalMutationOutcomeUnknownError();
|
|
49
|
+
}
|
|
50
|
+
await clearPrincipalMutationJournal({
|
|
51
|
+
execSql: input.execSql,
|
|
52
|
+
row,
|
|
53
|
+
stillCurrent: input.stillCurrent,
|
|
54
|
+
});
|
|
55
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
56
|
+
return { mutation, result };
|
|
57
|
+
}
|
|
58
|
+
/** No HTTP begins until the exact authored request is durably claimed. */
|
|
59
|
+
export async function submitJournaledPrincipalMutation(input) {
|
|
60
|
+
return runPrincipalMutationJournalOperation(input.execSql, input.scope, async () => {
|
|
61
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
62
|
+
const row = await sealPrincipalMutation(input);
|
|
63
|
+
await claimPrincipalMutationJournal({
|
|
64
|
+
execSql: input.execSql,
|
|
65
|
+
row,
|
|
66
|
+
stillCurrent: input.stillCurrent,
|
|
67
|
+
});
|
|
68
|
+
return (await submitSavedMutation(input, row, false)).result;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** Retry only authenticated saved bytes, never an application mutation callback. */
|
|
72
|
+
export async function recoverJournaledPrincipalMutation(input) {
|
|
73
|
+
return runPrincipalMutationJournalOperation(input.execSql, input.scope, async () => {
|
|
74
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
75
|
+
const row = await loadPrincipalMutationJournal(input.execSql, await principalMutationJournalScopeId(input.scope));
|
|
76
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
77
|
+
if (!row)
|
|
78
|
+
return null;
|
|
79
|
+
const { mutation, result } = await submitSavedMutation(input, row, true);
|
|
80
|
+
if (!result.ok)
|
|
81
|
+
throw new PrincipalMutationOutcomeUnknownError();
|
|
82
|
+
return { mutation, response: result.data };
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=principalMutationJournalSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalMutationJournalSession.js","sourceRoot":"","sources":["principalMutationJournalSession.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RequestResult } from \"@tearleads/api-client\";\nimport type { SigningKeyPair } from \"@tearleads/crypto\";\nimport type { CommitOrganizationGroupPolicyResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport {\n claimPrincipalMutationJournal,\n clearPrincipalMutationJournal,\n loadPrincipalMutationJournal,\n type PrincipalMutationJournalRow,\n} from \"../../data/persistence/principalMutationJournalPersistence\";\nimport {\n type AuthoredPrincipalMutation,\n openPrincipalMutation,\n type PrincipalMutationJournalScope,\n principalMutationJournalScopeId,\n sealPrincipalMutation,\n} from \"../../data/principals/principalMutationJournal\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { runPrincipalMutationJournalOperation } from \"./principalMutationJournalLane\";\nimport { assertAuthoredPrincipalMutationReceipt } from \"./principalMutationReceipt\";\n\ntype MutationResult = RequestResult<CommitOrganizationGroupPolicyResponse>;\n\nexport interface PrincipalMutationJournalContext {\n readonly execSql: ExecSql;\n readonly scope: PrincipalMutationJournalScope;\n readonly signingKeyPair: SigningKeyPair;\n readonly stillCurrent: () => boolean;\n readonly submit: (\n mutation: AuthoredPrincipalMutation,\n ) => Promise<MutationResult>;\n}\n\nexport class PrincipalMutationOutcomeUnknownError extends Error {\n constructor(options?: ErrorOptions) {\n super(\n \"A saved policy request may have committed; resolve its outcome or explicitly abandon its retry before another mutation\",\n options,\n );\n this.name = \"PrincipalMutationOutcomeUnknownError\";\n }\n}\n\nfunction knownInitialRefusal(result: MutationResult): boolean {\n if (result.ok) return false;\n // ApiClient separates pre-dispatch cancellation from an uncertain sent write.\n if (result.kind === \"cancelled\") return true;\n if (result.kind !== \"http\") return false;\n return (\n [400, 401, 402, 403, 409].includes(result.status ?? 0) ||\n (result.status === 503 &&\n result.code === \"principal_history_preparation_unavailable\")\n );\n}\n\nasync function submitSavedMutation(\n input: PrincipalMutationJournalContext,\n row: PrincipalMutationJournalRow,\n recovering: boolean,\n): Promise<{ mutation: AuthoredPrincipalMutation; result: MutationResult }> {\n const mutation = await openPrincipalMutation({\n scope: input.scope,\n row,\n signingPublicKey: input.signingKeyPair.signingPublicKey,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n // Keep the authenticated copy for acknowledgement checks even if a transport\n // mutates its argument while preparing or retrying the HTTP request.\n let result: MutationResult;\n try {\n result = await input.submit(structuredClone(mutation));\n } catch (cause) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n throw new PrincipalMutationOutcomeUnknownError({ cause });\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (result.ok) {\n await assertAuthoredPrincipalMutationReceipt(mutation.request, result.data);\n } else if (recovering || !knownInitialRefusal(result)) {\n // A refusal today (including loss of admin access) cannot establish whether\n // an earlier disconnected attempt committed. Preserve the original intent.\n throw new PrincipalMutationOutcomeUnknownError();\n }\n await clearPrincipalMutationJournal({\n execSql: input.execSql,\n row,\n stillCurrent: input.stillCurrent,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n return { mutation, result };\n}\n\n/** No HTTP begins until the exact authored request is durably claimed. */\nexport async function submitJournaledPrincipalMutation(\n input: PrincipalMutationJournalContext & {\n readonly mutation: AuthoredPrincipalMutation;\n },\n): Promise<MutationResult> {\n return runPrincipalMutationJournalOperation(\n input.execSql,\n input.scope,\n async () => {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const row = await sealPrincipalMutation(input);\n await claimPrincipalMutationJournal({\n execSql: input.execSql,\n row,\n stillCurrent: input.stillCurrent,\n });\n return (await submitSavedMutation(input, row, false)).result;\n },\n );\n}\n\n/** Retry only authenticated saved bytes, never an application mutation callback. */\nexport async function recoverJournaledPrincipalMutation(\n input: PrincipalMutationJournalContext,\n): Promise<{\n readonly mutation: AuthoredPrincipalMutation;\n readonly response: CommitOrganizationGroupPolicyResponse;\n} | null> {\n return runPrincipalMutationJournalOperation(\n input.execSql,\n input.scope,\n async () => {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const row = await loadPrincipalMutationJournal(\n input.execSql,\n await principalMutationJournalScopeId(input.scope),\n );\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (!row) return null;\n const { mutation, result } = await submitSavedMutation(input, row, true);\n if (!result.ok) throw new PrincipalMutationOutcomeUnknownError();\n return { mutation, response: result.data };\n },\n );\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { computePrincipalStateHash } from "../../internal/crypto/index.js";
|
|
2
|
+
import { canonicalKeyingJsonString } from "../../data/keyingCanonicalJson.js";
|
|
3
|
+
import { assertPrincipalPolicyReceiptArtifacts } from "./principalPolicyReceiptArtifacts.js";
|
|
4
|
+
/** A past commit acknowledgement is not evidence for advancing current pins. */
|
|
5
|
+
export async function assertAuthoredPrincipalMutationReceipt(request, response) {
|
|
6
|
+
for (const part of ["groupPolicy", "organizationPolicy"]) {
|
|
7
|
+
const expected = request[part];
|
|
8
|
+
const observed = response[part];
|
|
9
|
+
const { stateHash, createdAt: _createdAt, ...state } = observed.currentState;
|
|
10
|
+
if (stateHash !== (await computePrincipalStateHash(expected.state)) ||
|
|
11
|
+
canonicalKeyingJsonString(state, "principal mutation receipt state") !==
|
|
12
|
+
canonicalKeyingJsonString(expected.state, "authored principal state"))
|
|
13
|
+
throw new Error("Principal mutation receipt state differs from the authored request");
|
|
14
|
+
assertPrincipalPolicyReceiptArtifacts({
|
|
15
|
+
request: expected,
|
|
16
|
+
response: observed,
|
|
17
|
+
expectedHead: { ...observed.currentState, stateHash },
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=principalMutationReceipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalMutationReceipt.js","sourceRoot":"","sources":["principalMutationReceipt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,qCAAqC,EAAE,MAAM,mCAAmC,CAAC;AAE1F,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,sCAAsC,CAC1D,OAA6C,EAC7C,QAA+C;IAE/C,KAAK,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAU,EAAE,CAAC;QAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,EACJ,SAAS,EACT,SAAS,EAAE,UAAU,EACrB,GAAG,KAAK,EACT,GAAG,QAAQ,CAAC,YAAY,CAAC;QAC1B,IACE,SAAS,KAAK,CAAC,MAAM,yBAAyB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC/D,yBAAyB,CAAC,KAAK,EAAE,kCAAkC,CAAC;gBAClE,yBAAyB,CAAC,QAAQ,CAAC,KAAK,EAAE,0BAA0B,CAAC;YAEvE,MAAM,IAAI,KAAK,CACb,oEAAoE,CACrE,CAAC;QACJ,qCAAqC,CAAC;YACpC,OAAO,EAAE,QAAQ;YACjB,QAAQ,EAAE,QAAQ;YAClB,YAAY,EAAE,EAAE,GAAG,QAAQ,CAAC,YAAY,EAAE,SAAS,EAAE;SACtD,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["import { computePrincipalStateHash } from \"@tearleads/crypto\";\nimport type { CommitOrganizationGroupPolicyRequest } from \"@tearleads/validators/request\";\nimport type { CommitOrganizationGroupPolicyResponse } from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../../data/keyingCanonicalJson\";\nimport { assertPrincipalPolicyReceiptArtifacts } from \"./principalPolicyReceiptArtifacts\";\n\n/** A past commit acknowledgement is not evidence for advancing current pins. */\nexport async function assertAuthoredPrincipalMutationReceipt(\n request: CommitOrganizationGroupPolicyRequest,\n response: CommitOrganizationGroupPolicyResponse,\n): Promise<void> {\n for (const part of [\"groupPolicy\", \"organizationPolicy\"] as const) {\n const expected = request[part];\n const observed = response[part];\n const {\n stateHash,\n createdAt: _createdAt,\n ...state\n } = observed.currentState;\n if (\n stateHash !== (await computePrincipalStateHash(expected.state)) ||\n canonicalKeyingJsonString(state, \"principal mutation receipt state\") !==\n canonicalKeyingJsonString(expected.state, \"authored principal state\")\n )\n throw new Error(\n \"Principal mutation receipt state differs from the authored request\",\n );\n assertPrincipalPolicyReceiptArtifacts({\n request: expected,\n response: observed,\n expectedHead: { ...observed.currentState, stateHash },\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { compareCanonicalStrings, normalizePrincipalContainerGrants, normalizePrincipalProjectionMembers, } from "../../internal/crypto/index.js";
|
|
2
|
+
import { canonicalKeyingJsonString } from "../../data/keyingCanonicalJson.js";
|
|
3
|
+
function sortedCanonicalValues(values, label) {
|
|
4
|
+
return [...values].sort((left, right) => compareCanonicalStrings(canonicalKeyingJsonString(left, label), canonicalKeyingJsonString(right, label)));
|
|
5
|
+
}
|
|
6
|
+
export function assertGroupPolicyEnvelopesMatchAcknowledgement(expected, observed) {
|
|
7
|
+
const normalized = (value) => ({
|
|
8
|
+
...value,
|
|
9
|
+
envelopes: sortedCanonicalValues(value.envelopes, "principal member envelope"),
|
|
10
|
+
});
|
|
11
|
+
if (canonicalKeyingJsonString(normalized(expected), "acknowledged group member envelopes") !==
|
|
12
|
+
canonicalKeyingJsonString(normalized(observed), "observed group member envelopes")) {
|
|
13
|
+
throw new Error("Group member envelopes changed after acknowledgement");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function assertContainerMutationAcknowledgements(input) {
|
|
17
|
+
if (!input.responses || input.responses.length !== input.requests.length) {
|
|
18
|
+
throw new Error("Group policy container acknowledgement batch is incomplete");
|
|
19
|
+
}
|
|
20
|
+
for (const [index, request] of input.requests.entries()) {
|
|
21
|
+
const response = input.responses[index];
|
|
22
|
+
if (!response) {
|
|
23
|
+
throw new Error("Group policy container acknowledgement batch is incomplete");
|
|
24
|
+
}
|
|
25
|
+
const expected = {
|
|
26
|
+
body: request.body,
|
|
27
|
+
event: request.event,
|
|
28
|
+
keyEpoch: request.keyEpoch,
|
|
29
|
+
manifest: request.manifest,
|
|
30
|
+
wraps: sortedCanonicalValues(request.wraps, "authored container wrap"),
|
|
31
|
+
};
|
|
32
|
+
const observed = {
|
|
33
|
+
body: response.accessManifest.event.body,
|
|
34
|
+
event: response.accessManifest.event.event,
|
|
35
|
+
keyEpoch: response.containerKek.keyEpoch,
|
|
36
|
+
manifest: response.accessManifest.manifest,
|
|
37
|
+
wraps: sortedCanonicalValues(response.containerKek.wraps, "stored container wrap"),
|
|
38
|
+
};
|
|
39
|
+
if (canonicalKeyingJsonString(observed, "stored group policy container mutation") !==
|
|
40
|
+
canonicalKeyingJsonString(expected, "authored group policy container mutation")) {
|
|
41
|
+
throw new Error("Group policy container acknowledgement mismatch");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Compare receipt artifacts without manufacturing predecessor history or pins. */
|
|
46
|
+
export function assertPrincipalPolicyReceiptArtifacts(input) {
|
|
47
|
+
assertContainerMutationAcknowledgements({
|
|
48
|
+
requests: input.request.containerMutations ?? [],
|
|
49
|
+
responses: input.response.containerMutations,
|
|
50
|
+
});
|
|
51
|
+
const { createdAt: _payloadCreatedAt, ...observedPayload } = input.response.currentPayload;
|
|
52
|
+
const expectedPayload = {
|
|
53
|
+
principalType: input.request.state.principalType,
|
|
54
|
+
principalId: input.request.state.principalId,
|
|
55
|
+
stateHash: input.expectedHead.stateHash,
|
|
56
|
+
...input.request.encryptedPayload,
|
|
57
|
+
};
|
|
58
|
+
if (canonicalKeyingJsonString(observedPayload, "stored group policy payload") !==
|
|
59
|
+
canonicalKeyingJsonString(expectedPayload, "authored group policy payload") ||
|
|
60
|
+
canonicalKeyingJsonString(normalizePrincipalProjectionMembers(input.response.currentProjection), "stored group policy projection") !==
|
|
61
|
+
canonicalKeyingJsonString(normalizePrincipalProjectionMembers(input.request.projection), "authored group policy projection") ||
|
|
62
|
+
canonicalKeyingJsonString(normalizePrincipalContainerGrants(input.response.currentGrants), "stored group policy grants") !==
|
|
63
|
+
canonicalKeyingJsonString(normalizePrincipalContainerGrants(input.request.grants), "authored group policy grants")) {
|
|
64
|
+
throw new Error("Group policy bundle acknowledgement mismatch");
|
|
65
|
+
}
|
|
66
|
+
assertGroupPolicyEnvelopesMatchAcknowledgement({
|
|
67
|
+
principalType: input.request.state.principalType,
|
|
68
|
+
principalId: input.request.state.principalId,
|
|
69
|
+
stateHash: input.expectedHead.stateHash,
|
|
70
|
+
epoch: input.request.state.keyEpoch,
|
|
71
|
+
envelopes: input.request.memberEnvelopes,
|
|
72
|
+
}, input.response.currentMemberEnvelopes);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=principalPolicyReceiptArtifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalPolicyReceiptArtifacts.js","sourceRoot":"","sources":["principalPolicyReceiptArtifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compareCanonicalStrings,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n type ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerMutationResponse,\n CurrentPrincipalMemberEnvelopesResponse,\n PrincipalPolicyMutationResponse,\n} from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../../data/keyingCanonicalJson\";\n\nfunction sortedCanonicalValues<T>(values: readonly T[], label: string): T[] {\n return [...values].sort((left, right) =>\n compareCanonicalStrings(\n canonicalKeyingJsonString(left, label),\n canonicalKeyingJsonString(right, label),\n ),\n );\n}\n\nexport function assertGroupPolicyEnvelopesMatchAcknowledgement(\n expected: CurrentPrincipalMemberEnvelopesResponse,\n observed: CurrentPrincipalMemberEnvelopesResponse,\n): void {\n const normalized = (value: CurrentPrincipalMemberEnvelopesResponse) => ({\n ...value,\n envelopes: sortedCanonicalValues(\n value.envelopes,\n \"principal member envelope\",\n ),\n });\n if (\n canonicalKeyingJsonString(\n normalized(expected),\n \"acknowledged group member envelopes\",\n ) !==\n canonicalKeyingJsonString(\n normalized(observed),\n \"observed group member envelopes\",\n )\n ) {\n throw new Error(\"Group member envelopes changed after acknowledgement\");\n }\n}\n\nfunction assertContainerMutationAcknowledgements(input: {\n readonly requests: readonly NonNullable<\n PutPrincipalPolicyRequest[\"containerMutations\"]\n >[number][];\n readonly responses: readonly ContainerMutationResponse[] | undefined;\n}): void {\n if (!input.responses || input.responses.length !== input.requests.length) {\n throw new Error(\n \"Group policy container acknowledgement batch is incomplete\",\n );\n }\n for (const [index, request] of input.requests.entries()) {\n const response = input.responses[index];\n if (!response) {\n throw new Error(\n \"Group policy container acknowledgement batch is incomplete\",\n );\n }\n const expected = {\n body: request.body,\n event: request.event,\n keyEpoch: request.keyEpoch,\n manifest: request.manifest,\n wraps: sortedCanonicalValues(request.wraps, \"authored container wrap\"),\n };\n const observed = {\n body: response.accessManifest.event.body,\n event: response.accessManifest.event.event,\n keyEpoch: response.containerKek.keyEpoch,\n manifest: response.accessManifest.manifest,\n wraps: sortedCanonicalValues(\n response.containerKek.wraps,\n \"stored container wrap\",\n ),\n };\n if (\n canonicalKeyingJsonString(\n observed,\n \"stored group policy container mutation\",\n ) !==\n canonicalKeyingJsonString(\n expected,\n \"authored group policy container mutation\",\n )\n ) {\n throw new Error(\"Group policy container acknowledgement mismatch\");\n }\n }\n}\n\n/** Compare receipt artifacts without manufacturing predecessor history or pins. */\nexport function assertPrincipalPolicyReceiptArtifacts(input: {\n readonly expectedHead: ReferencedPrincipalHead;\n readonly request: PutPrincipalPolicyRequest;\n readonly response: PrincipalPolicyMutationResponse;\n}): void {\n assertContainerMutationAcknowledgements({\n requests: input.request.containerMutations ?? [],\n responses: input.response.containerMutations,\n });\n const { createdAt: _payloadCreatedAt, ...observedPayload } =\n input.response.currentPayload;\n const expectedPayload = {\n principalType: input.request.state.principalType,\n principalId: input.request.state.principalId,\n stateHash: input.expectedHead.stateHash,\n ...input.request.encryptedPayload,\n };\n\n if (\n canonicalKeyingJsonString(\n observedPayload,\n \"stored group policy payload\",\n ) !==\n canonicalKeyingJsonString(\n expectedPayload,\n \"authored group policy payload\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(input.response.currentProjection),\n \"stored group policy projection\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(input.request.projection),\n \"authored group policy projection\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(input.response.currentGrants),\n \"stored group policy grants\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(input.request.grants),\n \"authored group policy grants\",\n )\n ) {\n throw new Error(\"Group policy bundle acknowledgement mismatch\");\n }\n\n assertGroupPolicyEnvelopesMatchAcknowledgement(\n {\n principalType: input.request.state.principalType,\n principalId: input.request.state.principalId,\n stateHash: input.expectedHead.stateHash,\n epoch: input.request.state.keyEpoch,\n envelopes: input.request.memberEnvelopes,\n },\n input.response.currentMemberEnvelopes,\n );\n}\n"]}
|
|
@@ -26,13 +26,14 @@ export declare function userProjectionMember(userId: string, role: "member" | "a
|
|
|
26
26
|
* created.
|
|
27
27
|
*/
|
|
28
28
|
export declare function canonicalGroupNameKey(name: string): string;
|
|
29
|
-
|
|
29
|
+
type GroupPolicyNameInput = Pick<PrincipalPolicyBundleResponse, "currentState" | "currentPayload">;
|
|
30
|
+
export type GroupPolicyNameReader = (bundle: GroupPolicyNameInput) => Promise<string>;
|
|
30
31
|
/** Read only after the policy and its organization-directory binding verify. */
|
|
31
|
-
export declare function readGroupPolicyPayloadName(bundle:
|
|
32
|
+
export declare function readGroupPolicyPayloadName(bundle: GroupPolicyNameInput, readEncryptedName?: GroupPolicyNameReader): Promise<string>;
|
|
32
33
|
/** One binding predicate for every operation selected by a read-model label. */
|
|
33
|
-
export declare function groupPolicyNameMismatch(bundle:
|
|
34
|
+
export declare function groupPolicyNameMismatch(bundle: GroupPolicyNameInput, expectedGroupName: string, readEncryptedName?: GroupPolicyNameReader): Promise<"forbidden_characters" | "name_mismatch" | null>;
|
|
34
35
|
export declare function signedGroupPolicyRequest(input: {
|
|
35
|
-
readonly currentPolicy?: PrincipalPolicyBundleResponse
|
|
36
|
+
readonly currentPolicy?: Pick<PrincipalPolicyBundleResponse, "currentState">;
|
|
36
37
|
readonly encapsulationPublicKey: string;
|
|
37
38
|
readonly externalAuthority: PrincipalPolicyExternalAuthority["currentHead"] | null;
|
|
38
39
|
readonly keyEpoch: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principalPolicyRequest.js","sourceRoot":"","sources":["principalPolicyRequest.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n buildPrincipalStateSigningInput,\n type EncapsulationKeyPair,\n encodeBuiltinGroupMetadata,\n encryptGroupMetadata,\n type GroupMetadataKey,\n generateKemSeedAndKeyPair,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n type PrincipalContainerGrant,\n type PrincipalPolicyExternalAuthority,\n readGroupMetadata,\n type SigningKeyPair,\n signPrincipalState,\n toFingerprint,\n wrapDekForRecipients,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type {\n CreateOrganizationGroupRequest,\n PrincipalMemberEnvelopeRequest,\n PrincipalProjectionMemberRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\n\ninterface BuildInitialGroupPolicyInput {\n readonly creatorEncapsulationKeyPair: EncapsulationKeyPair;\n readonly externalAuthority?:\n | PrincipalPolicyExternalAuthority[\"currentHead\"]\n | null;\n readonly groupId: string;\n readonly grants?: readonly PrincipalContainerGrant[] | undefined;\n readonly includeSignerAsAdmin?: boolean;\n readonly name: string;\n readonly metadataKey?: GroupMetadataKey;\n readonly builtinRole?: \"admins\" | \"members\";\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}\n\nexport function userProjectionMember(\n userId: string,\n role: \"member\" | \"admin\",\n): PrincipalProjectionMemberRequest {\n return { userId: userId, role };\n}\n\nfunction projectionToStateMembers(\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n) {\n return projection.map((member) => ({ userId: member.userId }));\n}\n\n/**\n * Code points that must never appear in a group name: control and format\n * characters (bidi overrides, zero-width joiners, newlines), lone surrogates\n * (re-encoded as U+FFFD when signed, so the signed name would no longer match\n * the one sent to the server), and every other default-ignorable code point\n * (Hangul fillers, variation selectors), which render as nothing and would\n * let one name pass for another. A group name is an identifier here, so this\n * deliberately refuses ZWJ emoji sequences as well. One predicate serves the\n * signing-time and the share-time refusal so the two cannot drift.\n */\nfunction hasForbiddenGroupNameCharacter(name: string): boolean {\n return /[\\p{Cc}\\p{Cf}\\p{Cs}\\p{Default_Ignorable_Code_Point}]/u.test(name);\n}\n\n/**\n * The comparison key for a group display name: width- and compatibility-\n * normalized, stripped of control, format, and default-ignorable characters,\n * whitespace-collapsed, and case-folded. Two names that a user cannot tell\n * apart in a picker must compare equal, or a look-alike name would slip past\n * the share-time binding. Cross-script homoglyphs (Latin \"A\" against Greek\n * \"Α\") are not folded: that needs the UTS #39 confusables table, and both\n * names would still have to be signed groups the organization's own admins\n * created.\n */\nexport function canonicalGroupNameKey(name: string): string {\n return (\n name\n .normalize(\"NFKC\")\n .replace(/[\\p{Cc}\\p{Cf}\\p{Default_Ignorable_Code_Point}]/gu, \"\")\n .replace(/\\s+/gu, \" \")\n .trim()\n .toLocaleLowerCase(\"en-US\")\n // Case folding can leave the string un-normalized (U+0130 lowercases to\n // \"i\" plus a combining dot), so normalize once more after it.\n .normalize(\"NFKC\")\n );\n}\n\nexport type GroupPolicyNameReader = (\n bundle: PrincipalPolicyBundleResponse,\n) => Promise<string>;\n\n/** Read only after the policy and its organization-directory binding verify. */\nexport async function readGroupPolicyPayloadName(\n bundle: PrincipalPolicyBundleResponse,\n readEncryptedName?: GroupPolicyNameReader,\n): Promise<string> {\n const metadata = readGroupMetadata(bundle.currentPayload.ciphertext);\n if (\"role\" in metadata)\n return metadata.role === \"admins\" ? \"Admins\" : \"Members\";\n if (!readEncryptedName)\n throw new Error(\"Group metadata decryption context is unavailable\");\n return readEncryptedName(bundle);\n}\n\n/** One binding predicate for every operation selected by a read-model label. */\nexport async function groupPolicyNameMismatch(\n bundle: PrincipalPolicyBundleResponse,\n expectedGroupName: string,\n readEncryptedName?: GroupPolicyNameReader,\n): Promise<\"forbidden_characters\" | \"name_mismatch\" | null> {\n if (hasForbiddenGroupNameCharacter(expectedGroupName)) {\n return \"forbidden_characters\";\n }\n const signedName = await readGroupPolicyPayloadName(\n bundle,\n readEncryptedName,\n );\n if (hasForbiddenGroupNameCharacter(signedName)) return \"forbidden_characters\";\n return canonicalGroupNameKey(signedName) ===\n canonicalGroupNameKey(expectedGroupName)\n ? null\n : \"name_mismatch\";\n}\n\nexport async function signedGroupPolicyRequest(input: {\n readonly currentPolicy?: PrincipalPolicyBundleResponse;\n readonly encapsulationPublicKey: string;\n readonly externalAuthority:\n | PrincipalPolicyExternalAuthority[\"currentHead\"]\n | null;\n readonly keyEpoch: number;\n readonly keyFingerprint: string;\n readonly grants: ReadonlyArray<PrincipalContainerGrant>;\n readonly memberEnvelopes: ReadonlyArray<PrincipalMemberEnvelopeRequest>;\n readonly payloadCiphertext: string;\n readonly principalId: string;\n readonly projection: ReadonlyArray<PrincipalProjectionMemberRequest>;\n readonly signedAt: string;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<PutPrincipalPolicyRequest> {\n const projection = normalizePrincipalProjectionMembers(input.projection);\n const grants = normalizePrincipalContainerGrants(input.grants);\n const payloadCiphertext = input.payloadCiphertext;\n const state = await signPrincipalState(\n await buildPrincipalStateSigningInput({\n principalType: \"group\",\n principalId: input.principalId,\n version: input.currentPolicy\n ? input.currentPolicy.currentState.version + 1\n : 1,\n prevStateHash: input.currentPolicy?.currentState.stateHash ?? null,\n keyEpoch: input.keyEpoch,\n encapsulationPublicKey: input.encapsulationPublicKey,\n keyFingerprint: input.keyFingerprint,\n members: projectionToStateMembers(projection),\n memberEnvelopes: [...input.memberEnvelopes],\n projection,\n grants,\n payloadCiphertext,\n externalAuthority: input.externalAuthority,\n signedAt: input.signedAt,\n signerUserId: input.signerUserId,\n signerUserKeyFingerprint: input.signingFingerprint,\n }),\n input.signingKeyPair.signingPrivateKey,\n );\n\n return {\n state,\n encryptedPayload: {\n cipherSuite: \"aes-256-gcm\",\n ciphertext: payloadCiphertext,\n ciphertextHash: state.payloadCiphertextHash,\n },\n projection,\n grants,\n memberEnvelopes: [...input.memberEnvelopes],\n };\n}\n\nexport async function buildInitialGroupPolicyRequest(\n input: BuildInitialGroupPolicyInput,\n): Promise<CreateOrganizationGroupRequest> {\n const groupKem = generateKemSeedAndKeyPair();\n const withSigner = input.includeSignerAsAdmin ?? true;\n const projection = withSigner\n ? [userProjectionMember(input.signerUserId, \"admin\")]\n : [];\n const memberEnvelopes: PrincipalMemberEnvelopeRequest[] = [];\n\n if (withSigner) {\n const creatorFingerprint = await toFingerprint(\n input.creatorEncapsulationKeyPair.publicKey,\n );\n const [creatorEnvelope] = await wrapDekForRecipients(groupKem.secretKey, [\n input.creatorEncapsulationKeyPair.publicKey,\n ]);\n\n if (!creatorEnvelope) {\n throw new Error(\"Failed to wrap group key for creator\");\n }\n\n memberEnvelopes.push({\n userId: input.signerUserId,\n memberKeyFingerprint: creatorFingerprint,\n kemCipherText: bytesToBase64(creatorEnvelope.kemCipherText),\n wrappedKey: bytesToBase64(creatorEnvelope.wrappedKey),\n });\n }\n const name = input.name.trim();\n // A name is compared by canonical key but displayed raw, so an invisible\n // code point would let one signed name render as another. Refuse them\n // where the name is signed.\n if (name.length === 0 || hasForbiddenGroupNameCharacter(name)) {\n throw new Error(\n \"Group names must be non-empty and contain no control, format, or surrogate characters\",\n );\n }\n const payloadCiphertext = input.builtinRole\n ? encodeBuiltinGroupMetadata(input.builtinRole)\n : input.metadataKey\n ? await encryptGroupMetadata({\n key: input.metadataKey,\n groupId: input.groupId,\n name,\n })\n : (() => {\n throw new Error(\"Group metadata encryption context is unavailable\");\n })();\n const policyRequest = await signedGroupPolicyRequest({\n encapsulationPublicKey: bytesToBase64(groupKem.publicKey),\n externalAuthority: input.externalAuthority ?? null,\n keyEpoch: 1,\n keyFingerprint: await toFingerprint(groupKem.publicKey),\n grants: input.grants ?? [],\n memberEnvelopes,\n payloadCiphertext,\n principalId: input.groupId,\n projection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n\n return {\n groupId: input.groupId,\n initialGroupPolicy: policyRequest,\n };\n}\n\n/**\n * Members at bootstrap holds the registering user alone.\n *\n * It used to also contain the Admins group as a nested member, so that admins\n * were implicitly members. Principals contain only users now, so an admin is an\n * ordinary Members entry — and bootstrap has exactly one user, who is that\n * admin.\n */\nexport async function buildInitialMemberGroupPolicyRequest(input: {\n readonly creatorEncapsulationKeyPair: EncapsulationKeyPair;\n readonly groupId: string;\n readonly grants?: readonly PrincipalContainerGrant[] | undefined;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<CreateOrganizationGroupRequest> {\n return buildInitialGroupPolicyRequest({\n ...input,\n name: \"Members\",\n builtinRole: \"members\",\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"principalPolicyRequest.js","sourceRoot":"","sources":["principalPolicyRequest.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n buildPrincipalStateSigningInput,\n type EncapsulationKeyPair,\n encodeBuiltinGroupMetadata,\n encryptGroupMetadata,\n type GroupMetadataKey,\n generateKemSeedAndKeyPair,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n type PrincipalContainerGrant,\n type PrincipalPolicyExternalAuthority,\n readGroupMetadata,\n type SigningKeyPair,\n signPrincipalState,\n toFingerprint,\n wrapDekForRecipients,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type {\n CreateOrganizationGroupRequest,\n PrincipalMemberEnvelopeRequest,\n PrincipalProjectionMemberRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\n\ninterface BuildInitialGroupPolicyInput {\n readonly creatorEncapsulationKeyPair: EncapsulationKeyPair;\n readonly externalAuthority?:\n | PrincipalPolicyExternalAuthority[\"currentHead\"]\n | null;\n readonly groupId: string;\n readonly grants?: readonly PrincipalContainerGrant[] | undefined;\n readonly includeSignerAsAdmin?: boolean;\n readonly name: string;\n readonly metadataKey?: GroupMetadataKey;\n readonly builtinRole?: \"admins\" | \"members\";\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}\n\nexport function userProjectionMember(\n userId: string,\n role: \"member\" | \"admin\",\n): PrincipalProjectionMemberRequest {\n return { userId: userId, role };\n}\n\nfunction projectionToStateMembers(\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n) {\n return projection.map((member) => ({ userId: member.userId }));\n}\n\n/**\n * Code points that must never appear in a group name: control and format\n * characters (bidi overrides, zero-width joiners, newlines), lone surrogates\n * (re-encoded as U+FFFD when signed, so the signed name would no longer match\n * the one sent to the server), and every other default-ignorable code point\n * (Hangul fillers, variation selectors), which render as nothing and would\n * let one name pass for another. A group name is an identifier here, so this\n * deliberately refuses ZWJ emoji sequences as well. One predicate serves the\n * signing-time and the share-time refusal so the two cannot drift.\n */\nfunction hasForbiddenGroupNameCharacter(name: string): boolean {\n return /[\\p{Cc}\\p{Cf}\\p{Cs}\\p{Default_Ignorable_Code_Point}]/u.test(name);\n}\n\n/**\n * The comparison key for a group display name: width- and compatibility-\n * normalized, stripped of control, format, and default-ignorable characters,\n * whitespace-collapsed, and case-folded. Two names that a user cannot tell\n * apart in a picker must compare equal, or a look-alike name would slip past\n * the share-time binding. Cross-script homoglyphs (Latin \"A\" against Greek\n * \"Α\") are not folded: that needs the UTS #39 confusables table, and both\n * names would still have to be signed groups the organization's own admins\n * created.\n */\nexport function canonicalGroupNameKey(name: string): string {\n return (\n name\n .normalize(\"NFKC\")\n .replace(/[\\p{Cc}\\p{Cf}\\p{Default_Ignorable_Code_Point}]/gu, \"\")\n .replace(/\\s+/gu, \" \")\n .trim()\n .toLocaleLowerCase(\"en-US\")\n // Case folding can leave the string un-normalized (U+0130 lowercases to\n // \"i\" plus a combining dot), so normalize once more after it.\n .normalize(\"NFKC\")\n );\n}\n\ntype GroupPolicyNameInput = Pick<\n PrincipalPolicyBundleResponse,\n \"currentState\" | \"currentPayload\"\n>;\n\nexport type GroupPolicyNameReader = (\n bundle: GroupPolicyNameInput,\n) => Promise<string>;\n\n/** Read only after the policy and its organization-directory binding verify. */\nexport async function readGroupPolicyPayloadName(\n bundle: GroupPolicyNameInput,\n readEncryptedName?: GroupPolicyNameReader,\n): Promise<string> {\n const metadata = readGroupMetadata(bundle.currentPayload.ciphertext);\n if (\"role\" in metadata)\n return metadata.role === \"admins\" ? \"Admins\" : \"Members\";\n if (!readEncryptedName)\n throw new Error(\"Group metadata decryption context is unavailable\");\n return readEncryptedName(bundle);\n}\n\n/** One binding predicate for every operation selected by a read-model label. */\nexport async function groupPolicyNameMismatch(\n bundle: GroupPolicyNameInput,\n expectedGroupName: string,\n readEncryptedName?: GroupPolicyNameReader,\n): Promise<\"forbidden_characters\" | \"name_mismatch\" | null> {\n if (hasForbiddenGroupNameCharacter(expectedGroupName)) {\n return \"forbidden_characters\";\n }\n const signedName = await readGroupPolicyPayloadName(\n bundle,\n readEncryptedName,\n );\n if (hasForbiddenGroupNameCharacter(signedName)) return \"forbidden_characters\";\n return canonicalGroupNameKey(signedName) ===\n canonicalGroupNameKey(expectedGroupName)\n ? null\n : \"name_mismatch\";\n}\n\nexport async function signedGroupPolicyRequest(input: {\n readonly currentPolicy?: Pick<PrincipalPolicyBundleResponse, \"currentState\">;\n readonly encapsulationPublicKey: string;\n readonly externalAuthority:\n | PrincipalPolicyExternalAuthority[\"currentHead\"]\n | null;\n readonly keyEpoch: number;\n readonly keyFingerprint: string;\n readonly grants: ReadonlyArray<PrincipalContainerGrant>;\n readonly memberEnvelopes: ReadonlyArray<PrincipalMemberEnvelopeRequest>;\n readonly payloadCiphertext: string;\n readonly principalId: string;\n readonly projection: ReadonlyArray<PrincipalProjectionMemberRequest>;\n readonly signedAt: string;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<PutPrincipalPolicyRequest> {\n const projection = normalizePrincipalProjectionMembers(input.projection);\n const grants = normalizePrincipalContainerGrants(input.grants);\n const payloadCiphertext = input.payloadCiphertext;\n const state = await signPrincipalState(\n await buildPrincipalStateSigningInput({\n principalType: \"group\",\n principalId: input.principalId,\n version: input.currentPolicy\n ? input.currentPolicy.currentState.version + 1\n : 1,\n prevStateHash: input.currentPolicy?.currentState.stateHash ?? null,\n keyEpoch: input.keyEpoch,\n encapsulationPublicKey: input.encapsulationPublicKey,\n keyFingerprint: input.keyFingerprint,\n members: projectionToStateMembers(projection),\n memberEnvelopes: [...input.memberEnvelopes],\n projection,\n grants,\n payloadCiphertext,\n externalAuthority: input.externalAuthority,\n signedAt: input.signedAt,\n signerUserId: input.signerUserId,\n signerUserKeyFingerprint: input.signingFingerprint,\n }),\n input.signingKeyPair.signingPrivateKey,\n );\n\n return {\n state,\n encryptedPayload: {\n cipherSuite: \"aes-256-gcm\",\n ciphertext: payloadCiphertext,\n ciphertextHash: state.payloadCiphertextHash,\n },\n projection,\n grants,\n memberEnvelopes: [...input.memberEnvelopes],\n };\n}\n\nexport async function buildInitialGroupPolicyRequest(\n input: BuildInitialGroupPolicyInput,\n): Promise<CreateOrganizationGroupRequest> {\n const groupKem = generateKemSeedAndKeyPair();\n const withSigner = input.includeSignerAsAdmin ?? true;\n const projection = withSigner\n ? [userProjectionMember(input.signerUserId, \"admin\")]\n : [];\n const memberEnvelopes: PrincipalMemberEnvelopeRequest[] = [];\n\n if (withSigner) {\n const creatorFingerprint = await toFingerprint(\n input.creatorEncapsulationKeyPair.publicKey,\n );\n const [creatorEnvelope] = await wrapDekForRecipients(groupKem.secretKey, [\n input.creatorEncapsulationKeyPair.publicKey,\n ]);\n\n if (!creatorEnvelope) {\n throw new Error(\"Failed to wrap group key for creator\");\n }\n\n memberEnvelopes.push({\n userId: input.signerUserId,\n memberKeyFingerprint: creatorFingerprint,\n kemCipherText: bytesToBase64(creatorEnvelope.kemCipherText),\n wrappedKey: bytesToBase64(creatorEnvelope.wrappedKey),\n });\n }\n const name = input.name.trim();\n // A name is compared by canonical key but displayed raw, so an invisible\n // code point would let one signed name render as another. Refuse them\n // where the name is signed.\n if (name.length === 0 || hasForbiddenGroupNameCharacter(name)) {\n throw new Error(\n \"Group names must be non-empty and contain no control, format, or surrogate characters\",\n );\n }\n const payloadCiphertext = input.builtinRole\n ? encodeBuiltinGroupMetadata(input.builtinRole)\n : input.metadataKey\n ? await encryptGroupMetadata({\n key: input.metadataKey,\n groupId: input.groupId,\n name,\n })\n : (() => {\n throw new Error(\"Group metadata encryption context is unavailable\");\n })();\n const policyRequest = await signedGroupPolicyRequest({\n encapsulationPublicKey: bytesToBase64(groupKem.publicKey),\n externalAuthority: input.externalAuthority ?? null,\n keyEpoch: 1,\n keyFingerprint: await toFingerprint(groupKem.publicKey),\n grants: input.grants ?? [],\n memberEnvelopes,\n payloadCiphertext,\n principalId: input.groupId,\n projection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n\n return {\n groupId: input.groupId,\n initialGroupPolicy: policyRequest,\n };\n}\n\n/**\n * Members at bootstrap holds the registering user alone.\n *\n * It used to also contain the Admins group as a nested member, so that admins\n * were implicitly members. Principals contain only users now, so an admin is an\n * ordinary Members entry — and bootstrap has exactly one user, who is that\n * admin.\n */\nexport async function buildInitialMemberGroupPolicyRequest(input: {\n readonly creatorEncapsulationKeyPair: EncapsulationKeyPair;\n readonly groupId: string;\n readonly grants?: readonly PrincipalContainerGrant[] | undefined;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<CreateOrganizationGroupRequest> {\n return buildInitialGroupPolicyRequest({\n ...input,\n name: \"Members\",\n builtinRole: \"members\",\n });\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type VerifiedPrincipalPolicyCurrent } from "../../internal/crypto/index.js";
|
|
2
|
+
import type { PutPrincipalPolicyRequest } from "../../internal/validators/request/index.js";
|
|
3
|
+
import type { PrincipalPolicyMutationResponse } from "../../internal/validators/response/index.js";
|
|
4
|
+
import { type AcknowledgedPrincipalCurrentRetirement } from "../../data/persistence/principalCurrentAcknowledgementPersistence.js";
|
|
5
|
+
import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
|
|
6
|
+
import type { RecoverPrincipalPolicyHistoryOptions } from "../principals/principalHistoryRecoveryTypes.js";
|
|
7
|
+
export type { AcknowledgedPrincipalCurrentRetirement } from "../../data/persistence/principalCurrentAcknowledgementPersistence.js";
|
|
8
|
+
export interface AcknowledgedPrincipalCurrentInput {
|
|
9
|
+
/** The same scoped protection and verification mode used to recover the predecessor. */
|
|
10
|
+
readonly recovery: Omit<RecoverPrincipalPolicyHistoryOptions, "execSql" | "organizationId" | "stillCurrent">;
|
|
11
|
+
readonly request: PutPrincipalPolicyRequest;
|
|
12
|
+
readonly response: PrincipalPolicyMutationResponse;
|
|
13
|
+
}
|
|
14
|
+
/** Extend authenticated local progress and retain exact acknowledged artifacts atomically with pins. */
|
|
15
|
+
export declare function retainAcknowledgedPrincipalCurrents(input: {
|
|
16
|
+
readonly execSql: ExecSql;
|
|
17
|
+
readonly organizationId: string;
|
|
18
|
+
readonly entries: readonly AcknowledgedPrincipalCurrentInput[];
|
|
19
|
+
readonly retirements?: readonly AcknowledgedPrincipalCurrentRetirement[] | undefined;
|
|
20
|
+
readonly stillCurrent: () => boolean;
|
|
21
|
+
}): Promise<VerifiedPrincipalPolicyCurrent[]>;
|