@tearleads/client-sdk 0.1.57 → 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/index.d.ts +4 -4
- package/index.js +2 -2
- package/index.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/currentOrganizationMutationRetention.js +1 -1
- package/workflows/organizations/currentOrganizationMutationRetention.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/index.d.ts +0 -1
- package/workflows/organizations/index.js +0 -1
- package/workflows/organizations/index.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/retainAcknowledgedPrincipalCurrents.d.ts +4 -24
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +13 -133
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
- package/workflows/organizations/rosterProfileContainer.js +1 -1
- package/workflows/organizations/rosterProfileContainer.js.map +1 -1
- package/workflows/organizations/runtimeCurrentGroupMutation.js +1 -1
- package/workflows/organizations/runtimeCurrentGroupMutation.js.map +1 -1
- package/workflows/principals/acknowledgedPrincipalCurrents.d.ts +33 -0
- package/workflows/principals/acknowledgedPrincipalCurrents.js +140 -0
- package/workflows/principals/acknowledgedPrincipalCurrents.js.map +1 -0
- package/workflows/{organizations → principals}/acknowledgedPrincipalPredecessor.d.ts +1 -1
- package/workflows/{organizations → principals}/acknowledgedPrincipalPredecessor.js +1 -1
- package/workflows/principals/acknowledgedPrincipalPredecessor.js.map +1 -0
- package/workflows/principals/index.d.ts +1 -0
- package/workflows/principals/index.js +1 -0
- package/workflows/principals/index.js.map +1 -1
- package/workflows/{organizations → principals}/initialPrincipalCurrentPublication.js +5 -7
- package/workflows/principals/initialPrincipalCurrentPublication.js.map +1 -0
- 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/principalAcknowledgementChecks.d.ts +30 -0
- package/workflows/principals/principalAcknowledgementChecks.js +2 -0
- package/workflows/principals/principalAcknowledgementChecks.js.map +1 -0
- package/workflows/{organizations → principals}/principalCurrentPublicationSeal.js.map +1 -1
- package/workflows/{organizations → principals}/reconcileAcknowledgedPrincipalCurrent.js +2 -2
- package/workflows/principals/reconcileAcknowledgedPrincipalCurrent.js.map +1 -0
- 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/workflows/organizations/acknowledgedPrincipalPredecessor.js.map +0 -1
- package/workflows/organizations/initialPrincipalCurrentPublication.js.map +0 -1
- package/workflows/organizations/reconcileAcknowledgedPrincipalCurrent.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
- /package/workflows/{organizations → principals}/principalCurrentPublicationSeal.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationReadModels.js","sourceRoot":"","sources":["organizationReadModels.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DomainScope } from \"../../data/domainScope\";\nimport {\n loadLocalOrganizationContainerGrants,\n loadLocalOrganizationDirectoryAndGroups,\n loadLocalOrganizationGroupContainers,\n loadLocalOrganizationGroupMembers,\n loadLocalOrganizationUserDetail,\n type OrganizationContainerGrants,\n type OrganizationDirectoryAndGroups,\n type OrganizationGroupContainers,\n type OrganizationGroupMembers,\n type OrganizationGroupPolicyHistory,\n type OrganizationPolicyHistory,\n type OrganizationUserDetail,\n reconcileOrganizationDirectoryAndGroups,\n} from \"../../workflows/organizations\";\nimport {\n organizationAccessScopeKey,\n wasOrganizationPresentationAccessDeniedByServer,\n} from \"../../workflows/organizations/organizationPresentationAccessState\";\nimport type { InternalRuntime } from \"../workflowRuntime\";\nimport { recoverOrganizationAccess } from \"./organizationAccessRestoration\";\nimport { loadBoundedOrganizationGroupHistory } from \"./organizationGroupHistory\";\nimport { hydrateOrganizationGroupNamesForRuntime } from \"./organizationGroupNameHydration\";\nimport { loadBoundedOrganizationHistory } from \"./organizationHistory\";\nimport {\n type ActiveOrganizationDataRuntime,\n activeOrganizationDataRuntime,\n isOrganizationDataRuntimeCurrent,\n} from \"./organizationWorkflowRuntime\";\n\nconst coordinatorsByRuntime = new WeakMap<\n InternalRuntime,\n OrganizationReadModelCoordinator\n>();\n\nexport interface OrganizationReadModelCoordinator {\n loadLocal(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null>;\n loadLocalGroupMembers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupMembers | null>;\n loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationGroupPolicyHistory | null>;\n loadOrganizationPolicyHistory(\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationPolicyHistory | null>;\n loadLocalGrants(\n organizationId?: string | undefined,\n ): Promise<OrganizationContainerGrants | null>;\n loadLocalGroupContainers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupContainers | null>;\n loadLocalUserDetail(\n userId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationUserDetail | null>;\n /**\n * Resolves `undefined` when the runtime declines without I/O (offline,\n * database not ready, organization mismatch) or when the feed failed with\n * no locally retained projection — passes that must not count as caught\n * up; `null` when the reconcile completed but produced nothing presentable\n * — including an authoritative denial that purged the projection, which\n * consumers must repaint.\n */\n reconcile(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n reconcileAfterMutation(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n}\n\nclass OrganizationReadModelCoordinatorImpl\n implements OrganizationReadModelCoordinator\n{\n private readonly reconciliationsByScope = new WeakMap<\n DomainScope,\n Map<string, Promise<OrganizationDirectoryAndGroups | null | undefined>>\n >();\n constructor(private readonly runtimeService: InternalRuntime) {}\n\n private reconciliationMap(active: ActiveOrganizationDataRuntime) {\n const scope = active.runtime.state.domainScope;\n let byKey = this.reconciliationsByScope.get(scope);\n if (!byKey) {\n byKey = new Map();\n this.reconciliationsByScope.set(scope, byKey);\n }\n return byKey;\n }\n\n async loadLocal(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return loadLocalOrganizationDirectoryAndGroups({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGrants(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return loadLocalOrganizationContainerGrants({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupContainers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupContainers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupMembers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupMembers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationGroupHistory({\n active,\n groupId,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadOrganizationPolicyHistory(\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) return null;\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationHistory({\n active,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadLocalUserDetail(userId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || userId.length === 0) {\n return null;\n }\n return loadLocalOrganizationUserDetail({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n userId,\n });\n }\n\n reconcile(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return Promise.resolve(undefined);\n }\n\n const byKey = this.reconciliationMap(active);\n const key = organizationAccessScopeKey(\n active.organizationId,\n active.userId,\n );\n const existing = byKey.get(key);\n if (existing) {\n return existing;\n }\n\n // Snapshot the server-denied flag before reconciling. A reconcile that\n // flips it back to readable means org access was just restored (e.g. the\n // user was re-added to a group), and any write lanes idled by\n // permission-denied submissions have no self re-arm — regaining access is\n // their retry signal, mirroring how billing recovery re-requests all\n // lanes. Only a genuine server denial counts: a local session reset also\n // marks scopes denied, and re-arming on its first reconcile would race the\n // startup sync passes (e.g. pending-create adoption between panes).\n const accessWasDenied = wasOrganizationPresentationAccessDeniedByServer(\n {\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n requesterUserId: active.userId,\n },\n \"readModel\",\n );\n const domainScope = active.runtime.state.domainScope;\n const stillCurrent = () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n );\n\n const reconciliation = reconcileOrganizationDirectoryAndGroups({\n apiClient: active.runtime.apiClient,\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n logError: active.runtime.util.logError,\n organizationId: active.organizationId,\n })\n .then(async (directoryAndGroups) => {\n if (!stillCurrent()) return null;\n // Feed success restores retry eligibility even if name decryption fails.\n const accessWasRestored =\n accessWasDenied &&\n directoryAndGroups !== null &&\n directoryAndGroups !== undefined;\n if (accessWasRestored)\n await recoverOrganizationAccess({\n active,\n domainScope,\n stillCurrent,\n });\n if (!stillCurrent()) return null;\n return hydrateOrganizationGroupNamesForRuntime(\n this.runtimeService,\n active,\n domainScope,\n directoryAndGroups,\n );\n })\n .finally(() => {\n if (byKey.get(key) === reconciliation) {\n byKey.delete(key);\n }\n });\n byKey.set(key, reconciliation);\n return reconciliation;\n }\n\n async reconcileAfterMutation(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return undefined;\n }\n const existing = this.reconciliationMap(active).get(\n organizationAccessScopeKey(active.organizationId, active.userId),\n );\n if (existing) {\n await existing.catch(() => null);\n }\n return this.reconcile(active.organizationId);\n }\n}\n\nexport function createOrganizationReadModelCoordinator(\n runtimeService: InternalRuntime,\n): OrganizationReadModelCoordinator {\n const existing = coordinatorsByRuntime.get(runtimeService);\n if (existing) {\n return existing;\n }\n\n const coordinator = new OrganizationReadModelCoordinatorImpl(runtimeService);\n coordinatorsByRuntime.set(runtimeService, coordinator);\n return coordinator;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organizationReadModels.js","sourceRoot":"","sources":["organizationReadModels.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DomainScope } from \"../../data/shared/domainScope\";\nimport {\n loadLocalOrganizationContainerGrants,\n loadLocalOrganizationDirectoryAndGroups,\n loadLocalOrganizationGroupContainers,\n loadLocalOrganizationGroupMembers,\n loadLocalOrganizationUserDetail,\n type OrganizationContainerGrants,\n type OrganizationDirectoryAndGroups,\n type OrganizationGroupContainers,\n type OrganizationGroupMembers,\n type OrganizationGroupPolicyHistory,\n type OrganizationPolicyHistory,\n type OrganizationUserDetail,\n reconcileOrganizationDirectoryAndGroups,\n} from \"../../workflows/organizations\";\nimport {\n organizationAccessScopeKey,\n wasOrganizationPresentationAccessDeniedByServer,\n} from \"../../workflows/organizations/organizationPresentationAccessState\";\nimport type { InternalRuntime } from \"../workflowRuntime\";\nimport { recoverOrganizationAccess } from \"./organizationAccessRestoration\";\nimport { loadBoundedOrganizationGroupHistory } from \"./organizationGroupHistory\";\nimport { hydrateOrganizationGroupNamesForRuntime } from \"./organizationGroupNameHydration\";\nimport { loadBoundedOrganizationHistory } from \"./organizationHistory\";\nimport {\n type ActiveOrganizationDataRuntime,\n activeOrganizationDataRuntime,\n isOrganizationDataRuntimeCurrent,\n} from \"./organizationWorkflowRuntime\";\n\nconst coordinatorsByRuntime = new WeakMap<\n InternalRuntime,\n OrganizationReadModelCoordinator\n>();\n\nexport interface OrganizationReadModelCoordinator {\n loadLocal(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null>;\n loadLocalGroupMembers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupMembers | null>;\n loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationGroupPolicyHistory | null>;\n loadOrganizationPolicyHistory(\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationPolicyHistory | null>;\n loadLocalGrants(\n organizationId?: string | undefined,\n ): Promise<OrganizationContainerGrants | null>;\n loadLocalGroupContainers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupContainers | null>;\n loadLocalUserDetail(\n userId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationUserDetail | null>;\n /**\n * Resolves `undefined` when the runtime declines without I/O (offline,\n * database not ready, organization mismatch) or when the feed failed with\n * no locally retained projection — passes that must not count as caught\n * up; `null` when the reconcile completed but produced nothing presentable\n * — including an authoritative denial that purged the projection, which\n * consumers must repaint.\n */\n reconcile(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n reconcileAfterMutation(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n}\n\nclass OrganizationReadModelCoordinatorImpl\n implements OrganizationReadModelCoordinator\n{\n private readonly reconciliationsByScope = new WeakMap<\n DomainScope,\n Map<string, Promise<OrganizationDirectoryAndGroups | null | undefined>>\n >();\n constructor(private readonly runtimeService: InternalRuntime) {}\n\n private reconciliationMap(active: ActiveOrganizationDataRuntime) {\n const scope = active.runtime.state.domainScope;\n let byKey = this.reconciliationsByScope.get(scope);\n if (!byKey) {\n byKey = new Map();\n this.reconciliationsByScope.set(scope, byKey);\n }\n return byKey;\n }\n\n async loadLocal(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return loadLocalOrganizationDirectoryAndGroups({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGrants(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return loadLocalOrganizationContainerGrants({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupContainers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupContainers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupMembers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupMembers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationGroupHistory({\n active,\n groupId,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadOrganizationPolicyHistory(\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) return null;\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationHistory({\n active,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadLocalUserDetail(userId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || userId.length === 0) {\n return null;\n }\n return loadLocalOrganizationUserDetail({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n userId,\n });\n }\n\n reconcile(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return Promise.resolve(undefined);\n }\n\n const byKey = this.reconciliationMap(active);\n const key = organizationAccessScopeKey(\n active.organizationId,\n active.userId,\n );\n const existing = byKey.get(key);\n if (existing) {\n return existing;\n }\n\n // Snapshot the server-denied flag before reconciling. A reconcile that\n // flips it back to readable means org access was just restored (e.g. the\n // user was re-added to a group), and any write lanes idled by\n // permission-denied submissions have no self re-arm — regaining access is\n // their retry signal, mirroring how billing recovery re-requests all\n // lanes. Only a genuine server denial counts: a local session reset also\n // marks scopes denied, and re-arming on its first reconcile would race the\n // startup sync passes (e.g. pending-create adoption between panes).\n const accessWasDenied = wasOrganizationPresentationAccessDeniedByServer(\n {\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n requesterUserId: active.userId,\n },\n \"readModel\",\n );\n const domainScope = active.runtime.state.domainScope;\n const stillCurrent = () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n );\n\n const reconciliation = reconcileOrganizationDirectoryAndGroups({\n apiClient: active.runtime.apiClient,\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n logError: active.runtime.util.logError,\n organizationId: active.organizationId,\n })\n .then(async (directoryAndGroups) => {\n if (!stillCurrent()) return null;\n // Feed success restores retry eligibility even if name decryption fails.\n const accessWasRestored =\n accessWasDenied &&\n directoryAndGroups !== null &&\n directoryAndGroups !== undefined;\n if (accessWasRestored)\n await recoverOrganizationAccess({\n active,\n domainScope,\n stillCurrent,\n });\n if (!stillCurrent()) return null;\n return hydrateOrganizationGroupNamesForRuntime(\n this.runtimeService,\n active,\n domainScope,\n directoryAndGroups,\n );\n })\n .finally(() => {\n if (byKey.get(key) === reconciliation) {\n byKey.delete(key);\n }\n });\n byKey.set(key, reconciliation);\n return reconciliation;\n }\n\n async reconcileAfterMutation(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return undefined;\n }\n const existing = this.reconciliationMap(active).get(\n organizationAccessScopeKey(active.organizationId, active.userId),\n );\n if (existing) {\n await existing.catch(() => null);\n }\n return this.reconcile(active.organizationId);\n }\n}\n\nexport function createOrganizationReadModelCoordinator(\n runtimeService: InternalRuntime,\n): OrganizationReadModelCoordinator {\n const existing = coordinatorsByRuntime.get(runtimeService);\n if (existing) {\n return existing;\n }\n\n const coordinator = new OrganizationReadModelCoordinatorImpl(runtimeService);\n coordinatorsByRuntime.set(runtimeService, coordinator);\n return coordinator;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationWorkflowRuntime.js","sourceRoot":"","sources":["organizationWorkflowRuntime.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,2BAA2B,CACzC,OAAqC;IAErC,OAAO,OAAO,CAAC,IAAI,CAAC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,eAAe;QAChE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc;QAC7B,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,cAA+B,EAC/B,QAAiC,EACjC,oBAA6B;IAE7B,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,EAAE,CAAC;IAC/C,MAAM,oBAAoB,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAClE,MAAM,cAAc,GAClB,oBAAoB,KAAK,SAAS;QAChC,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,oBAAoB,CAAC;IAC3B,IAAI,CAAC,oBAAoB,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,QAAQ,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;AACpE,CAAC;AAQD,MAAM,UAAU,6BAA6B,CAC3C,cAA+B,EAC/B,sBAA+B;IAE/B,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,EAAE,CAAC;IAC/C,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;IACnC,IACE,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe;QAC7B,CAAC,cAAc;QACf,CAAC,MAAM;QACP,OAAO,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO;QAClC,CAAC,sBAAsB,KAAK,SAAS;YACnC,cAAc,KAAK,sBAAsB,CAAC,EAC5C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,cAA+B,EAC/B,MAAqC,EACrC,WAAwB;IAExB,MAAM,OAAO,GAAG,6BAA6B,CAC3C,cAAc,EACd,MAAM,CAAC,cAAc,CACtB,CAAC;IACF,OAAO,CACL,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM;QACjC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9D,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAClD,CAAC;AACJ,CAAC","sourcesContent":["import type { DomainScope } from \"../../data/domainScope\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../workflowRuntime\";\n\ntype OrganizationWorkflow<T> = (input: {\n readonly apiClient: InternalWorkflowRuntimeInput[\"apiClient\"];\n readonly organizationId: string;\n}) => Promise<T>;\n\nexport function authenticatedOrganizationId(\n runtime: InternalWorkflowRuntimeInput,\n): string | null {\n return runtime.auth.organizationId && runtime.auth.isAuthenticated\n ? runtime.auth.organizationId\n : null;\n}\n\nexport function runForOrganization<T>(\n runtimeService: InternalRuntime,\n workflow: OrganizationWorkflow<T>,\n targetOrganizationId?: string,\n): Promise<T | null> {\n const runtime = runtimeService.workflowInput();\n const activeOrganizationId = authenticatedOrganizationId(runtime);\n const organizationId =\n targetOrganizationId === undefined\n ? activeOrganizationId\n : targetOrganizationId;\n if (!activeOrganizationId || !organizationId) {\n return Promise.resolve(null);\n }\n\n return workflow({ apiClient: runtime.apiClient, organizationId });\n}\n\nexport interface ActiveOrganizationDataRuntime {\n readonly runtime: InternalWorkflowRuntimeInput;\n readonly organizationId: string;\n readonly userId: string;\n}\n\nexport function activeOrganizationDataRuntime(\n runtimeService: InternalRuntime,\n expectedOrganizationId?: string,\n): ActiveOrganizationDataRuntime | null {\n const runtime = runtimeService.workflowInput();\n const organizationId = runtime.auth.organizationId;\n const userId = runtime.auth.userId;\n if (\n !runtime.auth.isAuthenticated ||\n !organizationId ||\n !userId ||\n runtime.infra.dbStatus !== \"ready\" ||\n (expectedOrganizationId !== undefined &&\n organizationId !== expectedOrganizationId)\n ) {\n return null;\n }\n\n return { runtime, organizationId, userId };\n}\n\nexport function isOrganizationDataRuntimeCurrent(\n runtimeService: InternalRuntime,\n active: ActiveOrganizationDataRuntime,\n domainScope: DomainScope,\n): boolean {\n const current = activeOrganizationDataRuntime(\n runtimeService,\n active.organizationId,\n );\n return (\n current?.userId === active.userId &&\n current.runtime.infra.execSql === active.runtime.infra.execSql &&\n current.runtime.state.domainScope === domainScope\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organizationWorkflowRuntime.js","sourceRoot":"","sources":["organizationWorkflowRuntime.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,2BAA2B,CACzC,OAAqC;IAErC,OAAO,OAAO,CAAC,IAAI,CAAC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,eAAe;QAChE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc;QAC7B,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,cAA+B,EAC/B,QAAiC,EACjC,oBAA6B;IAE7B,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,EAAE,CAAC;IAC/C,MAAM,oBAAoB,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAClE,MAAM,cAAc,GAClB,oBAAoB,KAAK,SAAS;QAChC,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,oBAAoB,CAAC;IAC3B,IAAI,CAAC,oBAAoB,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,QAAQ,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;AACpE,CAAC;AAQD,MAAM,UAAU,6BAA6B,CAC3C,cAA+B,EAC/B,sBAA+B;IAE/B,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,EAAE,CAAC;IAC/C,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;IACnC,IACE,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe;QAC7B,CAAC,cAAc;QACf,CAAC,MAAM;QACP,OAAO,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO;QAClC,CAAC,sBAAsB,KAAK,SAAS;YACnC,cAAc,KAAK,sBAAsB,CAAC,EAC5C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,cAA+B,EAC/B,MAAqC,EACrC,WAAwB;IAExB,MAAM,OAAO,GAAG,6BAA6B,CAC3C,cAAc,EACd,MAAM,CAAC,cAAc,CACtB,CAAC;IACF,OAAO,CACL,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM;QACjC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9D,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAClD,CAAC;AACJ,CAAC","sourcesContent":["import type { DomainScope } from \"../../data/shared/domainScope\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../workflowRuntime\";\n\ntype OrganizationWorkflow<T> = (input: {\n readonly apiClient: InternalWorkflowRuntimeInput[\"apiClient\"];\n readonly organizationId: string;\n}) => Promise<T>;\n\nexport function authenticatedOrganizationId(\n runtime: InternalWorkflowRuntimeInput,\n): string | null {\n return runtime.auth.organizationId && runtime.auth.isAuthenticated\n ? runtime.auth.organizationId\n : null;\n}\n\nexport function runForOrganization<T>(\n runtimeService: InternalRuntime,\n workflow: OrganizationWorkflow<T>,\n targetOrganizationId?: string,\n): Promise<T | null> {\n const runtime = runtimeService.workflowInput();\n const activeOrganizationId = authenticatedOrganizationId(runtime);\n const organizationId =\n targetOrganizationId === undefined\n ? activeOrganizationId\n : targetOrganizationId;\n if (!activeOrganizationId || !organizationId) {\n return Promise.resolve(null);\n }\n\n return workflow({ apiClient: runtime.apiClient, organizationId });\n}\n\nexport interface ActiveOrganizationDataRuntime {\n readonly runtime: InternalWorkflowRuntimeInput;\n readonly organizationId: string;\n readonly userId: string;\n}\n\nexport function activeOrganizationDataRuntime(\n runtimeService: InternalRuntime,\n expectedOrganizationId?: string,\n): ActiveOrganizationDataRuntime | null {\n const runtime = runtimeService.workflowInput();\n const organizationId = runtime.auth.organizationId;\n const userId = runtime.auth.userId;\n if (\n !runtime.auth.isAuthenticated ||\n !organizationId ||\n !userId ||\n runtime.infra.dbStatus !== \"ready\" ||\n (expectedOrganizationId !== undefined &&\n organizationId !== expectedOrganizationId)\n ) {\n return null;\n }\n\n return { runtime, organizationId, userId };\n}\n\nexport function isOrganizationDataRuntimeCurrent(\n runtimeService: InternalRuntime,\n active: ActiveOrganizationDataRuntime,\n domainScope: DomainScope,\n): boolean {\n const current = activeOrganizationDataRuntime(\n runtimeService,\n active.organizationId,\n );\n return (\n current?.userId === active.userId &&\n current.runtime.infra.execSql === active.runtime.infra.execSql &&\n current.runtime.state.domainScope === domainScope\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rootContainerAdoption.js","sourceRoot":"","sources":["rootContainerAdoption.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,yBAAyB,CACvC,YAA+C,EAC/C,KAAyC;IAEzC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;IACrC,IACE,YAAY,CAAC,cAAc,EAAE,KAAK,KAAK,CAAC,WAAW;QACnD,CAAC,OAAO,CAAC,eAAe;QACxB,OAAO,CAAC,cAAc,KAAK,KAAK,CAAC,cAAc;QAC/C,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAC/B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,CAAC,eAAe,EAAE,CAAC;QAClD,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,CAAC,mBAAmB,EAAE,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { DomainScope } from \"../data/domainScope\";\nimport type {\n ContainerContentsRootAdopter,\n ContainerContentsRootAdoptionInput,\n} from \"../workflows/container-contents/runtime\";\nimport type { Session } from \"./session/sessionTypes\";\n\ninterface RootContainerAdoptionDependencies {\n readonly getDomainScope: () => DomainScope;\n readonly session: Pick<\n Session,\n | \"containerId\"\n | \"isAuthenticated\"\n | \"organizationId\"\n | \"setContainerId\"\n | \"userId\"\n >;\n}\n\nexport function adoptSessionRootContainer(\n dependencies: RootContainerAdoptionDependencies,\n input: ContainerContentsRootAdoptionInput,\n): ReturnType<ContainerContentsRootAdopter> {\n const session = dependencies.session;\n if (\n dependencies.getDomainScope() !== input.domainScope ||\n !session.isAuthenticated ||\n session.organizationId !== input.organizationId ||\n session.userId !== input.userId\n ) {\n return false;\n }\n if (session.containerId === input.nextContainerId) {\n return \"already-adopted\";\n }\n if (session.containerId !== input.expectedContainerId) {\n return false;\n }\n\n session.setContainerId(input.nextContainerId);\n return true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rootContainerAdoption.js","sourceRoot":"","sources":["rootContainerAdoption.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,yBAAyB,CACvC,YAA+C,EAC/C,KAAyC;IAEzC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;IACrC,IACE,YAAY,CAAC,cAAc,EAAE,KAAK,KAAK,CAAC,WAAW;QACnD,CAAC,OAAO,CAAC,eAAe;QACxB,OAAO,CAAC,cAAc,KAAK,KAAK,CAAC,cAAc;QAC/C,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAC/B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,CAAC,eAAe,EAAE,CAAC;QAClD,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,CAAC,mBAAmB,EAAE,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { DomainScope } from \"../data/shared/domainScope\";\nimport type {\n ContainerContentsRootAdopter,\n ContainerContentsRootAdoptionInput,\n} from \"../workflows/container-contents/runtime\";\nimport type { Session } from \"./session/sessionTypes\";\n\ninterface RootContainerAdoptionDependencies {\n readonly getDomainScope: () => DomainScope;\n readonly session: Pick<\n Session,\n | \"containerId\"\n | \"isAuthenticated\"\n | \"organizationId\"\n | \"setContainerId\"\n | \"userId\"\n >;\n}\n\nexport function adoptSessionRootContainer(\n dependencies: RootContainerAdoptionDependencies,\n input: ContainerContentsRootAdoptionInput,\n): ReturnType<ContainerContentsRootAdopter> {\n const session = dependencies.session;\n if (\n dependencies.getDomainScope() !== input.domainScope ||\n !session.isAuthenticated ||\n session.organizationId !== input.organizationId ||\n session.userId !== input.userId\n ) {\n return false;\n }\n if (session.containerId === input.nextContainerId) {\n return \"already-adopted\";\n }\n if (session.containerId !== input.expectedContainerId) {\n return false;\n }\n\n session.setContainerId(input.nextContainerId);\n return true;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type KeyingVerificationError } from "../internal/crypto/index.js";
|
|
2
|
-
import type { SecurityIncident, SecurityIncidentContext, SecurityIncidentObjectKind, SecurityIncidentReporter } from "../data/securityIncidents.js";
|
|
2
|
+
import type { SecurityIncident, SecurityIncidentContext, SecurityIncidentObjectKind, SecurityIncidentReporter } from "../data/shared/securityIncidents.js";
|
|
3
3
|
import type { Database } from "./database.js";
|
|
4
4
|
export type { SecurityIncident, SecurityIncidentObjectKind };
|
|
5
5
|
export type SecurityIncidentListener = (incident: SecurityIncident) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"securityIncidents.js","sourceRoot":"","sources":["securityIncidents.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compareCanonicalStrings,\n isKeyingVerificationCode,\n type KeyingVerificationError,\n} from \"@tearleads/crypto\";\nimport { isKeyingVerificationError } from \"../data/keyingProjectionVerification/error\";\nimport {\n appendSecurityIncident,\n listSecurityIncidents,\n} from \"../data/persistence/securityIncidentPersistence\";\nimport type {\n SecurityIncident,\n SecurityIncidentContext,\n SecurityIncidentObjectKind,\n SecurityIncidentReporter,\n} from \"../data/securityIncidents\";\nimport type { Database } from \"./database\";\nimport { createListenerSet } from \"./listenerSet\";\n\nexport type { SecurityIncident, SecurityIncidentObjectKind };\n\nexport type SecurityIncidentListener = (incident: SecurityIncident) => void;\n\n/**\n * Where a reported incident ended up: `recorded` rows are durable in the local\n * ledger, `buffered` ones wait in memory for a retried write, and `failed`\n * ones were dropped, so only `recorded` justifies telling a user it was kept.\n * Hosts name it as `Awaited<ReturnType<SecurityIncidents[\"record\"]>>`.\n */\ntype SecurityIncidentRecordingStatus = \"buffered\" | \"failed\" | \"recorded\";\n\nconst MAX_BUFFERED_SECURITY_INCIDENTS = 100;\nconst MAX_EVIDENCE_HASH_COUNT = 32;\nconst MAX_EVIDENCE_HASH_KEY_LENGTH = 64;\nconst MAX_EVIDENCE_HASH_VALUE_LENGTH = 256;\nconst MAX_INCIDENT_IDENTIFIER_LENGTH = 256;\nconst MAX_INCIDENT_OPERATION_LENGTH = 128;\nconst SECURITY_INCIDENT_RETRY_DELAY_MS = 250;\nconst SECURITY_INCIDENT_MAX_RETRY_DELAY_MS = 30_000;\n\nexport interface SecurityIncidents {\n /** Returns null while the local database is unavailable. */\n list(): Promise<ReadonlyArray<SecurityIncident> | null>;\n /**\n * Durably record a terminal verification failure the host detected itself,\n * such as conflicting purge proofs found while merging a local backup. The\n * report is redacted, coalesced, retained, and buffered exactly like an\n * SDK-detected incident; one error instance is recorded at most once, and\n * repeats of it resolve with the status of the first report.\n */\n record(\n error: KeyingVerificationError,\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus>;\n subscribe(listener: SecurityIncidentListener): () => void;\n}\n\ninterface SecurityIncidentServiceOptions {\n readonly database: Database;\n readonly logError: (message: string | Error, cause?: unknown) => void;\n readonly onIncident?: SecurityIncidentListener | undefined;\n readonly trustDomain: string | null;\n}\n\ninterface SecurityIncidentServiceResult {\n readonly dispose: () => void;\n readonly incidents: SecurityIncidents;\n readonly report: SecurityIncidentReporter;\n}\n\nfunction verificationCode(error: unknown): SecurityIncident[\"code\"] | null {\n if (!isKeyingVerificationError(error)) return null;\n const code = Reflect.get(error, \"code\");\n return isKeyingVerificationCode(code)\n ? code\n : \"unrecognized_verification_code\";\n}\n\ninterface RedactedIncident {\n readonly code: SecurityIncident[\"code\"];\n readonly context: SecurityIncidentContext;\n readonly detectedAt: string;\n readonly lastDetectedAt: string;\n readonly occurrenceCount: number;\n}\n\nfunction boundIncidentText(value: string, maxLength: number): string {\n return value.slice(0, maxLength);\n}\n\nfunction boundNullableIncidentText(value: string | null): string | null {\n return value === null\n ? null\n : boundIncidentText(value, MAX_INCIDENT_IDENTIFIER_LENGTH);\n}\n\nfunction redactIncidentContext(\n context: SecurityIncidentContext,\n): SecurityIncidentContext {\n return {\n evidenceHashes: Object.fromEntries(\n Object.entries(context.evidenceHashes ?? {})\n .filter(\n ([key, value]) =>\n key.length > 0 &&\n key.length <= MAX_EVIDENCE_HASH_KEY_LENGTH &&\n value.length <= MAX_EVIDENCE_HASH_VALUE_LENGTH,\n )\n // Code-unit order: the retained keys feed the incident id hash, so\n // truncation must pick the same keys on every runtime and locale.\n .sort(([left], [right]) => compareCanonicalStrings(left, right))\n .slice(0, MAX_EVIDENCE_HASH_COUNT),\n ),\n objectId: boundNullableIncidentText(context.objectId),\n objectKind: context.objectKind,\n operation: boundIncidentText(\n context.operation,\n MAX_INCIDENT_OPERATION_LENGTH,\n ),\n organizationId: boundNullableIncidentText(context.organizationId ?? null),\n };\n}\n\nfunction redactedIncidentKey(incident: RedactedIncident): string {\n return JSON.stringify([\n incident.code,\n incident.context.operation,\n incident.context.objectKind,\n incident.context.objectId,\n incident.context.organizationId ?? null,\n incident.context.evidenceHashes,\n ]);\n}\n\ntype SecurityIncidentListeners = ReturnType<\n typeof createListenerSet<[SecurityIncident]>\n>;\n\nclass SecurityIncidentSink {\n private readonly bufferedIncidents = new Map<string, RedactedIncident>();\n private flushPromise: Promise<boolean> | null = null;\n private retryDelayMs = SECURITY_INCIDENT_RETRY_DELAY_MS;\n private retryTimeout: ReturnType<typeof setTimeout> | null = null;\n private readonly unsubscribeDatabase: () => void;\n private disposed = false;\n\n constructor(\n private readonly options: SecurityIncidentServiceOptions,\n private readonly listeners: SecurityIncidentListeners,\n ) {\n this.unsubscribeDatabase = options.database.subscribe(() => {\n void this.flush();\n });\n }\n\n dispose(): void {\n this.disposed = true;\n this.unsubscribeDatabase();\n if (this.retryTimeout) clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n this.bufferedIncidents.clear();\n }\n\n async persist(\n code: SecurityIncident[\"code\"],\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus> {\n if (this.disposed) return \"failed\";\n const detectedAt = new Date().toISOString();\n const incident: RedactedIncident = {\n code,\n context: redactIncidentContext(context),\n detectedAt,\n lastDetectedAt: detectedAt,\n occurrenceCount: 1,\n };\n const execSql = this.options.database.execSql;\n if (this.options.database.status !== \"ready\" || !execSql) {\n return this.bufferStatus(incident);\n }\n\n try {\n const persisted = await this.append(execSql, incident);\n if (this.bufferedIncidents.size === 0) this.resetFlushRetry();\n if (!persisted) {\n this.options.logError(\n \"Security incident was dropped by the local retention limit\",\n );\n return \"failed\";\n }\n this.notify(persisted);\n return \"recorded\";\n } catch (persistenceError) {\n const status = this.bufferStatus(incident);\n if (status === \"buffered\") this.scheduleFlushRetry();\n this.options.logError(\n \"Security incident could not be persisted\",\n persistenceError,\n );\n return status;\n }\n }\n\n private bufferStatus(\n incident: RedactedIncident,\n ): SecurityIncidentRecordingStatus {\n return this.buffer(incident) ? \"buffered\" : \"failed\";\n }\n\n async flush(): Promise<void> {\n if (this.disposed) return;\n for (;;) {\n const activeFlush = this.flushPromise ?? this.startFlushBatch();\n if (!activeFlush) return;\n const succeeded = await activeFlush;\n if (succeeded) this.resetFlushRetry();\n if (this.flushPromise && this.flushPromise !== activeFlush) continue;\n if (this.flushPromise === activeFlush) this.flushPromise = null;\n if (\n !succeeded ||\n this.bufferedIncidents.size === 0 ||\n this.options.database.status !== \"ready\"\n ) {\n return;\n }\n }\n }\n\n private startFlushBatch(): Promise<boolean> | null {\n const execSql = this.options.database.execSql;\n if (this.options.database.status !== \"ready\" || !execSql) return null;\n\n const pending = [...this.bufferedIncidents.values()];\n if (pending.length === 0) return null;\n this.bufferedIncidents.clear();\n const flush = this.flushPending(execSql, pending);\n this.flushPromise = flush;\n return flush;\n }\n\n private append(\n execSql: NonNullable<Database[\"execSql\"]>,\n incident: RedactedIncident,\n ): Promise<SecurityIncident | null> {\n return appendSecurityIncident(execSql, {\n code: incident.code,\n detectedAt: incident.detectedAt,\n evidenceHashes: incident.context.evidenceHashes,\n lastDetectedAt: incident.lastDetectedAt,\n objectId: incident.context.objectId,\n objectKind: incident.context.objectKind,\n occurrenceCount: incident.occurrenceCount,\n operation: incident.context.operation,\n organizationId: incident.context.organizationId,\n trustDomain: this.options.trustDomain,\n });\n }\n\n private buffer(incident: RedactedIncident): boolean {\n if (this.disposed) return false;\n const key = redactedIncidentKey(incident);\n const existing = this.bufferedIncidents.get(key);\n if (existing) {\n this.bufferedIncidents.set(key, {\n ...existing,\n lastDetectedAt: incident.lastDetectedAt,\n occurrenceCount: existing.occurrenceCount + incident.occurrenceCount,\n });\n return true;\n }\n if (this.bufferedIncidents.size >= MAX_BUFFERED_SECURITY_INCIDENTS) {\n this.options.logError(\n \"Security incident could not be buffered because the startup buffer is full\",\n );\n return false;\n }\n this.bufferedIncidents.set(key, incident);\n return true;\n }\n\n private async flushPending(\n execSql: NonNullable<Database[\"execSql\"]>,\n pending: ReadonlyArray<RedactedIncident>,\n ): Promise<boolean> {\n let succeeded = true;\n for (const incident of pending) {\n try {\n const persisted = await this.append(execSql, incident);\n if (persisted) this.notify(persisted);\n } catch (persistenceError) {\n succeeded = false;\n if (this.buffer(incident)) this.scheduleFlushRetry();\n this.options.logError(\n \"Buffered security incident could not be persisted\",\n persistenceError,\n );\n }\n }\n return succeeded;\n }\n\n private notify(incident: SecurityIncident): void {\n if (this.disposed) return;\n this.listeners.notify(incident);\n try {\n this.options.onIncident?.(incident);\n } catch (callbackError) {\n this.options.logError(\"Security incident callback failed\", callbackError);\n }\n }\n\n private scheduleFlushRetry(): void {\n if (this.disposed || this.retryTimeout) return;\n const retryDelayMs = this.retryDelayMs;\n this.retryDelayMs = Math.min(\n this.retryDelayMs * 2,\n SECURITY_INCIDENT_MAX_RETRY_DELAY_MS,\n );\n this.retryTimeout = setTimeout(() => {\n this.retryTimeout = null;\n if (this.disposed) return;\n void this.flush();\n }, retryDelayMs);\n }\n\n private resetFlushRetry(): void {\n this.retryDelayMs = SECURITY_INCIDENT_RETRY_DELAY_MS;\n if (!this.retryTimeout) return;\n clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n }\n}\n\nexport function createSecurityIncidentService(\n options: SecurityIncidentServiceOptions,\n): SecurityIncidentServiceResult {\n const listeners = createListenerSet<[SecurityIncident]>();\n const recordedErrors = new WeakMap<object, SecurityIncidentRecordingStatus>();\n const incidentReports = new WeakMap<\n object,\n Promise<SecurityIncidentRecordingStatus>\n >();\n const sink = new SecurityIncidentSink(options, listeners);\n\n const persistIncident = async (\n error: unknown,\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus> => {\n const code = verificationCode(error);\n if (!code) {\n return \"failed\";\n }\n if (code === \"unrecognized_verification_code\") {\n options.logError(\n \"Security incident used the fallback code because its verification code is unrecognized\",\n );\n }\n\n return sink.persist(code, context);\n };\n\n const record = async (\n error: unknown,\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus> => {\n if (typeof error !== \"object\" || error === null) {\n return \"failed\";\n }\n const recorded = recordedErrors.get(error);\n if (recorded) return recorded;\n const inFlight = incidentReports.get(error);\n if (inFlight) return inFlight;\n const pending = persistIncident(error, context)\n .then((status) => {\n if (status !== \"failed\") recordedErrors.set(error, status);\n return status;\n })\n .finally(() => {\n incidentReports.delete(error);\n });\n incidentReports.set(error, pending);\n return pending;\n };\n const report: SecurityIncidentReporter = async (error, context) => {\n await record(error, context);\n };\n\n return {\n dispose: () => sink.dispose(),\n incidents: {\n async list() {\n await sink.flush();\n const execSql = options.database.execSql;\n return options.database.status === \"ready\" && execSql\n ? listSecurityIncidents(execSql, options.trustDomain)\n : null;\n },\n record,\n subscribe: listeners.subscribe,\n },\n report,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"securityIncidents.js","sourceRoot":"","sources":["securityIncidents.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compareCanonicalStrings,\n isKeyingVerificationCode,\n type KeyingVerificationError,\n} from \"@tearleads/crypto\";\nimport { isKeyingVerificationError } from \"../data/keyingProjectionVerification/error\";\nimport {\n appendSecurityIncident,\n listSecurityIncidents,\n} from \"../data/persistence/securityIncidentPersistence\";\nimport type {\n SecurityIncident,\n SecurityIncidentContext,\n SecurityIncidentObjectKind,\n SecurityIncidentReporter,\n} from \"../data/shared/securityIncidents\";\nimport type { Database } from \"./database\";\nimport { createListenerSet } from \"./listenerSet\";\n\nexport type { SecurityIncident, SecurityIncidentObjectKind };\n\nexport type SecurityIncidentListener = (incident: SecurityIncident) => void;\n\n/**\n * Where a reported incident ended up: `recorded` rows are durable in the local\n * ledger, `buffered` ones wait in memory for a retried write, and `failed`\n * ones were dropped, so only `recorded` justifies telling a user it was kept.\n * Hosts name it as `Awaited<ReturnType<SecurityIncidents[\"record\"]>>`.\n */\ntype SecurityIncidentRecordingStatus = \"buffered\" | \"failed\" | \"recorded\";\n\nconst MAX_BUFFERED_SECURITY_INCIDENTS = 100;\nconst MAX_EVIDENCE_HASH_COUNT = 32;\nconst MAX_EVIDENCE_HASH_KEY_LENGTH = 64;\nconst MAX_EVIDENCE_HASH_VALUE_LENGTH = 256;\nconst MAX_INCIDENT_IDENTIFIER_LENGTH = 256;\nconst MAX_INCIDENT_OPERATION_LENGTH = 128;\nconst SECURITY_INCIDENT_RETRY_DELAY_MS = 250;\nconst SECURITY_INCIDENT_MAX_RETRY_DELAY_MS = 30_000;\n\nexport interface SecurityIncidents {\n /** Returns null while the local database is unavailable. */\n list(): Promise<ReadonlyArray<SecurityIncident> | null>;\n /**\n * Durably record a terminal verification failure the host detected itself,\n * such as conflicting purge proofs found while merging a local backup. The\n * report is redacted, coalesced, retained, and buffered exactly like an\n * SDK-detected incident; one error instance is recorded at most once, and\n * repeats of it resolve with the status of the first report.\n */\n record(\n error: KeyingVerificationError,\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus>;\n subscribe(listener: SecurityIncidentListener): () => void;\n}\n\ninterface SecurityIncidentServiceOptions {\n readonly database: Database;\n readonly logError: (message: string | Error, cause?: unknown) => void;\n readonly onIncident?: SecurityIncidentListener | undefined;\n readonly trustDomain: string | null;\n}\n\ninterface SecurityIncidentServiceResult {\n readonly dispose: () => void;\n readonly incidents: SecurityIncidents;\n readonly report: SecurityIncidentReporter;\n}\n\nfunction verificationCode(error: unknown): SecurityIncident[\"code\"] | null {\n if (!isKeyingVerificationError(error)) return null;\n const code = Reflect.get(error, \"code\");\n return isKeyingVerificationCode(code)\n ? code\n : \"unrecognized_verification_code\";\n}\n\ninterface RedactedIncident {\n readonly code: SecurityIncident[\"code\"];\n readonly context: SecurityIncidentContext;\n readonly detectedAt: string;\n readonly lastDetectedAt: string;\n readonly occurrenceCount: number;\n}\n\nfunction boundIncidentText(value: string, maxLength: number): string {\n return value.slice(0, maxLength);\n}\n\nfunction boundNullableIncidentText(value: string | null): string | null {\n return value === null\n ? null\n : boundIncidentText(value, MAX_INCIDENT_IDENTIFIER_LENGTH);\n}\n\nfunction redactIncidentContext(\n context: SecurityIncidentContext,\n): SecurityIncidentContext {\n return {\n evidenceHashes: Object.fromEntries(\n Object.entries(context.evidenceHashes ?? {})\n .filter(\n ([key, value]) =>\n key.length > 0 &&\n key.length <= MAX_EVIDENCE_HASH_KEY_LENGTH &&\n value.length <= MAX_EVIDENCE_HASH_VALUE_LENGTH,\n )\n // Code-unit order: the retained keys feed the incident id hash, so\n // truncation must pick the same keys on every runtime and locale.\n .sort(([left], [right]) => compareCanonicalStrings(left, right))\n .slice(0, MAX_EVIDENCE_HASH_COUNT),\n ),\n objectId: boundNullableIncidentText(context.objectId),\n objectKind: context.objectKind,\n operation: boundIncidentText(\n context.operation,\n MAX_INCIDENT_OPERATION_LENGTH,\n ),\n organizationId: boundNullableIncidentText(context.organizationId ?? null),\n };\n}\n\nfunction redactedIncidentKey(incident: RedactedIncident): string {\n return JSON.stringify([\n incident.code,\n incident.context.operation,\n incident.context.objectKind,\n incident.context.objectId,\n incident.context.organizationId ?? null,\n incident.context.evidenceHashes,\n ]);\n}\n\ntype SecurityIncidentListeners = ReturnType<\n typeof createListenerSet<[SecurityIncident]>\n>;\n\nclass SecurityIncidentSink {\n private readonly bufferedIncidents = new Map<string, RedactedIncident>();\n private flushPromise: Promise<boolean> | null = null;\n private retryDelayMs = SECURITY_INCIDENT_RETRY_DELAY_MS;\n private retryTimeout: ReturnType<typeof setTimeout> | null = null;\n private readonly unsubscribeDatabase: () => void;\n private disposed = false;\n\n constructor(\n private readonly options: SecurityIncidentServiceOptions,\n private readonly listeners: SecurityIncidentListeners,\n ) {\n this.unsubscribeDatabase = options.database.subscribe(() => {\n void this.flush();\n });\n }\n\n dispose(): void {\n this.disposed = true;\n this.unsubscribeDatabase();\n if (this.retryTimeout) clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n this.bufferedIncidents.clear();\n }\n\n async persist(\n code: SecurityIncident[\"code\"],\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus> {\n if (this.disposed) return \"failed\";\n const detectedAt = new Date().toISOString();\n const incident: RedactedIncident = {\n code,\n context: redactIncidentContext(context),\n detectedAt,\n lastDetectedAt: detectedAt,\n occurrenceCount: 1,\n };\n const execSql = this.options.database.execSql;\n if (this.options.database.status !== \"ready\" || !execSql) {\n return this.bufferStatus(incident);\n }\n\n try {\n const persisted = await this.append(execSql, incident);\n if (this.bufferedIncidents.size === 0) this.resetFlushRetry();\n if (!persisted) {\n this.options.logError(\n \"Security incident was dropped by the local retention limit\",\n );\n return \"failed\";\n }\n this.notify(persisted);\n return \"recorded\";\n } catch (persistenceError) {\n const status = this.bufferStatus(incident);\n if (status === \"buffered\") this.scheduleFlushRetry();\n this.options.logError(\n \"Security incident could not be persisted\",\n persistenceError,\n );\n return status;\n }\n }\n\n private bufferStatus(\n incident: RedactedIncident,\n ): SecurityIncidentRecordingStatus {\n return this.buffer(incident) ? \"buffered\" : \"failed\";\n }\n\n async flush(): Promise<void> {\n if (this.disposed) return;\n for (;;) {\n const activeFlush = this.flushPromise ?? this.startFlushBatch();\n if (!activeFlush) return;\n const succeeded = await activeFlush;\n if (succeeded) this.resetFlushRetry();\n if (this.flushPromise && this.flushPromise !== activeFlush) continue;\n if (this.flushPromise === activeFlush) this.flushPromise = null;\n if (\n !succeeded ||\n this.bufferedIncidents.size === 0 ||\n this.options.database.status !== \"ready\"\n ) {\n return;\n }\n }\n }\n\n private startFlushBatch(): Promise<boolean> | null {\n const execSql = this.options.database.execSql;\n if (this.options.database.status !== \"ready\" || !execSql) return null;\n\n const pending = [...this.bufferedIncidents.values()];\n if (pending.length === 0) return null;\n this.bufferedIncidents.clear();\n const flush = this.flushPending(execSql, pending);\n this.flushPromise = flush;\n return flush;\n }\n\n private append(\n execSql: NonNullable<Database[\"execSql\"]>,\n incident: RedactedIncident,\n ): Promise<SecurityIncident | null> {\n return appendSecurityIncident(execSql, {\n code: incident.code,\n detectedAt: incident.detectedAt,\n evidenceHashes: incident.context.evidenceHashes,\n lastDetectedAt: incident.lastDetectedAt,\n objectId: incident.context.objectId,\n objectKind: incident.context.objectKind,\n occurrenceCount: incident.occurrenceCount,\n operation: incident.context.operation,\n organizationId: incident.context.organizationId,\n trustDomain: this.options.trustDomain,\n });\n }\n\n private buffer(incident: RedactedIncident): boolean {\n if (this.disposed) return false;\n const key = redactedIncidentKey(incident);\n const existing = this.bufferedIncidents.get(key);\n if (existing) {\n this.bufferedIncidents.set(key, {\n ...existing,\n lastDetectedAt: incident.lastDetectedAt,\n occurrenceCount: existing.occurrenceCount + incident.occurrenceCount,\n });\n return true;\n }\n if (this.bufferedIncidents.size >= MAX_BUFFERED_SECURITY_INCIDENTS) {\n this.options.logError(\n \"Security incident could not be buffered because the startup buffer is full\",\n );\n return false;\n }\n this.bufferedIncidents.set(key, incident);\n return true;\n }\n\n private async flushPending(\n execSql: NonNullable<Database[\"execSql\"]>,\n pending: ReadonlyArray<RedactedIncident>,\n ): Promise<boolean> {\n let succeeded = true;\n for (const incident of pending) {\n try {\n const persisted = await this.append(execSql, incident);\n if (persisted) this.notify(persisted);\n } catch (persistenceError) {\n succeeded = false;\n if (this.buffer(incident)) this.scheduleFlushRetry();\n this.options.logError(\n \"Buffered security incident could not be persisted\",\n persistenceError,\n );\n }\n }\n return succeeded;\n }\n\n private notify(incident: SecurityIncident): void {\n if (this.disposed) return;\n this.listeners.notify(incident);\n try {\n this.options.onIncident?.(incident);\n } catch (callbackError) {\n this.options.logError(\"Security incident callback failed\", callbackError);\n }\n }\n\n private scheduleFlushRetry(): void {\n if (this.disposed || this.retryTimeout) return;\n const retryDelayMs = this.retryDelayMs;\n this.retryDelayMs = Math.min(\n this.retryDelayMs * 2,\n SECURITY_INCIDENT_MAX_RETRY_DELAY_MS,\n );\n this.retryTimeout = setTimeout(() => {\n this.retryTimeout = null;\n if (this.disposed) return;\n void this.flush();\n }, retryDelayMs);\n }\n\n private resetFlushRetry(): void {\n this.retryDelayMs = SECURITY_INCIDENT_RETRY_DELAY_MS;\n if (!this.retryTimeout) return;\n clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n }\n}\n\nexport function createSecurityIncidentService(\n options: SecurityIncidentServiceOptions,\n): SecurityIncidentServiceResult {\n const listeners = createListenerSet<[SecurityIncident]>();\n const recordedErrors = new WeakMap<object, SecurityIncidentRecordingStatus>();\n const incidentReports = new WeakMap<\n object,\n Promise<SecurityIncidentRecordingStatus>\n >();\n const sink = new SecurityIncidentSink(options, listeners);\n\n const persistIncident = async (\n error: unknown,\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus> => {\n const code = verificationCode(error);\n if (!code) {\n return \"failed\";\n }\n if (code === \"unrecognized_verification_code\") {\n options.logError(\n \"Security incident used the fallback code because its verification code is unrecognized\",\n );\n }\n\n return sink.persist(code, context);\n };\n\n const record = async (\n error: unknown,\n context: SecurityIncidentContext,\n ): Promise<SecurityIncidentRecordingStatus> => {\n if (typeof error !== \"object\" || error === null) {\n return \"failed\";\n }\n const recorded = recordedErrors.get(error);\n if (recorded) return recorded;\n const inFlight = incidentReports.get(error);\n if (inFlight) return inFlight;\n const pending = persistIncident(error, context)\n .then((status) => {\n if (status !== \"failed\") recordedErrors.set(error, status);\n return status;\n })\n .finally(() => {\n incidentReports.delete(error);\n });\n incidentReports.set(error, pending);\n return pending;\n };\n const report: SecurityIncidentReporter = async (error, context) => {\n await record(error, context);\n };\n\n return {\n dispose: () => sink.dispose(),\n incidents: {\n async list() {\n await sink.flush();\n const execSql = options.database.execSql;\n return options.database.status === \"ready\" && execSql\n ? listSecurityIncidents(execSql, options.trustDomain)\n : null;\n },\n record,\n subscribe: listeners.subscribe,\n },\n report,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionLoginRefusal.js","sourceRoot":"","sources":["sessionLoginRefusal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,+CAA+C,CAAC;AAGxG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAc,EACd,MAAc,EACd,OAGC;IAED,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,uCAAuC,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;QACnE,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,eAAe;KAC3B,CAAC,CAAC;IACH,MAAM,KAAK,CAAC;AACd,CAAC","sourcesContent":["import { reportAndRethrowKeyingVerificationError } from \"../../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\n\n/**\n * A server answering this identity with another account, or an identity\n * whose durable pin no longer matches, is evidence, not a login failure: the\n * session is cleared, the keying error is recorded, and the error propagates.\n */\nexport async function refuseSessionLogin(\n error: unknown,\n userId: string,\n session: {\n readonly clear: () => void;\n readonly report: SecurityIncidentReporter | undefined;\n },\n): Promise<never> {\n session.clear();\n await reportAndRethrowKeyingVerificationError(error, session.report, {\n objectId: userId,\n objectKind: \"user\",\n operation: \"session.login\",\n });\n throw error;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionLoginRefusal.js","sourceRoot":"","sources":["sessionLoginRefusal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,+CAA+C,CAAC;AAGxG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAc,EACd,MAAc,EACd,OAGC;IAED,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,uCAAuC,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;QACnE,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,eAAe;KAC3B,CAAC,CAAC;IACH,MAAM,KAAK,CAAC;AACd,CAAC","sourcesContent":["import { reportAndRethrowKeyingVerificationError } from \"../../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../../data/shared/securityIncidents\";\n\n/**\n * A server answering this identity with another account, or an identity\n * whose durable pin no longer matches, is evidence, not a login failure: the\n * session is cleared, the keying error is recorded, and the error propagates.\n */\nexport async function refuseSessionLogin(\n error: unknown,\n userId: string,\n session: {\n readonly clear: () => void;\n readonly report: SecurityIncidentReporter | undefined;\n },\n): Promise<never> {\n session.clear();\n await reportAndRethrowKeyingVerificationError(error, session.report, {\n objectId: userId,\n objectKind: \"user\",\n operation: \"session.login\",\n });\n throw error;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionRootAuthority.js","sourceRoot":"","sources":["sessionRootAuthority.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { reportKeyingVerificationErrorInCauseChain } from \"../../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\nimport type { Session, SessionContext, SessionSnapshot } from \"./sessionTypes\";\n\ntype RootAcknowledgments = SessionSnapshot[\"rootAcknowledgments\"];\ntype RootAcknowledgmentInput = Omit<\n RootAcknowledgments[number],\n \"signingFingerprint\"\n>;\n\n/**\n * The login, registration and organization-creation responses that carry a\n * root id are unsigned. An organization's root row is created once, in the\n * provisioning transaction, and only ever disappears through a purge, so an\n * honest server can re-acknowledge the same root or report it gone (null) but\n * never presents a different root for an organization this identity already\n * acknowledged. A different id is a substitution attempt: the previous root\n * stays authoritative and the caller records a security incident.\n */\nfunction assertRootAcknowledgmentUnchanged(\n previous: RootAcknowledgments[number] | undefined,\n input: RootAcknowledgmentInput,\n): void {\n if (\n !previous ||\n previous.rootContainerId === input.rootContainerId ||\n input.rootContainerId === null\n ) {\n return;\n }\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Session root acknowledgement changed for an acknowledged organization\",\n );\n}\n\nexport function acknowledgeSessionRoot(\n known: RootAcknowledgments,\n input: RootAcknowledgmentInput,\n signingFingerprint: string | null,\n): RootAcknowledgments {\n if (!signingFingerprint)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Session root acknowledgement requires a signing identity\",\n );\n const matchesIdentity = (entry: RootAcknowledgments[number]) =>\n entry.signingFingerprint === signingFingerprint &&\n entry.userId === input.userId;\n assertRootAcknowledgmentUnchanged(\n known.find(\n (entry) =>\n matchesIdentity(entry) && entry.organizationId === input.organizationId,\n ),\n input,\n );\n return [\n ...known.filter(\n (entry) =>\n matchesIdentity(entry) && entry.organizationId !== input.organizationId,\n ),\n {\n userId: input.userId,\n organizationId: input.organizationId,\n rootContainerId: input.rootContainerId,\n signingFingerprint,\n },\n ];\n}\n\n/**\n * Decides and commits an acknowledgement against the session's CURRENT\n * snapshot in one synchronous step: reading `rootAcknowledgments`, deciding,\n * and `setContext` happen with no await between them, so an overlapping login,\n * registration or organization creation can never overwrite this entry with a\n * stale copy (a lost acknowledgement would erase that organization's root-swap\n * protection). Only the incident report for a refusal is asynchronous, and it\n * runs after the decision has been made and before the error propagates;\n * `onRefused` runs synchronously with the decision, ahead of that report.\n */\nexport async function commitSessionRootAcknowledgment(input: {\n readonly context?: Omit<SessionContext, \"rootAcknowledgments\"> | undefined;\n readonly onRefused?: (() => void) | undefined;\n readonly reporter: SecurityIncidentReporter | undefined;\n readonly root: RootAcknowledgmentInput;\n readonly session: Pick<Session, \"setContext\" | \"snapshot\">;\n readonly signingFingerprint: string | null;\n}): Promise<void> {\n const { context, reporter, root, session, signingFingerprint } = input;\n let rootAcknowledgments: RootAcknowledgments;\n try {\n rootAcknowledgments = acknowledgeSessionRoot(\n session.snapshot.rootAcknowledgments,\n root,\n signingFingerprint,\n );\n } catch (error) {\n input.onRefused?.();\n if (signingFingerprint) {\n await reportKeyingVerificationErrorInCauseChain(error, reporter, {\n objectId: root.rootContainerId,\n objectKind: \"container\",\n operation: \"session.root.acknowledge\",\n organizationId: root.organizationId,\n });\n }\n throw error;\n }\n session.setContext({ ...context, rootAcknowledgments });\n}\n\n/** Only the encrypted host restore may supply previously acknowledged roots. */\nexport function restoreSessionRoots(\n known: RootAcknowledgments,\n restored: RootAcknowledgments | undefined,\n signingFingerprint: string | null,\n userId: string | null,\n): RootAcknowledgments {\n const matches = (entry: RootAcknowledgments[number]) =>\n entry.signingFingerprint === signingFingerprint && entry.userId === userId;\n if (restored) {\n if (\n !restored.every(matches) ||\n new Set(restored.map((entry) => entry.organizationId)).size !==\n restored.length\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Restored roots differ from the active identity\",\n );\n }\n return restored.map((entry) => ({ ...entry }));\n }\n return known.every(matches) ? known : known.filter(matches);\n}\n\nexport function acknowledgedSessionRoot(\n session: Session,\n signingFingerprint: string | null,\n): string | null {\n return (\n session.snapshot.rootAcknowledgments.find(\n (entry) =>\n entry.signingFingerprint === signingFingerprint &&\n entry.userId === session.userId &&\n entry.organizationId === session.organizationId,\n )?.rootContainerId ?? null\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionRootAuthority.js","sourceRoot":"","sources":["sessionRootAuthority.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { reportKeyingVerificationErrorInCauseChain } from \"../../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../../data/shared/securityIncidents\";\nimport type { Session, SessionContext, SessionSnapshot } from \"./sessionTypes\";\n\ntype RootAcknowledgments = SessionSnapshot[\"rootAcknowledgments\"];\ntype RootAcknowledgmentInput = Omit<\n RootAcknowledgments[number],\n \"signingFingerprint\"\n>;\n\n/**\n * The login, registration and organization-creation responses that carry a\n * root id are unsigned. An organization's root row is created once, in the\n * provisioning transaction, and only ever disappears through a purge, so an\n * honest server can re-acknowledge the same root or report it gone (null) but\n * never presents a different root for an organization this identity already\n * acknowledged. A different id is a substitution attempt: the previous root\n * stays authoritative and the caller records a security incident.\n */\nfunction assertRootAcknowledgmentUnchanged(\n previous: RootAcknowledgments[number] | undefined,\n input: RootAcknowledgmentInput,\n): void {\n if (\n !previous ||\n previous.rootContainerId === input.rootContainerId ||\n input.rootContainerId === null\n ) {\n return;\n }\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Session root acknowledgement changed for an acknowledged organization\",\n );\n}\n\nexport function acknowledgeSessionRoot(\n known: RootAcknowledgments,\n input: RootAcknowledgmentInput,\n signingFingerprint: string | null,\n): RootAcknowledgments {\n if (!signingFingerprint)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Session root acknowledgement requires a signing identity\",\n );\n const matchesIdentity = (entry: RootAcknowledgments[number]) =>\n entry.signingFingerprint === signingFingerprint &&\n entry.userId === input.userId;\n assertRootAcknowledgmentUnchanged(\n known.find(\n (entry) =>\n matchesIdentity(entry) && entry.organizationId === input.organizationId,\n ),\n input,\n );\n return [\n ...known.filter(\n (entry) =>\n matchesIdentity(entry) && entry.organizationId !== input.organizationId,\n ),\n {\n userId: input.userId,\n organizationId: input.organizationId,\n rootContainerId: input.rootContainerId,\n signingFingerprint,\n },\n ];\n}\n\n/**\n * Decides and commits an acknowledgement against the session's CURRENT\n * snapshot in one synchronous step: reading `rootAcknowledgments`, deciding,\n * and `setContext` happen with no await between them, so an overlapping login,\n * registration or organization creation can never overwrite this entry with a\n * stale copy (a lost acknowledgement would erase that organization's root-swap\n * protection). Only the incident report for a refusal is asynchronous, and it\n * runs after the decision has been made and before the error propagates;\n * `onRefused` runs synchronously with the decision, ahead of that report.\n */\nexport async function commitSessionRootAcknowledgment(input: {\n readonly context?: Omit<SessionContext, \"rootAcknowledgments\"> | undefined;\n readonly onRefused?: (() => void) | undefined;\n readonly reporter: SecurityIncidentReporter | undefined;\n readonly root: RootAcknowledgmentInput;\n readonly session: Pick<Session, \"setContext\" | \"snapshot\">;\n readonly signingFingerprint: string | null;\n}): Promise<void> {\n const { context, reporter, root, session, signingFingerprint } = input;\n let rootAcknowledgments: RootAcknowledgments;\n try {\n rootAcknowledgments = acknowledgeSessionRoot(\n session.snapshot.rootAcknowledgments,\n root,\n signingFingerprint,\n );\n } catch (error) {\n input.onRefused?.();\n if (signingFingerprint) {\n await reportKeyingVerificationErrorInCauseChain(error, reporter, {\n objectId: root.rootContainerId,\n objectKind: \"container\",\n operation: \"session.root.acknowledge\",\n organizationId: root.organizationId,\n });\n }\n throw error;\n }\n session.setContext({ ...context, rootAcknowledgments });\n}\n\n/** Only the encrypted host restore may supply previously acknowledged roots. */\nexport function restoreSessionRoots(\n known: RootAcknowledgments,\n restored: RootAcknowledgments | undefined,\n signingFingerprint: string | null,\n userId: string | null,\n): RootAcknowledgments {\n const matches = (entry: RootAcknowledgments[number]) =>\n entry.signingFingerprint === signingFingerprint && entry.userId === userId;\n if (restored) {\n if (\n !restored.every(matches) ||\n new Set(restored.map((entry) => entry.organizationId)).size !==\n restored.length\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Restored roots differ from the active identity\",\n );\n }\n return restored.map((entry) => ({ ...entry }));\n }\n return known.every(matches) ? known : known.filter(matches);\n}\n\nexport function acknowledgedSessionRoot(\n session: Session,\n signingFingerprint: string | null,\n): string | null {\n return (\n session.snapshot.rootAcknowledgments.find(\n (entry) =>\n entry.signingFingerprint === signingFingerprint &&\n entry.userId === session.userId &&\n entry.organizationId === session.organizationId,\n )?.rootContainerId ?? null\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ApiClient } from "../../internal/api-client/index.js";
|
|
2
2
|
import type { DocumentProjectorRegistryInput } from "../../data/documents/documentKinds.js";
|
|
3
|
-
import type { SecurityIncidentReporter } from "../../data/securityIncidents.js";
|
|
3
|
+
import type { SecurityIncidentReporter } from "../../data/shared/securityIncidents.js";
|
|
4
4
|
import type { ProvisionedSystemContainerSpec } from "../../workflows/registration/index.js";
|
|
5
5
|
import type { ProvisionedPrincipalHistoryPrimer } from "../../workflows/registration/provisionedPrincipalHistory.js";
|
|
6
6
|
import type { ClearRemoteSyncStateResult } from "../../workflows/sync/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionTypes.js","sourceRoot":"","sources":["sessionTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { DocumentProjectorRegistryInput } from \"../../data/documents/documentKinds\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\nimport type { ProvisionedSystemContainerSpec } from \"../../workflows/registration\";\nimport type { ProvisionedPrincipalHistoryPrimer } from \"../../workflows/registration/provisionedPrincipalHistory\";\nimport type { ClearRemoteSyncStateResult } from \"../../workflows/sync\";\nimport type { Database } from \"../database\";\nimport type { Identity } from \"../identity\";\nimport type {\n BoundUserIdLookup,\n SessionRegistrationRefusal,\n UserIdentityAvailable,\n} from \"./sessionIdentityTrust\";\n\nexport type { SessionRegistrationRefusal } from \"./sessionIdentityTrust\";\n\nexport interface SessionDependencies {\n api: ApiClient;\n database: Database;\n documentProjectors?: DocumentProjectorRegistryInput | undefined;\n identity: Identity;\n log: (message: string) => void;\n logError: (message: string | Error, cause?: unknown) => void;\n /** The user this device's trust store already binds a signing key to. */\n boundUserIdForSigningKey?: BoundUserIdLookup | undefined;\n onUserIdentityAvailable?: UserIdentityAvailable | undefined;\n /** Seeds verified recovery progress for a new organization's founding heads. */\n primeProvisionedPrincipalHistory?:\n | ProvisionedPrincipalHistoryPrimer\n | undefined;\n /** App-owned system containers provisioned with each new organization. */\n provisionedSystemContainers?:\n | ReadonlyArray<ProvisionedSystemContainerSpec>\n | undefined;\n /**\n * Records a refused login (a different account than acknowledged) or a\n * refused root acknowledgement; absent in bare test harnesses.\n */\n reportSecurityIncident?: SecurityIncidentReporter | undefined;\n}\n\nexport interface SessionContext {\n /** Fingerprint-bound host restore only; view selections never acknowledge roots. */\n rootAcknowledgments?: SessionSnapshot[\"rootAcknowledgments\"] | undefined;\n authToken?: string | null | undefined;\n containerId?: string | null | undefined;\n /** Server-backed personal organization; independent of the active org. */\n defaultOrganizationId?: string | null | undefined;\n isAuthenticated?: boolean | undefined;\n /** Platform-operator flag reported by the server at login. */\n isRoot?: boolean | undefined;\n organizationId?: string | null | undefined;\n userId?: string | null | undefined;\n}\n\nexport interface SessionSnapshot {\n /**\n * Server acknowledgements retained independently of the selected container.\n * Bound to (signing fingerprint, user, organization): once acknowledged, an\n * organization's root id may only be re-acknowledged or reported purged.\n */\n rootAcknowledgments: ReadonlyArray<{\n readonly signingFingerprint: string;\n readonly userId: string;\n readonly organizationId: string;\n readonly rootContainerId: string | null;\n }>;\n authToken: string | null;\n containerId: string | null;\n /** Server-backed personal organization; independent of the active org. */\n defaultOrganizationId: string | null;\n isAuthenticated: boolean;\n /** Platform-operator flag reported by the server at login. */\n isRoot: boolean;\n organizationId: string | null;\n userId: string | null;\n}\n\nexport type SessionListener = () => void;\n\nexport interface SessionRegistrationResult {\n readonly challenge: string;\n readonly containerId: string;\n readonly organizationId: string;\n readonly userId: string;\n}\n\nexport interface SessionCreateOrganizationResult {\n readonly containerId: string;\n readonly organizationId: string;\n}\n\nexport interface SessionRecoverOrganizationResult\n extends SessionCreateOrganizationResult {\n readonly reset: ClearRemoteSyncStateResult;\n readonly replacedOrganizationId: string;\n}\n\nexport interface CreateOrganizationOptions {\n /** Overrides the seeded organization profile name; see registration. */\n readonly organizationProfileName?: string | undefined;\n /** Overrides the seeded self roster-profile nickname; see registration. */\n readonly rosterProfileNickname?: string | undefined;\n}\n\nexport interface RegisterIdentityOptions {\n /**\n * Overrides the seeded personal-organization profile name. Optional; when\n * omitted the default personal-org name is used. The demo host passes each\n * pane's peer-labeled org name (\"Peer 1's Org\").\n */\n readonly organizationProfileName?: string | undefined;\n /**\n * Overrides the seeded self roster-profile nickname. Optional; when omitted\n * the default (\"You\") is used. The demo host passes each pane's peer-labeled\n * self name (\"Peer 1 (You)\").\n */\n readonly rosterProfileNickname?: string | undefined;\n}\n\nexport interface UserSession {\n readonly createdAt: string;\n readonly id: string;\n readonly ipAddresses: string[];\n readonly isCurrent: boolean;\n readonly lastActiveAt: string;\n readonly lastActiveIp: string | null;\n readonly signingKeyFingerprint: string;\n}\n\nexport interface Session {\n readonly authToken: string | null;\n readonly containerId: string | null;\n /** Server-backed personal organization; independent of the active org. */\n readonly defaultOrganizationId: string | null;\n readonly isAuthenticated: boolean;\n /**\n * Platform-operator flag reported by the server at login. It only decides\n * whether the root console is offered; the API enforces root access itself.\n */\n readonly isRoot: boolean;\n readonly organizationId: string | null;\n readonly snapshot: SessionSnapshot;\n /** Controls server replication without changing network connectivity. */\n readonly syncEnabled: boolean;\n readonly userId: string | null;\n /**\n * Whether `userId` was acknowledged by the server for the active signing\n * identity (a successful login or a fingerprint-bound host restore). A user\n * ID chosen locally through `setUserId` is not, and hosts must not persist\n * it as this identity's account.\n */\n readonly userIdAcknowledged: boolean;\n bootstrapLocalRootContainer(): Promise<{\n containerId: string;\n created: boolean;\n }>;\n clearRemoteSyncState(\n organizationId: string,\n ): Promise<ClearRemoteSyncStateResult>;\n createOrganization(\n options?: CreateOrganizationOptions,\n ): Promise<SessionCreateOrganizationResult | null>;\n completeNativeSubscriptionRestoreOrganization(\n organizationId: string,\n ): Promise<boolean>;\n destroySession(sessionId: string): Promise<boolean>;\n listSessions(): Promise<UserSession[]>;\n login(challengeHex?: string | undefined): Promise<boolean>;\n logout(): void;\n logoutRemote(): Promise<boolean>;\n prepareNativeSubscriptionRestoreOrganization(\n options?: CreateOrganizationOptions,\n ): Promise<SessionCreateOrganizationResult | null>;\n registerIdentity(\n options?: RegisterIdentityOptions,\n ): Promise<SessionRegistrationResult | SessionRegistrationRefusal | null>;\n recoverPurgedOrganization(\n organizationId: string,\n options?: CreateOrganizationOptions,\n ): Promise<SessionRecoverOrganizationResult | null>;\n setAuthToken(authToken: string | null): void;\n setContainerId(containerId: string | null): void;\n /** Host-restored context must match the active signing identity; conflicting user acknowledgments throw. */\n setContext(context: SessionContext): void;\n setOrganizationId(organizationId: string | null): void;\n setSyncEnabled(enabled: boolean): void;\n setUserId(userId: string | null): void;\n subscribe(listener: SessionListener): () => void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionTypes.js","sourceRoot":"","sources":["sessionTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { DocumentProjectorRegistryInput } from \"../../data/documents/documentKinds\";\nimport type { SecurityIncidentReporter } from \"../../data/shared/securityIncidents\";\nimport type { ProvisionedSystemContainerSpec } from \"../../workflows/registration\";\nimport type { ProvisionedPrincipalHistoryPrimer } from \"../../workflows/registration/provisionedPrincipalHistory\";\nimport type { ClearRemoteSyncStateResult } from \"../../workflows/sync\";\nimport type { Database } from \"../database\";\nimport type { Identity } from \"../identity\";\nimport type {\n BoundUserIdLookup,\n SessionRegistrationRefusal,\n UserIdentityAvailable,\n} from \"./sessionIdentityTrust\";\n\nexport type { SessionRegistrationRefusal } from \"./sessionIdentityTrust\";\n\nexport interface SessionDependencies {\n api: ApiClient;\n database: Database;\n documentProjectors?: DocumentProjectorRegistryInput | undefined;\n identity: Identity;\n log: (message: string) => void;\n logError: (message: string | Error, cause?: unknown) => void;\n /** The user this device's trust store already binds a signing key to. */\n boundUserIdForSigningKey?: BoundUserIdLookup | undefined;\n onUserIdentityAvailable?: UserIdentityAvailable | undefined;\n /** Seeds verified recovery progress for a new organization's founding heads. */\n primeProvisionedPrincipalHistory?:\n | ProvisionedPrincipalHistoryPrimer\n | undefined;\n /** App-owned system containers provisioned with each new organization. */\n provisionedSystemContainers?:\n | ReadonlyArray<ProvisionedSystemContainerSpec>\n | undefined;\n /**\n * Records a refused login (a different account than acknowledged) or a\n * refused root acknowledgement; absent in bare test harnesses.\n */\n reportSecurityIncident?: SecurityIncidentReporter | undefined;\n}\n\nexport interface SessionContext {\n /** Fingerprint-bound host restore only; view selections never acknowledge roots. */\n rootAcknowledgments?: SessionSnapshot[\"rootAcknowledgments\"] | undefined;\n authToken?: string | null | undefined;\n containerId?: string | null | undefined;\n /** Server-backed personal organization; independent of the active org. */\n defaultOrganizationId?: string | null | undefined;\n isAuthenticated?: boolean | undefined;\n /** Platform-operator flag reported by the server at login. */\n isRoot?: boolean | undefined;\n organizationId?: string | null | undefined;\n userId?: string | null | undefined;\n}\n\nexport interface SessionSnapshot {\n /**\n * Server acknowledgements retained independently of the selected container.\n * Bound to (signing fingerprint, user, organization): once acknowledged, an\n * organization's root id may only be re-acknowledged or reported purged.\n */\n rootAcknowledgments: ReadonlyArray<{\n readonly signingFingerprint: string;\n readonly userId: string;\n readonly organizationId: string;\n readonly rootContainerId: string | null;\n }>;\n authToken: string | null;\n containerId: string | null;\n /** Server-backed personal organization; independent of the active org. */\n defaultOrganizationId: string | null;\n isAuthenticated: boolean;\n /** Platform-operator flag reported by the server at login. */\n isRoot: boolean;\n organizationId: string | null;\n userId: string | null;\n}\n\nexport type SessionListener = () => void;\n\nexport interface SessionRegistrationResult {\n readonly challenge: string;\n readonly containerId: string;\n readonly organizationId: string;\n readonly userId: string;\n}\n\nexport interface SessionCreateOrganizationResult {\n readonly containerId: string;\n readonly organizationId: string;\n}\n\nexport interface SessionRecoverOrganizationResult\n extends SessionCreateOrganizationResult {\n readonly reset: ClearRemoteSyncStateResult;\n readonly replacedOrganizationId: string;\n}\n\nexport interface CreateOrganizationOptions {\n /** Overrides the seeded organization profile name; see registration. */\n readonly organizationProfileName?: string | undefined;\n /** Overrides the seeded self roster-profile nickname; see registration. */\n readonly rosterProfileNickname?: string | undefined;\n}\n\nexport interface RegisterIdentityOptions {\n /**\n * Overrides the seeded personal-organization profile name. Optional; when\n * omitted the default personal-org name is used. The demo host passes each\n * pane's peer-labeled org name (\"Peer 1's Org\").\n */\n readonly organizationProfileName?: string | undefined;\n /**\n * Overrides the seeded self roster-profile nickname. Optional; when omitted\n * the default (\"You\") is used. The demo host passes each pane's peer-labeled\n * self name (\"Peer 1 (You)\").\n */\n readonly rosterProfileNickname?: string | undefined;\n}\n\nexport interface UserSession {\n readonly createdAt: string;\n readonly id: string;\n readonly ipAddresses: string[];\n readonly isCurrent: boolean;\n readonly lastActiveAt: string;\n readonly lastActiveIp: string | null;\n readonly signingKeyFingerprint: string;\n}\n\nexport interface Session {\n readonly authToken: string | null;\n readonly containerId: string | null;\n /** Server-backed personal organization; independent of the active org. */\n readonly defaultOrganizationId: string | null;\n readonly isAuthenticated: boolean;\n /**\n * Platform-operator flag reported by the server at login. It only decides\n * whether the root console is offered; the API enforces root access itself.\n */\n readonly isRoot: boolean;\n readonly organizationId: string | null;\n readonly snapshot: SessionSnapshot;\n /** Controls server replication without changing network connectivity. */\n readonly syncEnabled: boolean;\n readonly userId: string | null;\n /**\n * Whether `userId` was acknowledged by the server for the active signing\n * identity (a successful login or a fingerprint-bound host restore). A user\n * ID chosen locally through `setUserId` is not, and hosts must not persist\n * it as this identity's account.\n */\n readonly userIdAcknowledged: boolean;\n bootstrapLocalRootContainer(): Promise<{\n containerId: string;\n created: boolean;\n }>;\n clearRemoteSyncState(\n organizationId: string,\n ): Promise<ClearRemoteSyncStateResult>;\n createOrganization(\n options?: CreateOrganizationOptions,\n ): Promise<SessionCreateOrganizationResult | null>;\n completeNativeSubscriptionRestoreOrganization(\n organizationId: string,\n ): Promise<boolean>;\n destroySession(sessionId: string): Promise<boolean>;\n listSessions(): Promise<UserSession[]>;\n login(challengeHex?: string | undefined): Promise<boolean>;\n logout(): void;\n logoutRemote(): Promise<boolean>;\n prepareNativeSubscriptionRestoreOrganization(\n options?: CreateOrganizationOptions,\n ): Promise<SessionCreateOrganizationResult | null>;\n registerIdentity(\n options?: RegisterIdentityOptions,\n ): Promise<SessionRegistrationResult | SessionRegistrationRefusal | null>;\n recoverPurgedOrganization(\n organizationId: string,\n options?: CreateOrganizationOptions,\n ): Promise<SessionRecoverOrganizationResult | null>;\n setAuthToken(authToken: string | null): void;\n setContainerId(containerId: string | null): void;\n /** Host-restored context must match the active signing identity; conflicting user acknowledgments throw. */\n setContext(context: SessionContext): void;\n setOrganizationId(organizationId: string | null): void;\n setSyncEnabled(enabled: boolean): void;\n setUserId(userId: string | null): void;\n subscribe(listener: SessionListener): () => void;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SecurityIncidentReporter } from "../data/securityIncidents.js";
|
|
1
|
+
import type { SecurityIncidentReporter } from "../data/shared/securityIncidents.js";
|
|
2
2
|
import { type TrustedUserIdentityResolver, type TrustedUserIdentityService } from "../data/trustedUserIdentity/index.js";
|
|
3
3
|
export interface ResolvedUserIdentity {
|
|
4
4
|
encapsulationKeyFingerprint: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userIdentities.js","sourceRoot":"","sources":["userIdentities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,oCAAoC,EAAE,MAAM,4DAA4D,CAAC;AAClH,OAAO,EAAE,gCAAgC,EAAE,MAAM,4CAA4C,CAAC;AAE9F,OAAO,EACL,iBAAiB,EACjB,kCAAkC,GAInC,MAAM,6BAA6B,CAAC;AAqBrC,SAAS,kBAAkB,CACzB,QAA6B;IAE7B,OAAO;QACL,2BAA2B,EAAE,QAAQ,CAAC,2BAA2B;QACjE,sBAAsB,EAAE,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACtE,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB;QACrD,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC1D,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KASpC;IACC,MAAM,0BAA0B,GAAG,kCAAkC,CACnE,KAAK,CAAC,0BAA0B,CACjC,CAAC;IACF,OAAO;QACL,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC;QAC9D,KAAK,CAAC,UAAU,CAAC,IAAI;YACnB,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC3C,OAAO,gCAAgC,CACrC,KAAK,CAAC,sBAAsB,EAC5B;gBACE,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,MAAM;gBAClB,SAAS,EAAE,2BAA2B;gBACtC,cAAc,EAAE,KAAK,CAAC,iBAAiB,EAAE;aAC1C,EACD,KAAK,IAAI,EAAE,CACT,kBAAkB,CAAC,MAAM,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CACjE,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,MAAM;YACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACjE,OAAO,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,MAAM;YAClB,KAAK,CAAC,GAAG,CAAC,qCAAqC,MAAM,EAAE,CAAC,CAAC;YACzD,IAAI,QAA0D,CAAC;YAC/D,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,0BAA0B,CAAC,MAAM,CAAC,CAAC;YACtD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,CAAC,KAAK,YAAY,oCAAoC,CAAC;oBAC1D,MAAM,KAAK,CAAC;gBACd,KAAK,CAAC,GAAG,CACP,qBAAqB,MAAM,oBAAoB,KAAK,CAAC,OAAO,EAAE,CAC/D,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport { ProjectionDependencyUnavailableError } from \"../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { runWithSecurityIncidentReporting } from \"../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../data/securityIncidents\";\nimport {\n parseIdentityLink,\n requireTrustedUserIdentityResolver,\n type TrustedUserIdentity,\n type TrustedUserIdentityResolver,\n type TrustedUserIdentityService,\n} from \"../data/trustedUserIdentity\";\n\nexport interface ResolvedUserIdentity {\n encapsulationKeyFingerprint: string;\n encapsulationPublicKey: string;\n signingKeyFingerprint: string;\n signingPublicKey: string;\n userId: string;\n}\n\nexport interface UserIdentities {\n /** Share a stable link derived exclusively from this user's local keys. */\n createLink(appUrl: string): Promise<string>;\n /** Compare an independently received link before durably pinning either key. */\n verifyLink(link: string): Promise<ResolvedUserIdentity>;\n /** Read an existing durable pin without fetching or trusting a new identity. */\n resolvePinned(userId: string): Promise<ResolvedUserIdentity | null>;\n /** `null` when the user is unknown or currently unresolvable; integrity failures throw. */\n resolve(userId: string): Promise<ResolvedUserIdentity | null>;\n}\n\nfunction toResolvedIdentity(\n identity: TrustedUserIdentity,\n): ResolvedUserIdentity {\n return {\n encapsulationKeyFingerprint: identity.encapsulationKeyFingerprint,\n encapsulationPublicKey: bytesToBase64(identity.encapsulationPublicKey),\n signingKeyFingerprint: identity.signingKeyFingerprint,\n signingPublicKey: bytesToBase64(identity.signingPublicKey),\n userId: identity.userId,\n };\n}\n\nexport function createUserIdentities(input: {\n getOrganizationId: () => string | null;\n reportSecurityIncident: SecurityIncidentReporter;\n identityLinks: Pick<\n TrustedUserIdentityService,\n \"createLink\" | \"verifyLink\" | \"resolvePinned\"\n >;\n log: (message: string) => void;\n resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}): UserIdentities {\n const resolveTrustedUserIdentity = requireTrustedUserIdentityResolver(\n input.resolveTrustedUserIdentity,\n );\n return {\n createLink: (appUrl) => input.identityLinks.createLink(appUrl),\n async verifyLink(link) {\n const { userId } = parseIdentityLink(link);\n return runWithSecurityIncidentReporting(\n input.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.verify_link\",\n organizationId: input.getOrganizationId(),\n },\n async () =>\n toResolvedIdentity(await input.identityLinks.verifyLink(link)),\n );\n },\n async resolvePinned(userId) {\n const identity = await input.identityLinks.resolvePinned(userId);\n return identity ? toResolvedIdentity(identity) : null;\n },\n async resolve(userId) {\n input.log(`Loading user identity for userId: ${userId}`);\n let identity: Awaited<ReturnType<TrustedUserIdentityResolver>>;\n try {\n identity = await resolveTrustedUserIdentity(userId);\n } catch (error) {\n if (!(error instanceof ProjectionDependencyUnavailableError))\n throw error;\n input.log(\n `User identity for ${userId} is unavailable: ${error.message}`,\n );\n return null;\n }\n if (!identity) {\n return null;\n }\n\n return toResolvedIdentity(identity);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"userIdentities.js","sourceRoot":"","sources":["userIdentities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,oCAAoC,EAAE,MAAM,4DAA4D,CAAC;AAClH,OAAO,EAAE,gCAAgC,EAAE,MAAM,4CAA4C,CAAC;AAE9F,OAAO,EACL,iBAAiB,EACjB,kCAAkC,GAInC,MAAM,6BAA6B,CAAC;AAqBrC,SAAS,kBAAkB,CACzB,QAA6B;IAE7B,OAAO;QACL,2BAA2B,EAAE,QAAQ,CAAC,2BAA2B;QACjE,sBAAsB,EAAE,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACtE,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB;QACrD,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC1D,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KASpC;IACC,MAAM,0BAA0B,GAAG,kCAAkC,CACnE,KAAK,CAAC,0BAA0B,CACjC,CAAC;IACF,OAAO;QACL,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC;QAC9D,KAAK,CAAC,UAAU,CAAC,IAAI;YACnB,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC3C,OAAO,gCAAgC,CACrC,KAAK,CAAC,sBAAsB,EAC5B;gBACE,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,MAAM;gBAClB,SAAS,EAAE,2BAA2B;gBACtC,cAAc,EAAE,KAAK,CAAC,iBAAiB,EAAE;aAC1C,EACD,KAAK,IAAI,EAAE,CACT,kBAAkB,CAAC,MAAM,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CACjE,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,MAAM;YACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACjE,OAAO,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,MAAM;YAClB,KAAK,CAAC,GAAG,CAAC,qCAAqC,MAAM,EAAE,CAAC,CAAC;YACzD,IAAI,QAA0D,CAAC;YAC/D,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,0BAA0B,CAAC,MAAM,CAAC,CAAC;YACtD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,CAAC,KAAK,YAAY,oCAAoC,CAAC;oBAC1D,MAAM,KAAK,CAAC;gBACd,KAAK,CAAC,GAAG,CACP,qBAAqB,MAAM,oBAAoB,KAAK,CAAC,OAAO,EAAE,CAC/D,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport { ProjectionDependencyUnavailableError } from \"../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { runWithSecurityIncidentReporting } from \"../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../data/shared/securityIncidents\";\nimport {\n parseIdentityLink,\n requireTrustedUserIdentityResolver,\n type TrustedUserIdentity,\n type TrustedUserIdentityResolver,\n type TrustedUserIdentityService,\n} from \"../data/trustedUserIdentity\";\n\nexport interface ResolvedUserIdentity {\n encapsulationKeyFingerprint: string;\n encapsulationPublicKey: string;\n signingKeyFingerprint: string;\n signingPublicKey: string;\n userId: string;\n}\n\nexport interface UserIdentities {\n /** Share a stable link derived exclusively from this user's local keys. */\n createLink(appUrl: string): Promise<string>;\n /** Compare an independently received link before durably pinning either key. */\n verifyLink(link: string): Promise<ResolvedUserIdentity>;\n /** Read an existing durable pin without fetching or trusting a new identity. */\n resolvePinned(userId: string): Promise<ResolvedUserIdentity | null>;\n /** `null` when the user is unknown or currently unresolvable; integrity failures throw. */\n resolve(userId: string): Promise<ResolvedUserIdentity | null>;\n}\n\nfunction toResolvedIdentity(\n identity: TrustedUserIdentity,\n): ResolvedUserIdentity {\n return {\n encapsulationKeyFingerprint: identity.encapsulationKeyFingerprint,\n encapsulationPublicKey: bytesToBase64(identity.encapsulationPublicKey),\n signingKeyFingerprint: identity.signingKeyFingerprint,\n signingPublicKey: bytesToBase64(identity.signingPublicKey),\n userId: identity.userId,\n };\n}\n\nexport function createUserIdentities(input: {\n getOrganizationId: () => string | null;\n reportSecurityIncident: SecurityIncidentReporter;\n identityLinks: Pick<\n TrustedUserIdentityService,\n \"createLink\" | \"verifyLink\" | \"resolvePinned\"\n >;\n log: (message: string) => void;\n resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}): UserIdentities {\n const resolveTrustedUserIdentity = requireTrustedUserIdentityResolver(\n input.resolveTrustedUserIdentity,\n );\n return {\n createLink: (appUrl) => input.identityLinks.createLink(appUrl),\n async verifyLink(link) {\n const { userId } = parseIdentityLink(link);\n return runWithSecurityIncidentReporting(\n input.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.verify_link\",\n organizationId: input.getOrganizationId(),\n },\n async () =>\n toResolvedIdentity(await input.identityLinks.verifyLink(link)),\n );\n },\n async resolvePinned(userId) {\n const identity = await input.identityLinks.resolvePinned(userId);\n return identity ? toResolvedIdentity(identity) : null;\n },\n async resolve(userId) {\n input.log(`Loading user identity for userId: ${userId}`);\n let identity: Awaited<ReturnType<TrustedUserIdentityResolver>>;\n try {\n identity = await resolveTrustedUserIdentity(userId);\n } catch (error) {\n if (!(error instanceof ProjectionDependencyUnavailableError))\n throw error;\n input.log(\n `User identity for ${userId} is unavailable: ${error.message}`,\n );\n return null;\n }\n if (!identity) {\n return null;\n }\n\n return toResolvedIdentity(identity);\n },\n };\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ApiClient } from "../internal/api-client/index.js";
|
|
2
2
|
import type { DocumentProjectorRegistry } from "../data/documents/documentKinds.js";
|
|
3
|
-
import type { DomainScope } from "../data/domainScope.js";
|
|
4
3
|
import type { PrincipalHistoryProtectionLease } from "../data/principals/principalHistoryProtection.js";
|
|
5
|
-
import type {
|
|
4
|
+
import type { DomainScope } from "../data/shared/domainScope.js";
|
|
5
|
+
import type { SecurityIncidentReporter } from "../data/shared/securityIncidents.js";
|
|
6
6
|
import { type LocalUserIdentityCandidate, type TrustedUserIdentityResolver, type TrustedUserIdentityService } from "../data/trustedUserIdentity/index.js";
|
|
7
7
|
import type { ContainerContentsRootAdopter } from "../workflows/container-contents/runtime.js";
|
|
8
8
|
import { type ProvisionedPrincipalHistoryPrimer } from "../workflows/registration/provisionedPrincipalHistory.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflowRuntime.js","sourceRoot":"","sources":["workflowRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { DocumentProjectorRegistry } from \"../data/documents/documentKinds\";\nimport type { DomainScope } from \"../data/domainScope\";\nimport { runWithSecurityIncidentReporting } from \"../data/keyingProjectionVerification/error\";\nimport type { PrincipalHistoryProtectionLease } from \"../data/principals/principalHistoryProtection\";\nimport type { SecurityIncidentReporter } from \"../data/securityIncidents\";\nimport { type ExecSql, unavailableExecSql } from \"../data/sqlite/sqlSchema\";\nimport {\n createApiUserIdentitySource,\n createTrustedUserIdentityService,\n type LocalUserIdentityCandidate,\n loadPinnedUserIdentity,\n type TrustedUserIdentityResolver,\n type TrustedUserIdentityService,\n} from \"../data/trustedUserIdentity\";\nimport type { ContainerContentsRootAdopter } from \"../workflows/container-contents/runtime\";\nimport {\n createProvisionedPrincipalHistoryPrimer,\n type ProvisionedPrincipalHistoryPrimer,\n} from \"../workflows/registration/provisionedPrincipalHistory\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeGroups,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../workflows/runtimeInput\";\nimport type { Blobs } from \"./blobs\";\nimport type { Database } from \"./database\";\nimport type { Events } from \"./events\";\nimport type { Identity } from \"./identity\";\nimport { createListenerSet } from \"./listenerSet\";\nimport type { Network } from \"./network\";\nimport {\n createPrincipalHistoryProtectionCustody,\n type PrincipalHistoryKeyProvider,\n} from \"./principalHistoryProtection\";\nimport {\n createPrincipalMutationApiCustody,\n type PrincipalMutationApi,\n} from \"./principalMutationApi\";\nimport { adoptSessionRootContainer } from \"./rootContainerAdoption\";\nimport { acknowledgedSessionRoot } from \"./session/sessionRootAuthority\";\nimport type { Session, SessionSnapshot } from \"./session/sessionTypes\";\nimport type { SyncBillingGate } from \"./syncBillingGate\";\n\ntype HostWorkflowRuntimeUtilInput = Omit<\n WorkflowRuntimeUtilInput,\n \"reportSecurityIncident\"\n>;\n\nexport interface WorkflowRuntimeInput\n extends Omit<WorkflowRuntimeGroups, \"util\"> {\n readonly util: HostWorkflowRuntimeUtilInput;\n}\n\nexport type RuntimeListener = () => void;\n\nexport interface Runtime {\n readonly version: number;\n input(containerId?: string | null | undefined): WorkflowRuntimeInput;\n subscribe(listener: RuntimeListener): () => void;\n}\n\nexport interface InternalWorkflowRuntimeInput extends WorkflowRuntimeGroups {\n readonly apiClient: PrincipalMutationApi;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n}\n\nexport interface InternalRuntime {\n identityLinks: Pick<\n TrustedUserIdentityService,\n \"createLink\" | \"verifyLink\" | \"resolvePinned\"\n >;\n retirePrincipalHistoryProtection(): void;\n readonly sessionGeneration: number;\n readonly adoptRootContainer: ContainerContentsRootAdopter;\n readonly publicRuntime: Runtime;\n boundUserId(signingKeyFingerprint: string): Promise<string | null>;\n pinLocalUserIdentity(\n userId: string,\n candidate: LocalUserIdentityCandidate,\n ): Promise<void>;\n readonly primeProvisionedPrincipalHistory: ProvisionedPrincipalHistoryPrimer;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\ninterface WorkflowRuntimeDependencies {\n api: ApiClient;\n blobs: Blobs;\n database: Database;\n documentProjectors: DocumentProjectorRegistry;\n events: Events;\n getDomainScope: () => DomainScope;\n identity: Identity;\n identityTrustDomain: string | null;\n log: (message: string) => void;\n logError: (message: string | Error, cause?: unknown) => void;\n network: Network;\n peerScope?: string | null;\n principalHistoryKeyProvider?: PrincipalHistoryKeyProvider | undefined;\n principalMutationTimeoutMs?: number | undefined;\n reportSecurityIncident: SecurityIncidentReporter;\n session: Session;\n syncBillingGate?: SyncBillingGate | undefined;\n}\n\nfunction createRuntimeMutationApi(\n dependencies: WorkflowRuntimeDependencies,\n readGeneration: () => number,\n) {\n return createPrincipalMutationApiCustody({\n api: dependencies.api,\n principalMutationTimeoutMs: dependencies.principalMutationTimeoutMs,\n readScope: () => {\n const { signingKeyPair, signingFingerprint } = dependencies.identity;\n const { userId, isAuthenticated } = dependencies.session;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !isAuthenticated ||\n !userId ||\n !signingKeyPair ||\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n database: dependencies.getDomainScope(),\n execSql: dependencies.database.requireExecSql(\"principal mutation\"),\n generation: readGeneration(),\n identityTrustDomain,\n signingFingerprint,\n signingKeyPair,\n userId,\n };\n },\n });\n}\n\nfunction localIdentityCandidate(\n identity: Identity,\n): LocalUserIdentityCandidate | null {\n const { encapsulationKeyPair, signingKeyPair } = identity;\n if (!encapsulationKeyPair || !signingKeyPair) return null;\n return {\n encapsulationPublicKey: encapsulationKeyPair.publicKey,\n signingKeyFingerprint: identity.signingFingerprint,\n signingPublicKey: signingKeyPair.signingPublicKey,\n };\n}\n\n/** Priming reads the runtime's database, identity and trust pins; it pins nothing. */\nfunction createRuntimeProvisioningPrimer(\n dependencies: WorkflowRuntimeDependencies,\n bindLease: () => PrincipalHistoryProtectionLease | undefined,\n readyExecSql: () => ExecSql | null,\n): ProvisionedPrincipalHistoryPrimer {\n return createProvisionedPrincipalHistoryPrimer({\n bindLease,\n execSqlFor: (database) =>\n dependencies.database.client === database ? readyExecSql() : null,\n loadPinnedIdentity: async (execSql, userId) =>\n dependencies.identityTrustDomain\n ? loadPinnedUserIdentity({\n execSql,\n identityTrustDomain: dependencies.identityTrustDomain,\n userId,\n })\n : null,\n logError: dependencies.logError,\n signingFingerprint: () => dependencies.identity.signingFingerprint,\n });\n}\n\nexport function createRuntime(\n dependencies: WorkflowRuntimeDependencies,\n): InternalRuntime {\n const readyExecSql = () =>\n dependencies.database.status === \"ready\"\n ? dependencies.database.requireExecSql(\"trusted user identity\")\n : null;\n const trustedUserIdentityService = createTrustedUserIdentityService({\n getExecSql: readyExecSql,\n getLocalIdentity: () => localIdentityCandidate(dependencies.identity),\n getLocalUserId: () => dependencies.session.userId,\n identityTrustDomain: dependencies.identityTrustDomain,\n remoteSource: createApiUserIdentitySource(dependencies.api),\n });\n const resolveTrustedUserIdentity: TrustedUserIdentityResolver = (userId) =>\n runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.resolve\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.resolve(userId),\n );\n const runtimeSubscription = createRuntimeSubscription(dependencies);\n const historyProtection = createPrincipalHistoryProtectionCustody({\n keyProvider: dependencies.principalHistoryKeyProvider,\n readScope: () => {\n const signingFingerprint = dependencies.identity.signingFingerprint;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n signingFingerprint,\n identityTrustDomain,\n database: dependencies.getDomainScope(),\n generation: runtimeSubscription.recoveryGeneration,\n };\n },\n });\n const runtimeInput = createRuntimeInputFactory(\n dependencies,\n resolveTrustedUserIdentity,\n historyProtection.bind,\n createRuntimeMutationApi(\n dependencies,\n () => runtimeSubscription.mutationGeneration,\n ).bind,\n );\n\n return {\n identityLinks: trustedUserIdentityService,\n retirePrincipalHistoryProtection: historyProtection.retire,\n get sessionGeneration() {\n return runtimeSubscription.sessionGeneration;\n },\n adoptRootContainer: (input) =>\n adoptSessionRootContainer(dependencies, input),\n boundUserId: (signingKeyFingerprint) =>\n trustedUserIdentityService.boundUserId(signingKeyFingerprint),\n async pinLocalUserIdentity(userId, candidate) {\n await runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.pin_local\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.pinLocal(userId, candidate),\n );\n },\n primeProvisionedPrincipalHistory: createRuntimeProvisioningPrimer(\n dependencies,\n historyProtection.bind,\n readyExecSql,\n ),\n publicRuntime: {\n get version() {\n return runtimeSubscription.version;\n },\n input: runtimeInput.hostInput,\n subscribe: runtimeSubscription.subscribe,\n },\n workflowInput: runtimeInput.workflowInput,\n };\n}\n\nfunction createRuntimeSubscription(dependencies: WorkflowRuntimeDependencies) {\n const listeners = createListenerSet();\n let version = 0;\n let sessionGeneration = 0;\n let recoveryGeneration = 0;\n let mutationGeneration = 0;\n let sessionSnapshot = dependencies.session.snapshot;\n const notifyListeners = () => {\n version += 1;\n listeners.notify();\n };\n\n const notifyAuthority = () => {\n recoveryGeneration += 1;\n mutationGeneration += 1;\n notifyListeners();\n };\n dependencies.database.subscribe(notifyAuthority);\n dependencies.events.subscribe(notifyListeners);\n dependencies.identity.subscribe(notifyAuthority);\n dependencies.network.subscribe(() => notifyListeners());\n dependencies.session.subscribe(() => {\n const next = dependencies.session.snapshot;\n if (sessionAuthorityChanged(sessionSnapshot, next)) {\n sessionGeneration += 1;\n recoveryGeneration += 1;\n }\n if (sessionScopeChanged(sessionSnapshot, next)) mutationGeneration += 1;\n sessionSnapshot = next;\n notifyListeners();\n });\n dependencies.syncBillingGate?.subscribe(notifyListeners);\n\n return {\n get mutationGeneration() {\n return mutationGeneration;\n },\n get recoveryGeneration() {\n return recoveryGeneration;\n },\n get sessionGeneration() {\n return sessionGeneration;\n },\n get version() {\n return version;\n },\n subscribe(listener: RuntimeListener): () => void {\n return listeners.subscribe(listener);\n },\n };\n}\n\ninterface RuntimeInputFactory {\n hostInput(containerId?: string | null | undefined): WorkflowRuntimeInput;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\nfunction sessionAuthInput({\n session,\n identity,\n}: WorkflowRuntimeDependencies): WorkflowRuntimeAuthInput {\n const signingFingerprint = identity.snapshot.signingFingerprint;\n return {\n defaultOrganizationId: session.defaultOrganizationId,\n rootContainerId: acknowledgedSessionRoot(session, signingFingerprint),\n isAuthenticated: session.isAuthenticated,\n isRoot: session.isRoot,\n organizationId: session.organizationId,\n userId: session.userId,\n };\n}\n\n/** Fields whose change invalidates work keyed on the session's authority. */\nfunction sessionAuthorityChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.authToken !== previous.authToken || sessionScopeChanged(previous, next)\n );\n}\n\n// A transport token renewal cannot turn a definite write refusal into saved work.\n// Journal custody still expires on every change to its identity or storage scope.\nfunction sessionScopeChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.isAuthenticated !== previous.isAuthenticated ||\n next.isRoot !== previous.isRoot ||\n next.organizationId !== previous.organizationId ||\n next.userId !== previous.userId\n );\n}\n\nfunction createRuntimeInputFactory(\n dependencies: WorkflowRuntimeDependencies,\n resolveTrustedUserIdentity: TrustedUserIdentityResolver,\n bindHistoryProtection: () => PrincipalHistoryProtectionLease | undefined,\n bindMutationApi: () => PrincipalMutationApi,\n): RuntimeInputFactory {\n let auth: WorkflowRuntimeAuthInput | undefined;\n let crypto: WorkflowRuntimeCryptoInput | undefined;\n let infra: WorkflowRuntimeInfraInput | undefined;\n let state: WorkflowRuntimeStateInput | undefined;\n let util: WorkflowRuntimeUtilInput | undefined;\n let hostUtil: HostWorkflowRuntimeUtilInput | undefined;\n\n const workflowInput = (\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput => {\n const dbStatus = dependencies.database.status;\n const execSql =\n dbStatus === \"ready\"\n ? dependencies.database.requireExecSql(\"tearleads.runtime.input\")\n : unavailableExecSql;\n const nextContainerId =\n (containerId === undefined\n ? dependencies.session.containerId\n : containerId) ?? null;\n\n auth = reuseIfShallowEqual(auth, sessionAuthInput(dependencies));\n crypto = reuseIfShallowEqual(crypto, {\n encapsulationKeyPair: dependencies.identity.encapsulationKeyPair,\n signingFingerprint: dependencies.identity.signingFingerprint,\n signingKeyPair: dependencies.identity.signingKeyPair,\n });\n infra = reuseIfShallowEqual(infra, {\n blobStore: dependencies.blobs.store,\n dbStatus,\n documentProjectors: dependencies.documentProjectors,\n // Runtime consumers branch on dbStatus before touching SQLite. The\n // fallback preserves the runtime shape and catches lifecycle bugs.\n execSql,\n });\n state = reuseIfShallowEqual(state, {\n containerId: nextContainerId,\n domainScope: dependencies.getDomainScope(),\n events: dependencies.events.events,\n // Resolved sync-online: workflows treat local-only mode exactly like being\n // offline (no server I/O), while `tearleads.network` stays the truthful\n // connectivity signal for host/UI. See Session.syncEnabled.\n online: dependencies.network.online && dependencies.session.syncEnabled,\n peerScope: dependencies.peerScope ?? null,\n serverEventsConnectionGeneration:\n dependencies.events.connectionGeneration,\n });\n if (\n !util ||\n util.log !== dependencies.log ||\n util.logError !== dependencies.logError ||\n util.reportSecurityIncident !== dependencies.reportSecurityIncident\n ) {\n util = {\n isRemoteSyncBlocked: (organizationId) =>\n dependencies.syncBillingGate?.isBlockedForOrganization(\n organizationId,\n ) ?? false,\n log: dependencies.log,\n logError: dependencies.logError,\n reportSecurityIncident: dependencies.reportSecurityIncident,\n };\n }\n\n return {\n apiClient: bindMutationApi(),\n auth,\n crypto,\n infra,\n state,\n util,\n resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: bindHistoryProtection(),\n };\n };\n\n return {\n hostInput(containerId) {\n const {\n apiClient: _apiClient,\n resolveTrustedUserIdentity: _resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: _withPrincipalHistoryProtection,\n util: workflowUtil,\n ...input\n } = workflowInput(containerId);\n hostUtil = reuseIfShallowEqual(hostUtil, {\n isRemoteSyncBlocked: workflowUtil.isRemoteSyncBlocked,\n log: workflowUtil.log,\n logError: workflowUtil.logError,\n });\n return { ...input, util: hostUtil };\n },\n workflowInput,\n };\n}\n\n/**\n * Reuses the current runtime-input group when every field of the freshly\n * constructed `next` literal is reference-equal, so unchanged groups keep a\n * stable identity across runtime reads.\n */\nfunction reuseIfShallowEqual<T extends object>(\n current: T | undefined,\n next: T,\n): T {\n if (!current) {\n return next;\n }\n for (const key of Object.keys(next)) {\n if (Reflect.get(current, key) !== Reflect.get(next, key)) {\n return next;\n }\n }\n return current;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workflowRuntime.js","sourceRoot":"","sources":["workflowRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { DocumentProjectorRegistry } from \"../data/documents/documentKinds\";\nimport { runWithSecurityIncidentReporting } from \"../data/keyingProjectionVerification/error\";\nimport type { PrincipalHistoryProtectionLease } from \"../data/principals/principalHistoryProtection\";\nimport type { DomainScope } from \"../data/shared/domainScope\";\nimport type { SecurityIncidentReporter } from \"../data/shared/securityIncidents\";\nimport { type ExecSql, unavailableExecSql } from \"../data/sqlite/sqlSchema\";\nimport {\n createApiUserIdentitySource,\n createTrustedUserIdentityService,\n type LocalUserIdentityCandidate,\n loadPinnedUserIdentity,\n type TrustedUserIdentityResolver,\n type TrustedUserIdentityService,\n} from \"../data/trustedUserIdentity\";\nimport type { ContainerContentsRootAdopter } from \"../workflows/container-contents/runtime\";\nimport {\n createProvisionedPrincipalHistoryPrimer,\n type ProvisionedPrincipalHistoryPrimer,\n} from \"../workflows/registration/provisionedPrincipalHistory\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeGroups,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../workflows/runtimeInput\";\nimport type { Blobs } from \"./blobs\";\nimport type { Database } from \"./database\";\nimport type { Events } from \"./events\";\nimport type { Identity } from \"./identity\";\nimport { createListenerSet } from \"./listenerSet\";\nimport type { Network } from \"./network\";\nimport {\n createPrincipalHistoryProtectionCustody,\n type PrincipalHistoryKeyProvider,\n} from \"./principalHistoryProtection\";\nimport {\n createPrincipalMutationApiCustody,\n type PrincipalMutationApi,\n} from \"./principalMutationApi\";\nimport { adoptSessionRootContainer } from \"./rootContainerAdoption\";\nimport { acknowledgedSessionRoot } from \"./session/sessionRootAuthority\";\nimport type { Session, SessionSnapshot } from \"./session/sessionTypes\";\nimport type { SyncBillingGate } from \"./syncBillingGate\";\n\ntype HostWorkflowRuntimeUtilInput = Omit<\n WorkflowRuntimeUtilInput,\n \"reportSecurityIncident\"\n>;\n\nexport interface WorkflowRuntimeInput\n extends Omit<WorkflowRuntimeGroups, \"util\"> {\n readonly util: HostWorkflowRuntimeUtilInput;\n}\n\nexport type RuntimeListener = () => void;\n\nexport interface Runtime {\n readonly version: number;\n input(containerId?: string | null | undefined): WorkflowRuntimeInput;\n subscribe(listener: RuntimeListener): () => void;\n}\n\nexport interface InternalWorkflowRuntimeInput extends WorkflowRuntimeGroups {\n readonly apiClient: PrincipalMutationApi;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n}\n\nexport interface InternalRuntime {\n identityLinks: Pick<\n TrustedUserIdentityService,\n \"createLink\" | \"verifyLink\" | \"resolvePinned\"\n >;\n retirePrincipalHistoryProtection(): void;\n readonly sessionGeneration: number;\n readonly adoptRootContainer: ContainerContentsRootAdopter;\n readonly publicRuntime: Runtime;\n boundUserId(signingKeyFingerprint: string): Promise<string | null>;\n pinLocalUserIdentity(\n userId: string,\n candidate: LocalUserIdentityCandidate,\n ): Promise<void>;\n readonly primeProvisionedPrincipalHistory: ProvisionedPrincipalHistoryPrimer;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\ninterface WorkflowRuntimeDependencies {\n api: ApiClient;\n blobs: Blobs;\n database: Database;\n documentProjectors: DocumentProjectorRegistry;\n events: Events;\n getDomainScope: () => DomainScope;\n identity: Identity;\n identityTrustDomain: string | null;\n log: (message: string) => void;\n logError: (message: string | Error, cause?: unknown) => void;\n network: Network;\n peerScope?: string | null;\n principalHistoryKeyProvider?: PrincipalHistoryKeyProvider | undefined;\n principalMutationTimeoutMs?: number | undefined;\n reportSecurityIncident: SecurityIncidentReporter;\n session: Session;\n syncBillingGate?: SyncBillingGate | undefined;\n}\n\nfunction createRuntimeMutationApi(\n dependencies: WorkflowRuntimeDependencies,\n readGeneration: () => number,\n) {\n return createPrincipalMutationApiCustody({\n api: dependencies.api,\n principalMutationTimeoutMs: dependencies.principalMutationTimeoutMs,\n readScope: () => {\n const { signingKeyPair, signingFingerprint } = dependencies.identity;\n const { userId, isAuthenticated } = dependencies.session;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !isAuthenticated ||\n !userId ||\n !signingKeyPair ||\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n database: dependencies.getDomainScope(),\n execSql: dependencies.database.requireExecSql(\"principal mutation\"),\n generation: readGeneration(),\n identityTrustDomain,\n signingFingerprint,\n signingKeyPair,\n userId,\n };\n },\n });\n}\n\nfunction localIdentityCandidate(\n identity: Identity,\n): LocalUserIdentityCandidate | null {\n const { encapsulationKeyPair, signingKeyPair } = identity;\n if (!encapsulationKeyPair || !signingKeyPair) return null;\n return {\n encapsulationPublicKey: encapsulationKeyPair.publicKey,\n signingKeyFingerprint: identity.signingFingerprint,\n signingPublicKey: signingKeyPair.signingPublicKey,\n };\n}\n\n/** Priming reads the runtime's database, identity and trust pins; it pins nothing. */\nfunction createRuntimeProvisioningPrimer(\n dependencies: WorkflowRuntimeDependencies,\n bindLease: () => PrincipalHistoryProtectionLease | undefined,\n readyExecSql: () => ExecSql | null,\n): ProvisionedPrincipalHistoryPrimer {\n return createProvisionedPrincipalHistoryPrimer({\n bindLease,\n execSqlFor: (database) =>\n dependencies.database.client === database ? readyExecSql() : null,\n loadPinnedIdentity: async (execSql, userId) =>\n dependencies.identityTrustDomain\n ? loadPinnedUserIdentity({\n execSql,\n identityTrustDomain: dependencies.identityTrustDomain,\n userId,\n })\n : null,\n logError: dependencies.logError,\n signingFingerprint: () => dependencies.identity.signingFingerprint,\n });\n}\n\nexport function createRuntime(\n dependencies: WorkflowRuntimeDependencies,\n): InternalRuntime {\n const readyExecSql = () =>\n dependencies.database.status === \"ready\"\n ? dependencies.database.requireExecSql(\"trusted user identity\")\n : null;\n const trustedUserIdentityService = createTrustedUserIdentityService({\n getExecSql: readyExecSql,\n getLocalIdentity: () => localIdentityCandidate(dependencies.identity),\n getLocalUserId: () => dependencies.session.userId,\n identityTrustDomain: dependencies.identityTrustDomain,\n remoteSource: createApiUserIdentitySource(dependencies.api),\n });\n const resolveTrustedUserIdentity: TrustedUserIdentityResolver = (userId) =>\n runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.resolve\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.resolve(userId),\n );\n const runtimeSubscription = createRuntimeSubscription(dependencies);\n const historyProtection = createPrincipalHistoryProtectionCustody({\n keyProvider: dependencies.principalHistoryKeyProvider,\n readScope: () => {\n const signingFingerprint = dependencies.identity.signingFingerprint;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n signingFingerprint,\n identityTrustDomain,\n database: dependencies.getDomainScope(),\n generation: runtimeSubscription.recoveryGeneration,\n };\n },\n });\n const runtimeInput = createRuntimeInputFactory(\n dependencies,\n resolveTrustedUserIdentity,\n historyProtection.bind,\n createRuntimeMutationApi(\n dependencies,\n () => runtimeSubscription.mutationGeneration,\n ).bind,\n );\n\n return {\n identityLinks: trustedUserIdentityService,\n retirePrincipalHistoryProtection: historyProtection.retire,\n get sessionGeneration() {\n return runtimeSubscription.sessionGeneration;\n },\n adoptRootContainer: (input) =>\n adoptSessionRootContainer(dependencies, input),\n boundUserId: (signingKeyFingerprint) =>\n trustedUserIdentityService.boundUserId(signingKeyFingerprint),\n async pinLocalUserIdentity(userId, candidate) {\n await runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.pin_local\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.pinLocal(userId, candidate),\n );\n },\n primeProvisionedPrincipalHistory: createRuntimeProvisioningPrimer(\n dependencies,\n historyProtection.bind,\n readyExecSql,\n ),\n publicRuntime: {\n get version() {\n return runtimeSubscription.version;\n },\n input: runtimeInput.hostInput,\n subscribe: runtimeSubscription.subscribe,\n },\n workflowInput: runtimeInput.workflowInput,\n };\n}\n\nfunction createRuntimeSubscription(dependencies: WorkflowRuntimeDependencies) {\n const listeners = createListenerSet();\n let version = 0;\n let sessionGeneration = 0;\n let recoveryGeneration = 0;\n let mutationGeneration = 0;\n let sessionSnapshot = dependencies.session.snapshot;\n const notifyListeners = () => {\n version += 1;\n listeners.notify();\n };\n\n const notifyAuthority = () => {\n recoveryGeneration += 1;\n mutationGeneration += 1;\n notifyListeners();\n };\n dependencies.database.subscribe(notifyAuthority);\n dependencies.events.subscribe(notifyListeners);\n dependencies.identity.subscribe(notifyAuthority);\n dependencies.network.subscribe(() => notifyListeners());\n dependencies.session.subscribe(() => {\n const next = dependencies.session.snapshot;\n if (sessionAuthorityChanged(sessionSnapshot, next)) {\n sessionGeneration += 1;\n recoveryGeneration += 1;\n }\n if (sessionScopeChanged(sessionSnapshot, next)) mutationGeneration += 1;\n sessionSnapshot = next;\n notifyListeners();\n });\n dependencies.syncBillingGate?.subscribe(notifyListeners);\n\n return {\n get mutationGeneration() {\n return mutationGeneration;\n },\n get recoveryGeneration() {\n return recoveryGeneration;\n },\n get sessionGeneration() {\n return sessionGeneration;\n },\n get version() {\n return version;\n },\n subscribe(listener: RuntimeListener): () => void {\n return listeners.subscribe(listener);\n },\n };\n}\n\ninterface RuntimeInputFactory {\n hostInput(containerId?: string | null | undefined): WorkflowRuntimeInput;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\nfunction sessionAuthInput({\n session,\n identity,\n}: WorkflowRuntimeDependencies): WorkflowRuntimeAuthInput {\n const signingFingerprint = identity.snapshot.signingFingerprint;\n return {\n defaultOrganizationId: session.defaultOrganizationId,\n rootContainerId: acknowledgedSessionRoot(session, signingFingerprint),\n isAuthenticated: session.isAuthenticated,\n isRoot: session.isRoot,\n organizationId: session.organizationId,\n userId: session.userId,\n };\n}\n\n/** Fields whose change invalidates work keyed on the session's authority. */\nfunction sessionAuthorityChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.authToken !== previous.authToken || sessionScopeChanged(previous, next)\n );\n}\n\n// A transport token renewal cannot turn a definite write refusal into saved work.\n// Journal custody still expires on every change to its identity or storage scope.\nfunction sessionScopeChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.isAuthenticated !== previous.isAuthenticated ||\n next.isRoot !== previous.isRoot ||\n next.organizationId !== previous.organizationId ||\n next.userId !== previous.userId\n );\n}\n\nfunction createRuntimeInputFactory(\n dependencies: WorkflowRuntimeDependencies,\n resolveTrustedUserIdentity: TrustedUserIdentityResolver,\n bindHistoryProtection: () => PrincipalHistoryProtectionLease | undefined,\n bindMutationApi: () => PrincipalMutationApi,\n): RuntimeInputFactory {\n let auth: WorkflowRuntimeAuthInput | undefined;\n let crypto: WorkflowRuntimeCryptoInput | undefined;\n let infra: WorkflowRuntimeInfraInput | undefined;\n let state: WorkflowRuntimeStateInput | undefined;\n let util: WorkflowRuntimeUtilInput | undefined;\n let hostUtil: HostWorkflowRuntimeUtilInput | undefined;\n\n const workflowInput = (\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput => {\n const dbStatus = dependencies.database.status;\n const execSql =\n dbStatus === \"ready\"\n ? dependencies.database.requireExecSql(\"tearleads.runtime.input\")\n : unavailableExecSql;\n const nextContainerId =\n (containerId === undefined\n ? dependencies.session.containerId\n : containerId) ?? null;\n\n auth = reuseIfShallowEqual(auth, sessionAuthInput(dependencies));\n crypto = reuseIfShallowEqual(crypto, {\n encapsulationKeyPair: dependencies.identity.encapsulationKeyPair,\n signingFingerprint: dependencies.identity.signingFingerprint,\n signingKeyPair: dependencies.identity.signingKeyPair,\n });\n infra = reuseIfShallowEqual(infra, {\n blobStore: dependencies.blobs.store,\n dbStatus,\n documentProjectors: dependencies.documentProjectors,\n // Runtime consumers branch on dbStatus before touching SQLite. The\n // fallback preserves the runtime shape and catches lifecycle bugs.\n execSql,\n });\n state = reuseIfShallowEqual(state, {\n containerId: nextContainerId,\n domainScope: dependencies.getDomainScope(),\n events: dependencies.events.events,\n // Resolved sync-online: workflows treat local-only mode exactly like being\n // offline (no server I/O), while `tearleads.network` stays the truthful\n // connectivity signal for host/UI. See Session.syncEnabled.\n online: dependencies.network.online && dependencies.session.syncEnabled,\n peerScope: dependencies.peerScope ?? null,\n serverEventsConnectionGeneration:\n dependencies.events.connectionGeneration,\n });\n if (\n !util ||\n util.log !== dependencies.log ||\n util.logError !== dependencies.logError ||\n util.reportSecurityIncident !== dependencies.reportSecurityIncident\n ) {\n util = {\n isRemoteSyncBlocked: (organizationId) =>\n dependencies.syncBillingGate?.isBlockedForOrganization(\n organizationId,\n ) ?? false,\n log: dependencies.log,\n logError: dependencies.logError,\n reportSecurityIncident: dependencies.reportSecurityIncident,\n };\n }\n\n return {\n apiClient: bindMutationApi(),\n auth,\n crypto,\n infra,\n state,\n util,\n resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: bindHistoryProtection(),\n };\n };\n\n return {\n hostInput(containerId) {\n const {\n apiClient: _apiClient,\n resolveTrustedUserIdentity: _resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: _withPrincipalHistoryProtection,\n util: workflowUtil,\n ...input\n } = workflowInput(containerId);\n hostUtil = reuseIfShallowEqual(hostUtil, {\n isRemoteSyncBlocked: workflowUtil.isRemoteSyncBlocked,\n log: workflowUtil.log,\n logError: workflowUtil.logError,\n });\n return { ...input, util: hostUtil };\n },\n workflowInput,\n };\n}\n\n/**\n * Reuses the current runtime-input group when every field of the freshly\n * constructed `next` literal is reference-equal, so unchanged groups keep a\n * stable identity across runtime reads.\n */\nfunction reuseIfShallowEqual<T extends object>(\n current: T | undefined,\n next: T,\n): T {\n if (!current) {\n return next;\n }\n for (const key of Object.keys(next)) {\n if (Reflect.get(current, key) !== Reflect.get(next, key)) {\n return next;\n }\n }\n return current;\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { BlobStore } from "
|
|
1
|
+
import type { BlobStore } from "./blobContracts.js";
|
|
2
2
|
export declare function createBlobStore(namespace: string): BlobStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createBlobStore.js","sourceRoot":"","sources":["createBlobStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE1D,6DAA6D;AAC7D,4BAA4B;AAC5B,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,aAAa,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACrD,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACnD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { BlobStore } from \"
|
|
1
|
+
{"version":3,"file":"createBlobStore.js","sourceRoot":"","sources":["createBlobStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE1D,6DAA6D;AAC7D,4BAA4B;AAC5B,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,aAAa,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACrD,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACnD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { BlobStore } from \"./blobContracts\";\nimport { createOpfsBlobStore, isOpfsBlobStoreSupported } from \"./opfsBlobStore\";\n\nconst opfsStoreByNamespace = new Map<string, BlobStore>();\n\n// namespace is a 64-character hex SHA-256 fingerprint of the\n// signing public key bytes.\nexport function createBlobStore(namespace: string): BlobStore {\n if (!isOpfsBlobStoreSupported()) {\n throw new Error(\"OPFS blob store is not supported.\");\n }\n\n const existingOpfsStore = opfsStoreByNamespace.get(namespace);\n if (existingOpfsStore) {\n return existingOpfsStore;\n }\n\n const nextOpfsStore = createOpfsBlobStore(namespace);\n opfsStoreByNamespace.set(namespace, nextOpfsStore);\n return nextOpfsStore;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertReadRange, readExactBlobBytes, } from "
|
|
1
|
+
import { assertReadRange, readExactBlobBytes, } from "./blobContracts.js";
|
|
2
2
|
import { AES_GCM_TAG_BYTES, chunkAdditionalData, deriveChunkIv, ENCRYPTED_BLOB_CHUNK_SIZE, getChunkPlaintextByteLength, } from "./encryptedBlobEnvelope.js";
|
|
3
3
|
function ciphertextOffset(prefixByteLength, chunkIndex) {
|
|
4
4
|
return (prefixByteLength +
|