@tearleads/client-sdk 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/organizations/index.js +2 -2
- package/client/organizations/index.js.map +1 -1
- package/client/organizations/organizationHistory.js +66 -0
- package/client/organizations/organizationHistory.js.map +1 -0
- package/client/organizations/organizationReadModels.d.ts +1 -1
- package/client/organizations/organizationReadModels.js +7 -27
- package/client/organizations/organizationReadModels.js.map +1 -1
- package/client/organizations/organizationsTypes.d.ts +1 -1
- package/client/organizations/organizationsTypes.js.map +1 -1
- package/data/containers/shared/types.d.ts +2 -2
- package/data/containers/shared/types.js.map +1 -1
- package/data/documents/shared/syncSubmitFailure.d.ts +2 -2
- package/data/documents/shared/syncSubmitFailure.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js +34 -8
- package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js +17 -0
- package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js.map +1 -0
- package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js +55 -0
- package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js.map +1 -0
- package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js +25 -13
- package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeProofVerification.d.ts +5 -3
- package/data/keyingProjectionVerification/documentPurgeProofVerification.js +52 -8
- package/data/keyingProjectionVerification/documentPurgeProofVerification.js.map +1 -1
- package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +4 -0
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/principalAuthorizationCheckpoints.js +1 -1
- package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -1
- package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +1 -0
- package/data/persistence/principalCurrentAcknowledgementPersistence.js +58 -12
- package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
- package/data/persistence/principalHistoryEvidencePersistence.d.ts +2 -0
- package/data/persistence/principalHistoryEvidencePersistence.js +2 -0
- package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -1
- package/data/persistence/principalHistoryIncompleteRetention.js +32 -0
- package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -0
- package/data/persistence/principalHistoryNodeRetention.js +76 -0
- package/data/persistence/principalHistoryNodeRetention.js.map +1 -0
- package/data/persistence/principalHistoryPrefixPersistence.d.ts +1 -0
- package/data/persistence/principalHistoryPrefixPersistence.js +30 -1
- package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
- package/data/persistence/principalHistoryRootOwnership.js +71 -0
- package/data/persistence/principalHistoryRootOwnership.js.map +1 -0
- package/data/persistence/principalHistoryStagePersistence.js +45 -0
- package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
- package/data/persistence/principalHistoryStageRetention.js +44 -0
- package/data/persistence/principalHistoryStageRetention.js.map +1 -0
- package/data/persistence/principalHistoryUnpublishedRetention.js +71 -0
- package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -0
- package/data/persistence/principalKeyEnvelopeArchivePersistence.js +63 -0
- package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +1 -0
- package/data/persistence/principalKeyEnvelopeCandidates.js +10 -1
- package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
- package/data/sqlite/principalHistoryEvidenceSchema.js +2 -0
- package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -1
- package/data/sqlite/principalHistoryNodeRetentionSchema.js +30 -0
- package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +1 -0
- package/data/sqlite/principalHistoryRetentionSchema.js +40 -0
- package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -0
- package/data/sqlite/principalHistoryStageSchema.js +2 -0
- package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
- package/data/sqlite/schema.d.ts +453 -0
- package/data/sqlite/schema.js +6 -0
- package/data/sqlite/schema.js.map +1 -1
- package/data/sqlite/sqliteCommitGuards.js +49 -0
- package/data/sqlite/sqliteCommitGuards.js.map +1 -0
- package/data/sqlite/sqlitePersistenceRuntime.js +14 -2
- package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
- package/index.d.ts +3 -1
- package/index.js.map +1 -1
- package/internal/api-client/ApiClient.d.ts +60 -137
- package/internal/api-client/ApiClient.js +7 -5
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/apiRequestRuntime.js +7 -7
- package/internal/api-client/apiRequestRuntime.js.map +1 -1
- package/internal/api-client/documentPurge.js +25 -0
- package/internal/api-client/documentPurge.js.map +1 -0
- package/internal/api-client/organizationPolicyHistory.d.ts +53 -0
- package/internal/api-client/organizationPolicyHistory.js +15 -0
- package/internal/api-client/organizationPolicyHistory.js.map +1 -0
- package/internal/api-client/requestInternals.js +4 -4
- package/internal/api-client/requestInternals.js.map +1 -1
- package/internal/api-client/types.d.ts +2 -2
- package/internal/api-client/types.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistory.js +4 -0
- package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
- package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
- package/internal/validators/operation/containerMutations.d.ts +448 -6528
- package/internal/validators/operation/documentMutations.d.ts +323 -579
- package/internal/validators/operation/documentMutations.js +22 -4
- package/internal/validators/operation/documentMutations.js.map +1 -1
- package/internal/validators/operation/documentSync.d.ts +26 -406
- package/internal/validators/operation/organizationPolicyHistory.d.ts +188 -310
- package/internal/validators/operation/organizationPolicyHistory.js +17 -3
- package/internal/validators/operation/organizationPolicyHistory.js.map +1 -1
- package/internal/validators/response/containerMutationError.d.ts +28 -408
- package/internal/validators/response/documentMutation.d.ts +232 -544
- package/internal/validators/response/documentMutation.js +1 -2
- package/internal/validators/response/documentMutation.js.map +1 -1
- package/internal/validators/response/documentSyncError.d.ts +26 -406
- package/internal/validators/response/documentSyncError.js +4 -3
- package/internal/validators/response/documentSyncError.js.map +1 -1
- package/internal/validators/response/index.d.ts +1 -1
- package/internal/validators/response/index.js +1 -1
- package/internal/validators/response/index.js.map +1 -1
- package/internal/validators/response/organizationPolicyHistory.d.ts +127 -309
- package/internal/validators/response/organizationPolicyHistory.js +10 -4
- package/internal/validators/response/organizationPolicyHistory.js.map +1 -1
- package/internal/validators/response/principal.d.ts +28 -408
- package/internal/validators/response/principal.js +3 -1
- package/internal/validators/response/principal.js.map +1 -1
- package/internal/validators/util/index.d.ts +1 -1
- package/internal/validators/util/index.js +1 -1
- package/internal/validators/util/index.js.map +1 -1
- package/internal/validators/util/principalHistoryWire.d.ts +2 -0
- package/internal/validators/util/principalHistoryWire.js +2 -0
- package/internal/validators/util/principalHistoryWire.js.map +1 -1
- package/package.json +1 -1
- package/workflows/container-contents/container-state/createWithMetadata.js +19 -49
- package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
- package/workflows/container-contents/container-state/groupGrantVerification.js +29 -0
- package/workflows/container-contents/container-state/groupGrantVerification.js.map +1 -1
- package/workflows/container-contents/container-state/groupShareEpoch.js +33 -0
- package/workflows/container-contents/container-state/groupShareEpoch.js.map +1 -0
- package/workflows/container-contents/container-state/remote.js +4 -1
- package/workflows/container-contents/container-state/remote.js.map +1 -1
- package/workflows/container-contents/container-state/share.js +2 -24
- package/workflows/container-contents/container-state/share.js.map +1 -1
- package/workflows/container-contents/documentTombstoneEvidence.js +23 -12
- package/workflows/container-contents/documentTombstoneEvidence.js.map +1 -1
- package/workflows/containers/child/create.js +1 -3
- package/workflows/containers/child/create.js.map +1 -1
- package/workflows/containers/child/createSubmission.d.ts +1 -3
- package/workflows/containers/child/createSubmission.js +13 -15
- package/workflows/containers/child/createSubmission.js.map +1 -1
- package/workflows/containers/child/currentShareGrantMutation.js +82 -0
- package/workflows/containers/child/currentShareGrantMutation.js.map +1 -0
- package/workflows/containers/child/currentSharePrincipalPolicy.js +83 -0
- package/workflows/containers/child/currentSharePrincipalPolicy.js.map +1 -0
- package/workflows/containers/child/mutationSubmit.js +1 -1
- package/workflows/containers/child/mutationSubmit.js.map +1 -1
- package/workflows/containers/child/runtimeCurrentGroupShare.js +82 -0
- package/workflows/containers/child/runtimeCurrentGroupShare.js.map +1 -0
- package/workflows/containers/child/share.js +1 -14
- package/workflows/containers/child/share.js.map +1 -1
- package/workflows/containers/child/shareProjection.js +15 -0
- package/workflows/containers/child/shareProjection.js.map +1 -0
- package/workflows/documents/purge.d.ts +3 -0
- package/workflows/documents/purge.js +13 -0
- package/workflows/documents/purge.js.map +1 -1
- package/workflows/documents/sync.js +2 -0
- package/workflows/documents/sync.js.map +1 -1
- package/workflows/documents/syncFailures.js +2 -2
- package/workflows/documents/syncFailures.js.map +1 -1
- package/workflows/documents/syncPolicyRepair.js +15 -13
- package/workflows/documents/syncPolicyRepair.js.map +1 -1
- package/workflows/organizations/initialPrincipalCurrentPublication.js +2 -0
- package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -1
- package/workflows/organizations/loadPolicyHistoryDetails.js +31 -32
- package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
- package/workflows/organizations/organizationPolicyHistoryDetails.js +37 -15
- package/workflows/organizations/organizationPolicyHistoryDetails.js.map +1 -1
- package/workflows/organizations/organizationPolicyHistoryVerification.js +56 -69
- package/workflows/organizations/organizationPolicyHistoryVerification.js.map +1 -1
- package/workflows/organizations/policyHistoryCache.js +5 -2
- package/workflows/organizations/policyHistoryCache.js.map +1 -1
- package/workflows/organizations/policyHistoryTypes.d.ts +1 -0
- package/workflows/organizations/policyHistoryTypes.js.map +1 -1
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +4 -1
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
- package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +0 -1
- package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +1 -2
- package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -1
- package/workflows/principals/policyRepair.js +38 -0
- package/workflows/principals/policyRepair.js.map +1 -0
- package/workflows/principals/policyRepairBudget.d.ts +2 -2
- package/workflows/principals/policyRepairBudget.js +3 -3
- package/workflows/principals/policyRepairBudget.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryPrefix.js +4 -0
- package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -1
- package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
- package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryPage.js +1 -0
- package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryProgress.js +1 -0
- package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryTypes.d.ts +2 -0
- package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -1
- package/workflows/principals/publicProjectionPrincipal.js +1 -0
- package/workflows/principals/publicProjectionPrincipal.js.map +1 -1
- package/workflows/principals/recoverPrincipalHistoryPage.js +2 -1
- package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js +1 -0
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverPublicPrincipalHistory.js +2 -0
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +2 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/selectPublicPrincipalHistory.js +21 -15
- package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -1
- package/workflows/sync/remoteResetPrincipalScope.js +6 -0
- package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js +0 -208
- package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js.map +0 -1
- package/data/keyingProjectionVerification/snapshotVerificationCache.js +0 -39
- package/data/keyingProjectionVerification/snapshotVerificationCache.js.map +0 -1
- package/workflows/containers/child/policyRepair.js +0 -23
- package/workflows/containers/child/policyRepair.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"purge.js","sourceRoot":"","sources":["purge.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeAccessEventBodyHash,\n type DocumentPurgeAccessEventBody,\n KeyingVerificationError,\n signAccessEvent,\n type UnsignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { DocumentPurgeRequest } from \"@tearleads/validators/request\";\nimport {\n DOCUMENT_NOT_FOUND_ERROR_CODE,\n type DocumentPurgeProofResponse,\n type DocumentPurgeResponse,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport {\n containerPathRefs,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"../../data/documents/shared/projection\";\nimport {\n assertDocumentManifestBundleConsistent,\n readManifestContainerId,\n} from \"../../data/documents/shared/readers\";\nimport type {\n DocumentCreateAuthor,\n DocumentSyncApi,\n} from \"../../data/documents/shared/types\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../data/keyingCanonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../data/keyingProjectionVerification\";\nimport {\n verifyDocumentPurgeProof,\n verifyDocumentPurgeProofBaseline,\n verifyDocumentWriterProjection,\n} from \"../../data/keyingProjectionVerification\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { documentContainerProjections } from \"../../data/keyingProjectionVerification/documentContainerProjections\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\ninterface DocumentPurgeApi {\n getDocumentPurgeProof(\n documentId: string,\n options?: {\n readonly documentCheckpointManifestHash?: string;\n },\n requestOptions?: {\n readonly expectedPaymentRequiredOrganizationId?: string;\n },\n ): Promise<DocumentPurgeProofResponse | null>;\n getDocumentWriterProjectionResult: NonNullable<\n DocumentSyncApi[\"getDocumentWriterProjectionResult\"]\n >;\n purgeDocument(\n documentId: string,\n request: DocumentPurgeRequest,\n options?: {\n readonly expectedPaymentRequiredOrganizationId?: string;\n },\n ): Promise<DocumentPurgeResponse | null>;\n}\n\nconst REMOTE_DOCUMENT_ALREADY_PURGED = Symbol(\"remoteDocumentAlreadyPurged\");\n\nasync function loadAuthenticatedDocumentPurgeProof(input: {\n readonly apiClient: Pick<DocumentSyncApi, \"getDocumentPurgeProof\">;\n readonly documentId: string;\n readonly execSql: ExecSql;\n readonly expectedOrganizationId: string;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n}): Promise<DocumentPurgeProofResponse | null> {\n if (!input.apiClient.getDocumentPurgeProof) {\n throw new ProjectionDependencyUnavailableError(\n \"Remote document deletion is missing a purge-proof endpoint\",\n );\n }\n const initialProof = await input.apiClient.getDocumentPurgeProof(\n input.documentId,\n undefined,\n {\n expectedPaymentRequiredOrganizationId: input.expectedOrganizationId,\n },\n );\n if (!initialProof) {\n // ApiClient returns null for transport, HTTP and response-shape failures.\n // Even after a deletion hint, absence cannot prove signed-data tampering.\n // Keep local data and defer deletion until an actual proof verifies.\n return null;\n }\n await verifyDocumentPurgeProofBaseline({\n execSql: input.execSql,\n expectedDocumentId: input.documentId,\n expectedOrganizationId: input.expectedOrganizationId,\n proof: initialProof,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n // The current API returns complete history to recorded readers. Otherwise\n // its terminal snapshot needs an exact local pin; a floor refetch cannot\n // grant missing observation authority.\n return initialProof;\n}\n\nasync function resolveDocumentPurgeWriterProjection(input: {\n readonly apiClient: DocumentPurgeApi;\n readonly documentId: string;\n}): Promise<\n | DocumentWriterProjectionResponse\n | typeof REMOTE_DOCUMENT_ALREADY_PURGED\n | null\n> {\n const result = await input.apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (result.ok) {\n return result.data;\n }\n if (result.status === 404 && result.code === DOCUMENT_NOT_FOUND_ERROR_CODE) {\n return REMOTE_DOCUMENT_ALREADY_PURGED;\n }\n result.report();\n return null;\n}\n\nexport async function buildDocumentPurgeRequest(input: {\n readonly author: DocumentCreateAuthor;\n readonly eventId?: string | undefined;\n readonly signedAt?: string | undefined;\n readonly writerProjection: DocumentWriterProjectionResponse;\n}): Promise<DocumentPurgeRequest> {\n const identity = await assertDocumentManifestBundleConsistent({\n bundle: input.writerProjection.documentManifest,\n label: \"Document purge predecessor\",\n });\n if (identity.documentId !== input.writerProjection.documentId) {\n throw new Error(\"Document purge projection identity mismatch\");\n }\n if (identity.organizationId !== input.author.organizationId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document purge author organization mismatch\",\n );\n }\n const linkedContainerIds = readLinkedContainerIdsFromDocumentManifest(\n input.writerProjection,\n );\n if (linkedContainerIds.length !== 1) {\n throw new Error(\"Document purge requires exactly one linked container\");\n }\n const [containerId] = linkedContainerIds;\n const authorizingProjection = documentContainerProjections(\n input.writerProjection,\n ).find((projection) => {\n const leaf = projection.path.at(-1);\n return leaf && readManifestContainerId(leaf) === containerId;\n });\n const containerManifestHash =\n authorizingProjection?.path.at(-1)?.manifestHash;\n if (!authorizingProjection || !containerId || !containerManifestHash) {\n throw new Error(\"Document purge authorization path is unavailable\");\n }\n const authorizingContainerManifestHashes = authorizingProjection.path.map(\n (bundle) => bundle.manifestHash,\n );\n const body: DocumentPurgeAccessEventBody = {\n authorizingContainerManifestHashes,\n containerId,\n containerManifestHash,\n documentManifestHash: input.writerProjection.documentManifest.manifestHash,\n eventType: \"document.purge\",\n };\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId ?? crypto.randomUUID(),\n eventType: \"document.purge\",\n objectKind: \"document\",\n objectId: input.writerProjection.documentId,\n organizationId: input.author.organizationId,\n previousManifestHash: input.writerProjection.documentManifest.manifestHash,\n dependencyManifestHashes: authorizingContainerManifestHashes,\n bodyHash: await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document purge body\"),\n ),\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n const event = await signAccessEvent(\n unsignedEvent,\n input.author.signerPrivateKey,\n );\n\n return {\n authorizingContainerPathRefs: containerPathRefs(authorizingProjection.path),\n body: readCanonicalRecord(body, \"Document purge body\"),\n event: readCanonicalRecord(event, \"Document purge event\"),\n };\n}\n\nexport function createVerifiedRemoteDocumentDeletionHandler(input: {\n readonly apiClient: Pick<DocumentSyncApi, \"getDocumentPurgeProof\">;\n readonly execSql: ExecSql;\n readonly expectedOrganizationId: string;\n readonly onVerifiedDeletion: (input: {\n readonly commitPurgeProof: (transactionExecSql: ExecSql) => Promise<void>;\n readonly documentId: string;\n }) => Promise<void> | void;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n}): (deleted: { readonly documentId: string }) => Promise<void> {\n return async ({ documentId }) => {\n const proof = await loadAuthenticatedDocumentPurgeProof({\n apiClient: input.apiClient,\n documentId,\n execSql: input.execSql,\n expectedOrganizationId: input.expectedOrganizationId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n });\n if (!proof) {\n throw new ProjectionDependencyUnavailableError(\n \"Remote document deletion is missing its signed purge proof\",\n );\n }\n const verified = await verifyDocumentPurgeProof({\n execSql: input.execSql,\n expectedDocumentId: documentId,\n expectedOrganizationId: input.expectedOrganizationId,\n proof,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n await input.onVerifiedDeletion({\n commitPurgeProof: verified.commitCheckpoints,\n documentId,\n });\n };\n}\n\nexport async function purgeRemoteDocument(input: {\n readonly apiClient: DocumentPurgeApi;\n readonly author: DocumentCreateAuthor;\n readonly documentId: string;\n readonly execSql: ExecSql;\n readonly onVerifiedPurge: (input: {\n readonly commitPurgeProof: (transactionExecSql: ExecSql) => Promise<void>;\n }) => Promise<void> | void;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<DocumentPurgeResponse | null> {\n const writerProjection = await resolveDocumentPurgeWriterProjection({\n apiClient: input.apiClient,\n documentId: input.documentId,\n });\n if (!writerProjection) {\n return null;\n }\n if (writerProjection === REMOTE_DOCUMENT_ALREADY_PURGED) {\n const proof = await loadAuthenticatedDocumentPurgeProof({\n apiClient: input.apiClient,\n documentId: input.documentId,\n execSql: input.execSql,\n expectedOrganizationId: input.author.organizationId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n });\n if (!proof) {\n throw new ProjectionDependencyUnavailableError(\n \"Purged remote document is missing its signed purge proof\",\n );\n }\n const verified = await verifyDocumentPurgeProof({\n execSql: input.execSql,\n expectedDocumentId: input.documentId,\n expectedOrganizationId: input.author.organizationId,\n proof,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n await input.onVerifiedPurge({\n commitPurgeProof: verified.commitCheckpoints,\n });\n return { ...proof, reclaimedBlobStorageKeys: [] };\n }\n await verifyDocumentWriterProjection({\n execSql: input.execSql,\n projection: writerProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const request = await buildDocumentPurgeRequest({\n author: input.author,\n writerProjection,\n });\n const response = await input.apiClient.purgeDocument(\n input.documentId,\n request,\n {\n expectedPaymentRequiredOrganizationId: input.author.organizationId,\n },\n );\n if (!response) {\n return null;\n }\n const verified = await verifyDocumentPurgeProof({\n execSql: input.execSql,\n expectedDocumentId: input.documentId,\n expectedOrganizationId: input.author.organizationId,\n proof: response,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n await input.onVerifiedPurge({\n commitPurgeProof: verified.commitCheckpoints,\n });\n return response;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"purge.js","sourceRoot":"","sources":["purge.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeAccessEventBodyHash,\n type DocumentPurgeAccessEventBody,\n KeyingVerificationError,\n signAccessEvent,\n type UnsignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { DocumentPurgeRequest } from \"@tearleads/validators/request\";\nimport {\n DOCUMENT_NOT_FOUND_ERROR_CODE,\n type DocumentPurgeProofResponse,\n type DocumentPurgeResponse,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport {\n containerPathRefs,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"../../data/documents/shared/projection\";\nimport {\n assertDocumentManifestBundleConsistent,\n readManifestContainerId,\n} from \"../../data/documents/shared/readers\";\nimport type {\n DocumentCreateAuthor,\n DocumentSyncApi,\n} from \"../../data/documents/shared/types\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../data/keyingCanonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../data/keyingProjectionVerification\";\nimport {\n verifyDocumentPurgeProof,\n verifyDocumentPurgeProofBaseline,\n verifyDocumentWriterProjection,\n} from \"../../data/keyingProjectionVerification\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { documentContainerProjections } from \"../../data/keyingProjectionVerification/documentContainerProjections\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\ninterface DocumentPurgeApi {\n getDocumentPurgeProof(\n documentId: string,\n options?: {\n readonly documentCheckpointManifestHash?: string;\n },\n requestOptions?: {\n readonly expectedPaymentRequiredOrganizationId?: string;\n },\n ): Promise<DocumentPurgeProofResponse | null>;\n getDocumentWriterProjectionResult: NonNullable<\n DocumentSyncApi[\"getDocumentWriterProjectionResult\"]\n >;\n purgeDocument(\n documentId: string,\n request: DocumentPurgeRequest,\n options?: {\n readonly expectedPaymentRequiredOrganizationId?: string;\n },\n ): Promise<DocumentPurgeResponse | null>;\n}\n\nconst REMOTE_DOCUMENT_ALREADY_PURGED = Symbol(\"remoteDocumentAlreadyPurged\");\n\nasync function loadAuthenticatedDocumentPurgeProof(input: {\n readonly apiClient: Pick<DocumentSyncApi, \"getDocumentPurgeProof\">;\n readonly documentId: string;\n readonly execSql: ExecSql;\n readonly expectedOrganizationId: string;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<DocumentPurgeProofResponse | null> {\n if (!input.apiClient.getDocumentPurgeProof) {\n throw new ProjectionDependencyUnavailableError(\n \"Remote document deletion is missing a purge-proof endpoint\",\n );\n }\n const initialProof = await input.apiClient.getDocumentPurgeProof(\n input.documentId,\n undefined,\n {\n expectedPaymentRequiredOrganizationId: input.expectedOrganizationId,\n },\n );\n if (!initialProof) {\n // ApiClient returns null for transport, HTTP and response-shape failures.\n // Even after a deletion hint, absence cannot prove signed-data tampering.\n // Keep local data and defer deletion until an actual proof verifies.\n return null;\n }\n await verifyDocumentPurgeProofBaseline({\n execSql: input.execSql,\n expectedDocumentId: input.documentId,\n expectedOrganizationId: input.expectedOrganizationId,\n proof: initialProof,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n // The current API returns complete history to recorded readers. Otherwise\n // its terminal snapshot needs an exact local pin; a floor refetch cannot\n // grant missing observation authority.\n return initialProof;\n}\n\nasync function resolveDocumentPurgeWriterProjection(input: {\n readonly apiClient: DocumentPurgeApi;\n readonly documentId: string;\n}): Promise<\n | DocumentWriterProjectionResponse\n | typeof REMOTE_DOCUMENT_ALREADY_PURGED\n | null\n> {\n const result = await input.apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (result.ok) {\n return result.data;\n }\n if (result.status === 404 && result.code === DOCUMENT_NOT_FOUND_ERROR_CODE) {\n return REMOTE_DOCUMENT_ALREADY_PURGED;\n }\n result.report();\n return null;\n}\n\nexport async function buildDocumentPurgeRequest(input: {\n readonly author: DocumentCreateAuthor;\n readonly eventId?: string | undefined;\n readonly signedAt?: string | undefined;\n readonly writerProjection: DocumentWriterProjectionResponse;\n}): Promise<DocumentPurgeRequest> {\n const identity = await assertDocumentManifestBundleConsistent({\n bundle: input.writerProjection.documentManifest,\n label: \"Document purge predecessor\",\n });\n if (identity.documentId !== input.writerProjection.documentId) {\n throw new Error(\"Document purge projection identity mismatch\");\n }\n if (identity.organizationId !== input.author.organizationId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document purge author organization mismatch\",\n );\n }\n const linkedContainerIds = readLinkedContainerIdsFromDocumentManifest(\n input.writerProjection,\n );\n if (linkedContainerIds.length !== 1) {\n throw new Error(\"Document purge requires exactly one linked container\");\n }\n const [containerId] = linkedContainerIds;\n const authorizingProjection = documentContainerProjections(\n input.writerProjection,\n ).find((projection) => {\n const leaf = projection.path.at(-1);\n return leaf && readManifestContainerId(leaf) === containerId;\n });\n const containerManifestHash =\n authorizingProjection?.path.at(-1)?.manifestHash;\n if (!authorizingProjection || !containerId || !containerManifestHash) {\n throw new Error(\"Document purge authorization path is unavailable\");\n }\n const authorizingContainerManifestHashes = authorizingProjection.path.map(\n (bundle) => bundle.manifestHash,\n );\n const body: DocumentPurgeAccessEventBody = {\n authorizingContainerManifestHashes,\n containerId,\n containerManifestHash,\n documentManifestHash: input.writerProjection.documentManifest.manifestHash,\n eventType: \"document.purge\",\n };\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId ?? crypto.randomUUID(),\n eventType: \"document.purge\",\n objectKind: \"document\",\n objectId: input.writerProjection.documentId,\n organizationId: input.author.organizationId,\n previousManifestHash: input.writerProjection.documentManifest.manifestHash,\n dependencyManifestHashes: authorizingContainerManifestHashes,\n bodyHash: await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document purge body\"),\n ),\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n const event = await signAccessEvent(\n unsignedEvent,\n input.author.signerPrivateKey,\n );\n\n return {\n authorizingContainerPathRefs: containerPathRefs(authorizingProjection.path),\n body: readCanonicalRecord(body, \"Document purge body\"),\n event: readCanonicalRecord(event, \"Document purge event\"),\n };\n}\n\nexport function createVerifiedRemoteDocumentDeletionHandler(input: {\n readonly apiClient: Pick<DocumentSyncApi, \"getDocumentPurgeProof\">;\n readonly execSql: ExecSql;\n readonly expectedOrganizationId: string;\n readonly onVerifiedDeletion: (input: {\n readonly commitPurgeProof: (transactionExecSql: ExecSql) => Promise<void>;\n readonly documentId: string;\n }) => Promise<void> | void;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): (deleted: { readonly documentId: string }) => Promise<void> {\n return async ({ documentId }) => {\n const proof = await loadAuthenticatedDocumentPurgeProof({\n apiClient: input.apiClient,\n documentId,\n execSql: input.execSql,\n expectedOrganizationId: input.expectedOrganizationId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n if (!proof) {\n throw new ProjectionDependencyUnavailableError(\n \"Remote document deletion is missing its signed purge proof\",\n );\n }\n const verified = await verifyDocumentPurgeProof({\n execSql: input.execSql,\n expectedDocumentId: documentId,\n expectedOrganizationId: input.expectedOrganizationId,\n proof,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n await input.onVerifiedDeletion({\n commitPurgeProof: verified.commitCheckpoints,\n documentId,\n });\n };\n}\n\nexport async function purgeRemoteDocument(input: {\n readonly apiClient: DocumentPurgeApi;\n readonly author: DocumentCreateAuthor;\n readonly documentId: string;\n readonly execSql: ExecSql;\n readonly onVerifiedPurge: (input: {\n readonly commitPurgeProof: (transactionExecSql: ExecSql) => Promise<void>;\n }) => Promise<void> | void;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<DocumentPurgeResponse | null> {\n const writerProjection = await resolveDocumentPurgeWriterProjection({\n apiClient: input.apiClient,\n documentId: input.documentId,\n });\n if (!writerProjection) {\n return null;\n }\n if (writerProjection === REMOTE_DOCUMENT_ALREADY_PURGED) {\n const proof = await loadAuthenticatedDocumentPurgeProof({\n apiClient: input.apiClient,\n documentId: input.documentId,\n execSql: input.execSql,\n expectedOrganizationId: input.author.organizationId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n if (!proof) {\n throw new ProjectionDependencyUnavailableError(\n \"Purged remote document is missing its signed purge proof\",\n );\n }\n const verified = await verifyDocumentPurgeProof({\n execSql: input.execSql,\n expectedDocumentId: input.documentId,\n expectedOrganizationId: input.author.organizationId,\n proof,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n await input.onVerifiedPurge({\n commitPurgeProof: verified.commitCheckpoints,\n });\n return { ...proof, reclaimedBlobStorageKeys: [] };\n }\n await verifyDocumentWriterProjection({\n execSql: input.execSql,\n projection: writerProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const request = await buildDocumentPurgeRequest({\n author: input.author,\n writerProjection,\n });\n const response = await input.apiClient.purgeDocument(\n input.documentId,\n request,\n {\n expectedPaymentRequiredOrganizationId: input.author.organizationId,\n },\n );\n if (!response) {\n return null;\n }\n const verified = await verifyDocumentPurgeProof({\n execSql: input.execSql,\n expectedDocumentId: input.documentId,\n expectedOrganizationId: input.author.organizationId,\n proof: response,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n await input.onVerifiedPurge({\n commitPurgeProof: verified.commitCheckpoints,\n });\n return response;\n}\n"]}
|
|
@@ -269,6 +269,8 @@ export async function syncRemoteDocument(input) {
|
|
|
269
269
|
});
|
|
270
270
|
},
|
|
271
271
|
resolveProjectionUserKey: input.resolveProjectionUserKey,
|
|
272
|
+
stillCurrent: input.stillCurrent,
|
|
273
|
+
warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,
|
|
272
274
|
}),
|
|
273
275
|
});
|
|
274
276
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { isDocumentUpdateCreatedEvent } from \"../../data/documents/documentSync\";\nimport { isDocumentSyncUpdateIsolationError } from \"../../data/documents/shared/documentSyncUpdateIsolation\";\nimport {\n type DocumentSyncPullContinuation,\n InvalidDocumentSyncPullContinuationError,\n} from \"../../data/documents/shared/syncPagination\";\nimport type {\n MaterializedDocumentSyncPlan,\n SyncRemoteDocumentResult,\n} from \"../../data/documents/shared/types\";\nimport {\n isProjectionVerificationCancelledError,\n type ProjectionUserKeyResolver,\n requireProjectionUserKeyResolver,\n} from \"../../data/keyingProjectionVerification\";\nimport type { PendingUpdateRecord } from \"../../data/sqlite/documentPersistence\";\nimport { createVerifiedRemoteDocumentDeletionHandler } from \"./purge\";\nimport {\n type SyncRemoteDocumentInput,\n tryPersistedReadOnlyDocumentSync,\n} from \"./readOnlySync\";\nimport {\n abandonAfterRetryableConflicts,\n abandonBlockedSync,\n} from \"./syncAbandon\";\nimport {\n planDocumentSyncAttempt,\n projectionFailureHandler,\n} from \"./syncAttemptPlanning\";\nimport type {\n RemoteDocumentSyncAttemptOutcome,\n RemoteDocumentSyncAttemptState,\n} from \"./syncAttemptState\";\nimport { requireStandaloneAncestorRepairs } from \"./syncContainerRekeyPreparation\";\nimport {\n assertRawContinuationCanRetry,\n resolveSyncAttemptWriterProjection,\n submitDocumentSyncAttemptIfAllowed,\n} from \"./syncFailures\";\nimport { recoverablePendingUpdates } from \"./syncPlanRequestBounds\";\nimport { resolveSubmittedDocumentSyncResult } from \"./syncSubmittedResult\";\n\nexport function hasDocumentUpdateEvent(\n events: ReadonlyArray<unknown>,\n documentId: string | null | undefined,\n): boolean {\n if (!documentId) return false;\n return events.some(\n (event) =>\n isDocumentUpdateCreatedEvent(event) && event.documentId === documentId,\n );\n}\n/**\n * A retryable stale-projection conflict means this writer projection is behind\n * the server. Evict only this document so the next attempt re-derives targets.\n */\nfunction evictStaleProjectionForRetry(input: SyncRemoteDocumentInput): void {\n input.apiClient.evictDocumentWriterProjection?.(input.documentId);\n}\n\n/**\n * A pass may repair a covering-baseline rejection by regenerating queued\n * rotation checkpoints — but only when there is something to regenerate FROM\n * (a snapshot provider and queued checkpoint rows), the failed pass was not\n * already a heal or a regeneration (whose fresh baseline proves this device\n * is simply behind), and an attempt remains.\n */\nfunction canRegenerateQueuedCheckpoints(input: {\n materializedPlan: MaterializedDocumentSyncPlan;\n pendingUpdates: readonly PendingUpdateRecord[];\n regenerateQueuedCheckpoints: boolean;\n sync: SyncRemoteDocumentInput;\n}): boolean {\n return (\n !input.regenerateQueuedCheckpoints &&\n !input.materializedPlan.healedStaleContentKeyBundle &&\n input.sync.buildRotationSnapshot !== undefined &&\n input.pendingUpdates.some((update) => update.sourceVersionVector != null)\n );\n}\n\nasync function submitPlannedSyncAttempt(args: {\n attempt: number;\n materializedPlan: MaterializedDocumentSyncPlan;\n maxAttempts: number;\n pendingUpdates: readonly PendingUpdateRecord[];\n pullContinuation?: DocumentSyncPullContinuation | undefined;\n regenerateQueuedCheckpoints: boolean;\n sync: SyncRemoteDocumentInput;\n failureBlocksQueuedWrites: boolean;\n}) {\n try {\n return await submitDocumentSyncAttemptIfAllowed({\n apiClient: args.sync.apiClient,\n attempt: args.attempt,\n canRegenerateQueuedCheckpoints: canRegenerateQueuedCheckpoints({\n materializedPlan: args.materializedPlan,\n pendingUpdates: args.pendingUpdates,\n regenerateQueuedCheckpoints: args.regenerateQueuedCheckpoints,\n sync: args.sync,\n }),\n documentId: args.sync.documentId,\n expectedCommitLsnMode: args.pullContinuation?.commitLsnMode,\n isRemoteSyncBlocked: args.sync.isRemoteSyncBlocked,\n maxAttempts: args.maxAttempts,\n onInlineRepairRefused: () => requireStandaloneAncestorRepairs(args.sync),\n onRemoteDocumentDeleted: args.sync.onRemoteDocumentDeleted,\n onOutgoingUpdatesMaterialized: args.sync.onOutgoingUpdatesMaterialized,\n onSyncTrace: args.sync.onSyncTrace,\n onTerminalSubmitFailure: args.sync.onTerminalSubmitFailure,\n pendingUpdates: args.pendingUpdates,\n plan: args.materializedPlan.plan,\n failureBlocksQueuedWrites: args.failureBlocksQueuedWrites,\n stillCurrent: args.sync.stillCurrent,\n warmReferencedPrincipalPolicies:\n args.sync.warmReferencedPrincipalPolicies,\n });\n } catch (error) {\n if (\n error instanceof InvalidDocumentSyncPullContinuationError &&\n args.pullContinuation !== undefined &&\n args.sync.historyMode !== \"raw\"\n ) {\n return \"retry\" as const;\n }\n throw error;\n }\n}\n\nfunction resolveAttemptProjection(\n input: SyncRemoteDocumentInput,\n failureBlocksQueuedWrites: boolean,\n reusableWriterProjection: DocumentWriterProjectionResponse | null,\n) {\n return resolveSyncAttemptWriterProjection({\n apiClient: input.apiClient,\n documentId: input.documentId,\n onRemoteDocumentDeleted: input.onRemoteDocumentDeleted,\n onSyncAbandoned: input.onSyncAbandoned,\n onSyncTrace: input.onSyncTrace,\n onTerminalFailure: projectionFailureHandler(\n input,\n failureBlocksQueuedWrites,\n ),\n reusableWriterProjection,\n stillCurrent: input.stillCurrent,\n });\n}\nfunction resolveRemoteSyncProjectionUserKey(input: SyncRemoteDocumentInput) {\n return requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote document sync\",\n );\n}\n\nasync function invalidatePullCursor(\n input: SyncRemoteDocumentInput,\n pullContinuation: DocumentSyncPullContinuation | undefined,\n): Promise<undefined> {\n if (pullContinuation !== undefined) {\n await input.onPullContinuationInvalidated?.(pullContinuation);\n }\n return undefined;\n}\n\nasync function preparePersistedDocumentSync(\n input: SyncRemoteDocumentInput,\n resolveProjectionUserKey: ProjectionUserKeyResolver,\n): Promise<\n | { readonly kind: \"completed\"; result: SyncRemoteDocumentResult | null }\n | {\n readonly kind: \"continue\";\n pullContinuation: DocumentSyncPullContinuation | undefined;\n }\n> {\n let pullContinuation = input.pullContinuation;\n try {\n const persisted = await tryPersistedReadOnlyDocumentSync(\n input,\n resolveProjectionUserKey,\n );\n if (persisted?.kind === \"completed\") return persisted;\n if (persisted?.kind === \"not_completed\" && input.historyMode !== \"raw\") {\n pullContinuation = await invalidatePullCursor(input, pullContinuation);\n }\n } catch (error) {\n if (\n !(error instanceof InvalidDocumentSyncPullContinuationError) ||\n pullContinuation === undefined ||\n input.historyMode === \"raw\"\n ) {\n throw error;\n }\n pullContinuation = await invalidatePullCursor(input, pullContinuation);\n }\n return { kind: \"continue\", pullContinuation };\n}\n\nfunction failureBlocksQueuedWrites(input: {\n readonly pendingUpdates: readonly PendingUpdateRecord[];\n readonly recoveryPendingUpdateCount: number;\n}): boolean {\n return (\n input.pendingUpdates.length > 0 || input.recoveryPendingUpdateCount > 0\n );\n}\n\nasync function retryRemoteSyncAttempt(\n sync: SyncRemoteDocumentInput,\n continuation: DocumentSyncPullContinuation | undefined,\n): Promise<RemoteDocumentSyncAttemptOutcome> {\n evictStaleProjectionForRetry(sync);\n return {\n kind: \"retry\",\n pullContinuation: await invalidatePullCursor(sync, continuation),\n };\n}\n\nasync function runRemoteDocumentSyncAttempt(input: {\n attempt: number;\n maxAttempts: number;\n pendingUpdateIds: readonly string[];\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n state: RemoteDocumentSyncAttemptState;\n sync: SyncRemoteDocumentInput;\n}): Promise<RemoteDocumentSyncAttemptOutcome> {\n if (input.sync.stillCurrent?.() === false) {\n return { kind: \"complete\", result: null };\n }\n const blocksQueuedWrites = failureBlocksQueuedWrites({\n pendingUpdates: input.state.pendingUpdates,\n recoveryPendingUpdateCount: input.state.recoveryPendingUpdatesById.size,\n });\n const writerProjection = await resolveAttemptProjection(\n input.sync,\n blocksQueuedWrites,\n input.state.reusableWriterProjection,\n );\n if (input.sync.stillCurrent?.() === false || !writerProjection) {\n return { kind: \"complete\", result: null };\n }\n const planned = await planDocumentSyncAttempt({\n pendingUpdates: input.state.pendingUpdates,\n pullContinuation: input.state.pullContinuation,\n regenerateQueuedCheckpoints: input.state.regenerateQueuedCheckpoints,\n sync: input.sync,\n failureBlocksQueuedWrites: blocksQueuedWrites,\n writerProjection,\n });\n if (planned === \"retry\") {\n return retryRemoteSyncAttempt(input.sync, input.state.pullContinuation);\n }\n if (!planned || input.sync.stillCurrent?.() === false) {\n return { kind: \"complete\", result: null };\n }\n const [materializedPlan] = planned;\n const submitted = await submitPlannedSyncAttempt({\n attempt: input.attempt,\n materializedPlan,\n maxAttempts: input.maxAttempts,\n pendingUpdates: recoverablePendingUpdates(\n input.state.pendingUpdates,\n materializedPlan,\n ),\n pullContinuation: input.state.pullContinuation,\n regenerateQueuedCheckpoints: input.state.regenerateQueuedCheckpoints,\n sync: input.sync,\n failureBlocksQueuedWrites: blocksQueuedWrites,\n });\n if (input.sync.stillCurrent?.() === false || submitted === \"cancelled\") {\n return { kind: \"complete\", result: null };\n }\n if (submitted === \"retry\") {\n assertRawContinuationCanRetry(\n input.sync.historyMode,\n input.state.pullContinuation,\n );\n return retryRemoteSyncAttempt(input.sync, input.state.pullContinuation);\n }\n if (submitted === \"blocked\") {\n abandonBlockedSync(input.sync);\n return { kind: \"complete\", result: null };\n }\n if (submitted === \"stop\") {\n input.sync.onSyncAbandoned?.(\"the sync submit failed terminally\");\n return { kind: \"complete\", result: null };\n }\n if (submitted.kind === \"regenerate_queued_checkpoints\") {\n return { kind: \"regenerate\" };\n }\n if (submitted.kind === \"recover_update_id_conflict\") {\n // A lost response may mean the server committed both this update id and an\n // inline container rekey. Force the read-only recovery pass to observe that\n // committed successor projection instead of reusing a cached predecessor.\n evictStaleProjectionForRetry(input.sync);\n return { kind: \"recover\", updates: submitted.recoveryPendingUpdatesById };\n }\n const result = await resolveSubmittedDocumentSyncResult({\n materializedPlan,\n pendingUpdateIds: input.pendingUpdateIds,\n pullComplete: submitted.pullComplete,\n recoveryPendingUpdatesById: input.state.recoveryPendingUpdatesById,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n response: submitted.response,\n sync: input.sync,\n writerProjection: materializedPlan.writerProjection,\n });\n return {\n kind: \"complete\",\n result: input.sync.stillCurrent?.() === false ? null : result,\n };\n}\n\nasync function syncRemoteDocumentInternal(\n input: SyncRemoteDocumentInput,\n): Promise<SyncRemoteDocumentResult | null> {\n if (input.stillCurrent?.() === false) return null;\n const resolveProjectionUserKey = resolveRemoteSyncProjectionUserKey(input);\n const maxAttempts = 3;\n let pendingUpdates = input.pendingUpdates ?? [];\n const pendingUpdateIds = pendingUpdates.map((update) => update.id);\n let recoveryPendingUpdatesById = new Map<string, PendingUpdateRecord>();\n let regenerateQueuedCheckpoints = false;\n let reusableWriterProjection = input.writerProjection ?? null;\n const persistedSync = await preparePersistedDocumentSync(\n input,\n resolveProjectionUserKey,\n );\n if (input.stillCurrent?.() === false) return null;\n if (persistedSync.kind === \"completed\") return persistedSync.result;\n let pullContinuation = persistedSync.pullContinuation;\n for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n const outcome = await runRemoteDocumentSyncAttempt({\n attempt,\n maxAttempts,\n pendingUpdateIds,\n resolveProjectionUserKey,\n state: {\n pendingUpdates,\n pullContinuation,\n recoveryPendingUpdatesById,\n regenerateQueuedCheckpoints,\n reusableWriterProjection,\n },\n sync: input,\n });\n reusableWriterProjection = null;\n if (outcome.kind === \"complete\") return outcome.result;\n if (outcome.kind === \"retry\") {\n pullContinuation = outcome.pullContinuation;\n if (input.stillCurrent?.() === false) return null;\n continue;\n }\n if (outcome.kind === \"regenerate\") {\n regenerateQueuedCheckpoints = true;\n continue;\n }\n recoveryPendingUpdatesById = outcome.updates;\n pendingUpdates = [];\n }\n return abandonAfterRetryableConflicts(input);\n}\n\nexport async function syncRemoteDocument(\n input: SyncRemoteDocumentInput,\n): Promise<SyncRemoteDocumentResult | null> {\n try {\n return await syncRemoteDocumentInternal({\n ...input,\n onRemoteDocumentDeleted: createVerifiedRemoteDocumentDeletionHandler({\n apiClient: input.apiClient,\n execSql: input.execSql,\n expectedOrganizationId: input.author.organizationId,\n onVerifiedDeletion: ({ commitPurgeProof, documentId }) => {\n if (input.stillCurrent?.() === false) return;\n if (!input.onRemoteDocumentDeleted) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Remote document deletion requires atomic local teardown\",\n );\n }\n return input.onRemoteDocumentDeleted({\n commitPurgeProof,\n documentId,\n });\n },\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n }),\n });\n } catch (error) {\n if (isProjectionVerificationCancelledError(error)) return null;\n if (\n input.stillCurrent?.() !== false &&\n isDocumentSyncUpdateIsolationError(error)\n ) {\n await input.onIncomingUpdateIsolationFailure?.(error);\n }\n throw error;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { isDocumentUpdateCreatedEvent } from \"../../data/documents/documentSync\";\nimport { isDocumentSyncUpdateIsolationError } from \"../../data/documents/shared/documentSyncUpdateIsolation\";\nimport {\n type DocumentSyncPullContinuation,\n InvalidDocumentSyncPullContinuationError,\n} from \"../../data/documents/shared/syncPagination\";\nimport type {\n MaterializedDocumentSyncPlan,\n SyncRemoteDocumentResult,\n} from \"../../data/documents/shared/types\";\nimport {\n isProjectionVerificationCancelledError,\n type ProjectionUserKeyResolver,\n requireProjectionUserKeyResolver,\n} from \"../../data/keyingProjectionVerification\";\nimport type { PendingUpdateRecord } from \"../../data/sqlite/documentPersistence\";\nimport { createVerifiedRemoteDocumentDeletionHandler } from \"./purge\";\nimport {\n type SyncRemoteDocumentInput,\n tryPersistedReadOnlyDocumentSync,\n} from \"./readOnlySync\";\nimport {\n abandonAfterRetryableConflicts,\n abandonBlockedSync,\n} from \"./syncAbandon\";\nimport {\n planDocumentSyncAttempt,\n projectionFailureHandler,\n} from \"./syncAttemptPlanning\";\nimport type {\n RemoteDocumentSyncAttemptOutcome,\n RemoteDocumentSyncAttemptState,\n} from \"./syncAttemptState\";\nimport { requireStandaloneAncestorRepairs } from \"./syncContainerRekeyPreparation\";\nimport {\n assertRawContinuationCanRetry,\n resolveSyncAttemptWriterProjection,\n submitDocumentSyncAttemptIfAllowed,\n} from \"./syncFailures\";\nimport { recoverablePendingUpdates } from \"./syncPlanRequestBounds\";\nimport { resolveSubmittedDocumentSyncResult } from \"./syncSubmittedResult\";\n\nexport function hasDocumentUpdateEvent(\n events: ReadonlyArray<unknown>,\n documentId: string | null | undefined,\n): boolean {\n if (!documentId) return false;\n return events.some(\n (event) =>\n isDocumentUpdateCreatedEvent(event) && event.documentId === documentId,\n );\n}\n/**\n * A retryable stale-projection conflict means this writer projection is behind\n * the server. Evict only this document so the next attempt re-derives targets.\n */\nfunction evictStaleProjectionForRetry(input: SyncRemoteDocumentInput): void {\n input.apiClient.evictDocumentWriterProjection?.(input.documentId);\n}\n\n/**\n * A pass may repair a covering-baseline rejection by regenerating queued\n * rotation checkpoints — but only when there is something to regenerate FROM\n * (a snapshot provider and queued checkpoint rows), the failed pass was not\n * already a heal or a regeneration (whose fresh baseline proves this device\n * is simply behind), and an attempt remains.\n */\nfunction canRegenerateQueuedCheckpoints(input: {\n materializedPlan: MaterializedDocumentSyncPlan;\n pendingUpdates: readonly PendingUpdateRecord[];\n regenerateQueuedCheckpoints: boolean;\n sync: SyncRemoteDocumentInput;\n}): boolean {\n return (\n !input.regenerateQueuedCheckpoints &&\n !input.materializedPlan.healedStaleContentKeyBundle &&\n input.sync.buildRotationSnapshot !== undefined &&\n input.pendingUpdates.some((update) => update.sourceVersionVector != null)\n );\n}\n\nasync function submitPlannedSyncAttempt(args: {\n attempt: number;\n materializedPlan: MaterializedDocumentSyncPlan;\n maxAttempts: number;\n pendingUpdates: readonly PendingUpdateRecord[];\n pullContinuation?: DocumentSyncPullContinuation | undefined;\n regenerateQueuedCheckpoints: boolean;\n sync: SyncRemoteDocumentInput;\n failureBlocksQueuedWrites: boolean;\n}) {\n try {\n return await submitDocumentSyncAttemptIfAllowed({\n apiClient: args.sync.apiClient,\n attempt: args.attempt,\n canRegenerateQueuedCheckpoints: canRegenerateQueuedCheckpoints({\n materializedPlan: args.materializedPlan,\n pendingUpdates: args.pendingUpdates,\n regenerateQueuedCheckpoints: args.regenerateQueuedCheckpoints,\n sync: args.sync,\n }),\n documentId: args.sync.documentId,\n expectedCommitLsnMode: args.pullContinuation?.commitLsnMode,\n isRemoteSyncBlocked: args.sync.isRemoteSyncBlocked,\n maxAttempts: args.maxAttempts,\n onInlineRepairRefused: () => requireStandaloneAncestorRepairs(args.sync),\n onRemoteDocumentDeleted: args.sync.onRemoteDocumentDeleted,\n onOutgoingUpdatesMaterialized: args.sync.onOutgoingUpdatesMaterialized,\n onSyncTrace: args.sync.onSyncTrace,\n onTerminalSubmitFailure: args.sync.onTerminalSubmitFailure,\n pendingUpdates: args.pendingUpdates,\n plan: args.materializedPlan.plan,\n failureBlocksQueuedWrites: args.failureBlocksQueuedWrites,\n stillCurrent: args.sync.stillCurrent,\n warmReferencedPrincipalPolicies:\n args.sync.warmReferencedPrincipalPolicies,\n });\n } catch (error) {\n if (\n error instanceof InvalidDocumentSyncPullContinuationError &&\n args.pullContinuation !== undefined &&\n args.sync.historyMode !== \"raw\"\n ) {\n return \"retry\" as const;\n }\n throw error;\n }\n}\n\nfunction resolveAttemptProjection(\n input: SyncRemoteDocumentInput,\n failureBlocksQueuedWrites: boolean,\n reusableWriterProjection: DocumentWriterProjectionResponse | null,\n) {\n return resolveSyncAttemptWriterProjection({\n apiClient: input.apiClient,\n documentId: input.documentId,\n onRemoteDocumentDeleted: input.onRemoteDocumentDeleted,\n onSyncAbandoned: input.onSyncAbandoned,\n onSyncTrace: input.onSyncTrace,\n onTerminalFailure: projectionFailureHandler(\n input,\n failureBlocksQueuedWrites,\n ),\n reusableWriterProjection,\n stillCurrent: input.stillCurrent,\n });\n}\nfunction resolveRemoteSyncProjectionUserKey(input: SyncRemoteDocumentInput) {\n return requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote document sync\",\n );\n}\n\nasync function invalidatePullCursor(\n input: SyncRemoteDocumentInput,\n pullContinuation: DocumentSyncPullContinuation | undefined,\n): Promise<undefined> {\n if (pullContinuation !== undefined) {\n await input.onPullContinuationInvalidated?.(pullContinuation);\n }\n return undefined;\n}\n\nasync function preparePersistedDocumentSync(\n input: SyncRemoteDocumentInput,\n resolveProjectionUserKey: ProjectionUserKeyResolver,\n): Promise<\n | { readonly kind: \"completed\"; result: SyncRemoteDocumentResult | null }\n | {\n readonly kind: \"continue\";\n pullContinuation: DocumentSyncPullContinuation | undefined;\n }\n> {\n let pullContinuation = input.pullContinuation;\n try {\n const persisted = await tryPersistedReadOnlyDocumentSync(\n input,\n resolveProjectionUserKey,\n );\n if (persisted?.kind === \"completed\") return persisted;\n if (persisted?.kind === \"not_completed\" && input.historyMode !== \"raw\") {\n pullContinuation = await invalidatePullCursor(input, pullContinuation);\n }\n } catch (error) {\n if (\n !(error instanceof InvalidDocumentSyncPullContinuationError) ||\n pullContinuation === undefined ||\n input.historyMode === \"raw\"\n ) {\n throw error;\n }\n pullContinuation = await invalidatePullCursor(input, pullContinuation);\n }\n return { kind: \"continue\", pullContinuation };\n}\n\nfunction failureBlocksQueuedWrites(input: {\n readonly pendingUpdates: readonly PendingUpdateRecord[];\n readonly recoveryPendingUpdateCount: number;\n}): boolean {\n return (\n input.pendingUpdates.length > 0 || input.recoveryPendingUpdateCount > 0\n );\n}\n\nasync function retryRemoteSyncAttempt(\n sync: SyncRemoteDocumentInput,\n continuation: DocumentSyncPullContinuation | undefined,\n): Promise<RemoteDocumentSyncAttemptOutcome> {\n evictStaleProjectionForRetry(sync);\n return {\n kind: \"retry\",\n pullContinuation: await invalidatePullCursor(sync, continuation),\n };\n}\n\nasync function runRemoteDocumentSyncAttempt(input: {\n attempt: number;\n maxAttempts: number;\n pendingUpdateIds: readonly string[];\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n state: RemoteDocumentSyncAttemptState;\n sync: SyncRemoteDocumentInput;\n}): Promise<RemoteDocumentSyncAttemptOutcome> {\n if (input.sync.stillCurrent?.() === false) {\n return { kind: \"complete\", result: null };\n }\n const blocksQueuedWrites = failureBlocksQueuedWrites({\n pendingUpdates: input.state.pendingUpdates,\n recoveryPendingUpdateCount: input.state.recoveryPendingUpdatesById.size,\n });\n const writerProjection = await resolveAttemptProjection(\n input.sync,\n blocksQueuedWrites,\n input.state.reusableWriterProjection,\n );\n if (input.sync.stillCurrent?.() === false || !writerProjection) {\n return { kind: \"complete\", result: null };\n }\n const planned = await planDocumentSyncAttempt({\n pendingUpdates: input.state.pendingUpdates,\n pullContinuation: input.state.pullContinuation,\n regenerateQueuedCheckpoints: input.state.regenerateQueuedCheckpoints,\n sync: input.sync,\n failureBlocksQueuedWrites: blocksQueuedWrites,\n writerProjection,\n });\n if (planned === \"retry\") {\n return retryRemoteSyncAttempt(input.sync, input.state.pullContinuation);\n }\n if (!planned || input.sync.stillCurrent?.() === false) {\n return { kind: \"complete\", result: null };\n }\n const [materializedPlan] = planned;\n const submitted = await submitPlannedSyncAttempt({\n attempt: input.attempt,\n materializedPlan,\n maxAttempts: input.maxAttempts,\n pendingUpdates: recoverablePendingUpdates(\n input.state.pendingUpdates,\n materializedPlan,\n ),\n pullContinuation: input.state.pullContinuation,\n regenerateQueuedCheckpoints: input.state.regenerateQueuedCheckpoints,\n sync: input.sync,\n failureBlocksQueuedWrites: blocksQueuedWrites,\n });\n if (input.sync.stillCurrent?.() === false || submitted === \"cancelled\") {\n return { kind: \"complete\", result: null };\n }\n if (submitted === \"retry\") {\n assertRawContinuationCanRetry(\n input.sync.historyMode,\n input.state.pullContinuation,\n );\n return retryRemoteSyncAttempt(input.sync, input.state.pullContinuation);\n }\n if (submitted === \"blocked\") {\n abandonBlockedSync(input.sync);\n return { kind: \"complete\", result: null };\n }\n if (submitted === \"stop\") {\n input.sync.onSyncAbandoned?.(\"the sync submit failed terminally\");\n return { kind: \"complete\", result: null };\n }\n if (submitted.kind === \"regenerate_queued_checkpoints\") {\n return { kind: \"regenerate\" };\n }\n if (submitted.kind === \"recover_update_id_conflict\") {\n // A lost response may mean the server committed both this update id and an\n // inline container rekey. Force the read-only recovery pass to observe that\n // committed successor projection instead of reusing a cached predecessor.\n evictStaleProjectionForRetry(input.sync);\n return { kind: \"recover\", updates: submitted.recoveryPendingUpdatesById };\n }\n const result = await resolveSubmittedDocumentSyncResult({\n materializedPlan,\n pendingUpdateIds: input.pendingUpdateIds,\n pullComplete: submitted.pullComplete,\n recoveryPendingUpdatesById: input.state.recoveryPendingUpdatesById,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n response: submitted.response,\n sync: input.sync,\n writerProjection: materializedPlan.writerProjection,\n });\n return {\n kind: \"complete\",\n result: input.sync.stillCurrent?.() === false ? null : result,\n };\n}\n\nasync function syncRemoteDocumentInternal(\n input: SyncRemoteDocumentInput,\n): Promise<SyncRemoteDocumentResult | null> {\n if (input.stillCurrent?.() === false) return null;\n const resolveProjectionUserKey = resolveRemoteSyncProjectionUserKey(input);\n const maxAttempts = 3;\n let pendingUpdates = input.pendingUpdates ?? [];\n const pendingUpdateIds = pendingUpdates.map((update) => update.id);\n let recoveryPendingUpdatesById = new Map<string, PendingUpdateRecord>();\n let regenerateQueuedCheckpoints = false;\n let reusableWriterProjection = input.writerProjection ?? null;\n const persistedSync = await preparePersistedDocumentSync(\n input,\n resolveProjectionUserKey,\n );\n if (input.stillCurrent?.() === false) return null;\n if (persistedSync.kind === \"completed\") return persistedSync.result;\n let pullContinuation = persistedSync.pullContinuation;\n for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n const outcome = await runRemoteDocumentSyncAttempt({\n attempt,\n maxAttempts,\n pendingUpdateIds,\n resolveProjectionUserKey,\n state: {\n pendingUpdates,\n pullContinuation,\n recoveryPendingUpdatesById,\n regenerateQueuedCheckpoints,\n reusableWriterProjection,\n },\n sync: input,\n });\n reusableWriterProjection = null;\n if (outcome.kind === \"complete\") return outcome.result;\n if (outcome.kind === \"retry\") {\n pullContinuation = outcome.pullContinuation;\n if (input.stillCurrent?.() === false) return null;\n continue;\n }\n if (outcome.kind === \"regenerate\") {\n regenerateQueuedCheckpoints = true;\n continue;\n }\n recoveryPendingUpdatesById = outcome.updates;\n pendingUpdates = [];\n }\n return abandonAfterRetryableConflicts(input);\n}\n\nexport async function syncRemoteDocument(\n input: SyncRemoteDocumentInput,\n): Promise<SyncRemoteDocumentResult | null> {\n try {\n return await syncRemoteDocumentInternal({\n ...input,\n onRemoteDocumentDeleted: createVerifiedRemoteDocumentDeletionHandler({\n apiClient: input.apiClient,\n execSql: input.execSql,\n expectedOrganizationId: input.author.organizationId,\n onVerifiedDeletion: ({ commitPurgeProof, documentId }) => {\n if (input.stillCurrent?.() === false) return;\n if (!input.onRemoteDocumentDeleted) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Remote document deletion requires atomic local teardown\",\n );\n }\n return input.onRemoteDocumentDeleted({\n commitPurgeProof,\n documentId,\n });\n },\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n });\n } catch (error) {\n if (isProjectionVerificationCancelledError(error)) return null;\n if (\n input.stillCurrent?.() !== false &&\n isDocumentSyncUpdateIsolationError(error)\n ) {\n await input.onIncomingUpdateIsolationFailure?.(error);\n }\n throw error;\n }\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import { DOCUMENT_SYNC_ERROR_CODES, } from "../../internal/validators/response/i
|
|
|
2
2
|
import { isUpstreamDeletedDocumentSyncFailure, submitDocumentSync, } from "../../data/documents/shared/responses.js";
|
|
3
3
|
import { InvalidDocumentSyncPullContinuationError, } from "../../data/documents/shared/syncPagination.js";
|
|
4
4
|
import { canRecoverDocumentUpdateIdConflict, canRetryDocumentSyncConflict, handleUpstreamDeletedDocumentSyncFailure, isCheckpointCoverageConflict, shouldRetrySyncWithFreshWriterProjection, } from "./syncFailureClassification.js";
|
|
5
|
-
import {
|
|
5
|
+
import { recoverDocumentSyncPolicyRepair } from "./syncPolicyRepair.js";
|
|
6
6
|
import { traceProjectionFailed, traceSubmitFailed, } from "./syncTrace.js";
|
|
7
7
|
const REMOTE_DOCUMENT_DELETED = Symbol("remoteDocumentDeleted");
|
|
8
8
|
export function assertRawContinuationCanRetry(historyMode, pullContinuation) {
|
|
@@ -88,7 +88,7 @@ async function submitDocumentSyncAttempt(input) {
|
|
|
88
88
|
response: submitted.response,
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
-
await
|
|
91
|
+
await recoverDocumentSyncPolicyRepair({
|
|
92
92
|
failure: submitted,
|
|
93
93
|
plan: input.plan,
|
|
94
94
|
stillCurrent: input.stillCurrent,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncFailures.js","sourceRoot":"","sources":["syncFailures.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DOCUMENT_SYNC_ERROR_CODES,\n type DocumentSyncResponse,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport {\n isUpstreamDeletedDocumentSyncFailure,\n submitDocumentSync,\n} from \"../../data/documents/shared/responses\";\nimport {\n type DocumentSyncCommitLsnMode,\n type DocumentSyncPullContinuation,\n InvalidDocumentSyncPullContinuationError,\n} from \"../../data/documents/shared/syncPagination\";\nimport type {\n DocumentSyncApi,\n DocumentSyncPlan,\n DocumentSyncSubmitFailure,\n MaterializedDocumentSyncPlan,\n} from \"../../data/documents/shared/types\";\nimport type { ReferencedPrincipalPolicyWarmer } from \"../../data/keyingProjectionVerification\";\nimport type { PendingUpdateRecord } from \"../../data/sqlite/documentPersistence\";\nimport {\n canRecoverDocumentUpdateIdConflict,\n canRetryDocumentSyncConflict,\n handleUpstreamDeletedDocumentSyncFailure,\n isCheckpointCoverageConflict,\n type RemoteDocumentDeletionHandler,\n shouldRetrySyncWithFreshWriterProjection,\n type TerminalSubmitFailureHandler,\n} from \"./syncFailureClassification\";\nimport { cacheDocumentSyncPolicyRepair } from \"./syncPolicyRepair\";\nimport {\n type DocumentSyncTraceEmitter,\n traceProjectionFailed,\n traceSubmitFailed,\n} from \"./syncTrace\";\n\nconst REMOTE_DOCUMENT_DELETED = Symbol(\"remoteDocumentDeleted\");\n\nexport function assertRawContinuationCanRetry(\n historyMode: \"raw\" | undefined,\n pullContinuation: DocumentSyncPullContinuation | undefined,\n): void {\n if (historyMode === \"raw\" && pullContinuation !== undefined) {\n throw new InvalidDocumentSyncPullContinuationError(\n \"Document raw-history continuation became stale\",\n );\n }\n}\n\ntype DocumentWriterProjectionResolution =\n | DocumentWriterProjectionResponse\n | typeof REMOTE_DOCUMENT_DELETED\n | null;\n\ntype FailedDocumentSyncAction =\n | \"retry\"\n | \"stop\"\n | {\n readonly kind: \"recover_update_id_conflict\";\n readonly recoveryPendingUpdatesById: Map<string, PendingUpdateRecord>;\n }\n | { readonly kind: \"regenerate_queued_checkpoints\" };\n\ntype DocumentSyncAttemptSubmission =\n | {\n readonly kind: \"completed\";\n readonly pullComplete: boolean;\n readonly response: DocumentSyncResponse;\n }\n | FailedDocumentSyncAction\n | \"cancelled\"\n | \"blocked\";\n\nasync function resolveFailedDocumentSyncAction(input: {\n attempt: number;\n canRegenerateQueuedCheckpoints?: boolean | undefined;\n documentId: string;\n failure: DocumentSyncSubmitFailure;\n maxAttempts: number;\n onInlineRepairRefused?: (() => void) | undefined;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalSubmitFailure?: TerminalSubmitFailureHandler | undefined;\n pendingUpdates: readonly PendingUpdateRecord[];\n}): Promise<FailedDocumentSyncAction> {\n const action = await classifyFailedDocumentSyncAction(input);\n traceSubmitFailed(input.onSyncTrace, {\n action:\n action === \"retry\" || action === \"stop\"\n ? action\n : action.kind === \"recover_update_id_conflict\"\n ? \"recover-update-ids\"\n : \"regenerate-checkpoints\",\n code: input.failure.code,\n documentId: input.documentId,\n status: input.failure.status,\n });\n return action;\n}\n\nasync function classifyFailedDocumentSyncAction(input: {\n attempt: number;\n canRegenerateQueuedCheckpoints?: boolean | undefined;\n documentId: string;\n failure: DocumentSyncSubmitFailure;\n maxAttempts: number;\n onInlineRepairRefused?: (() => void) | undefined;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onTerminalSubmitFailure?: TerminalSubmitFailureHandler | undefined;\n pendingUpdates: readonly PendingUpdateRecord[];\n}): Promise<FailedDocumentSyncAction> {\n if (\n await handleUpstreamDeletedDocumentSyncFailure({\n documentId: input.documentId,\n failure: input.failure,\n onRemoteDocumentDeleted: input.onRemoteDocumentDeleted,\n })\n ) {\n return \"stop\";\n }\n\n if (\n canRetryDocumentSyncConflict({\n attempt: input.attempt,\n failure: input.failure,\n maxAttempts: input.maxAttempts,\n })\n ) {\n return \"retry\";\n }\n\n // The write rolled back whole. Its inline repairs would have stranded a\n // level above a directly granted container, and a flat rekey list cannot say\n // what each must carry: the retry commits them standalone instead.\n if (\n input.attempt < input.maxAttempts &&\n input.onInlineRepairRefused &&\n input.failure.code === DOCUMENT_SYNC_ERROR_CODES.descendantRekeysRequired\n ) {\n input.onInlineRepairRefused();\n return \"retry\";\n }\n\n if (\n canRecoverDocumentUpdateIdConflict({\n attempt: input.attempt,\n failure: input.failure,\n maxAttempts: input.maxAttempts,\n pendingUpdateCount: input.pendingUpdates.length,\n })\n ) {\n return {\n kind: \"recover_update_id_conflict\",\n recoveryPendingUpdatesById: new Map(\n input.pendingUpdates.map((update) => [update.id, update]),\n ),\n };\n }\n\n if (\n input.attempt < input.maxAttempts &&\n input.canRegenerateQueuedCheckpoints === true &&\n isCheckpointCoverageConflict(input.failure)\n ) {\n return { kind: \"regenerate_queued_checkpoints\" };\n }\n\n input.failure.report();\n await input.onTerminalSubmitFailure?.(input.failure);\n return \"stop\";\n}\n\nasync function submitDocumentSyncAttempt(input: {\n apiClient: DocumentSyncApi;\n attempt: number;\n canRegenerateQueuedCheckpoints?: boolean | undefined;\n documentId: string;\n expectedCommitLsnMode?: DocumentSyncCommitLsnMode | undefined;\n maxAttempts: number;\n onInlineRepairRefused?: (() => void) | undefined;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalSubmitFailure?: TerminalSubmitFailureHandler | undefined;\n pendingUpdates: readonly PendingUpdateRecord[];\n plan: DocumentSyncPlan;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<DocumentSyncAttemptSubmission> {\n if (input.stillCurrent?.() === false) return \"cancelled\";\n const submitted = await submitDocumentSync({\n apiClient: input.apiClient,\n expectedCommitLsnMode: input.expectedCommitLsnMode,\n plan: input.plan,\n });\n if (input.stillCurrent?.() === false) return \"cancelled\";\n if (!submitted) {\n return \"stop\";\n }\n if (submitted.ok) {\n return {\n kind: \"completed\",\n pullComplete: submitted.pullComplete,\n response: submitted.response,\n };\n }\n\n await cacheDocumentSyncPolicyRepair({\n failure: submitted,\n plan: input.plan,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n if (input.stillCurrent?.() === false) return \"cancelled\";\n\n return resolveFailedDocumentSyncAction({\n attempt: input.attempt,\n canRegenerateQueuedCheckpoints: input.canRegenerateQueuedCheckpoints,\n documentId: input.documentId,\n failure: submitted,\n maxAttempts: input.maxAttempts,\n onInlineRepairRefused: input.onInlineRepairRefused,\n onRemoteDocumentDeleted: input.onRemoteDocumentDeleted,\n onSyncTrace: input.onSyncTrace,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n pendingUpdates: input.pendingUpdates,\n });\n}\n\nexport async function submitDocumentSyncAttemptIfAllowed(\n input: Parameters<typeof submitDocumentSyncAttempt>[0] & {\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n onOutgoingUpdatesMaterialized?:\n | ((updateIds: readonly string[]) => void)\n | undefined;\n failureBlocksQueuedWrites?: boolean | undefined;\n },\n): Promise<DocumentSyncAttemptSubmission> {\n const {\n failureBlocksQueuedWrites,\n isRemoteSyncBlocked,\n onOutgoingUpdatesMaterialized,\n ...submissionInput\n } = input;\n const hasRemoteWrites =\n input.plan.request.outgoingUpdates.length > 0 ||\n (input.plan.request.containerRekeys?.length ?? 0) > 0;\n if (hasRemoteWrites && isRemoteSyncBlocked?.(input.plan.organizationId)) {\n return \"blocked\";\n }\n if (input.stillCurrent?.() === false) return \"cancelled\";\n\n onOutgoingUpdatesMaterialized?.(\n input.plan.request.outgoingUpdates.map(({ id }) => id),\n );\n\n return submitDocumentSyncAttempt({\n ...submissionInput,\n // A read-only pass carries no writes, so a terminal failure describes a\n // pull, not queued local data — recording it would flag the next local\n // edit as failed before it was ever attempted. A cursor continuation and\n // update-id recovery both submit an empty request while durable rows still\n // exist; a terminal 403 there IS what blocks the queued edits.\n onTerminalSubmitFailure:\n hasRemoteWrites || failureBlocksQueuedWrites\n ? submissionInput.onTerminalSubmitFailure\n : undefined,\n });\n}\n\nasync function resolveDocumentSyncWriterProjection(input: {\n apiClient: DocumentSyncApi;\n documentId: string;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n /**\n * Invoked when the projection fetch fails terminally. Write-bearing sync\n * passes persist this: without a writer projection their queued writes can\n * never submit, so the failure (e.g. a 403 after access revocation) is what\n * the write queue should surface.\n */\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n reusableWriterProjection: DocumentWriterProjectionResponse | null;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<DocumentWriterProjectionResolution> {\n if (input.stillCurrent?.() === false) return null;\n if (input.reusableWriterProjection) {\n return input.reusableWriterProjection;\n }\n\n const result = await input.apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (input.stillCurrent?.() === false) return null;\n if (result.ok) {\n return result.data;\n }\n if (isUpstreamDeletedDocumentSyncFailure(result)) {\n return REMOTE_DOCUMENT_DELETED;\n }\n traceProjectionFailed(input.onSyncTrace, {\n code: result.code,\n documentId: input.documentId,\n status: result.status,\n });\n result.report();\n await input.onTerminalFailure?.(result);\n return null;\n}\n\nexport async function retrySyncPlan(input: {\n apiClient: DocumentSyncApi;\n buildWithProjection: (\n projection: DocumentWriterProjectionResponse,\n ) => Promise<MaterializedDocumentSyncPlan>;\n documentId: string;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n stillCurrent?: (() => boolean) | undefined;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<\n | readonly [MaterializedDocumentSyncPlan, DocumentWriterProjectionResponse]\n | null\n> {\n try {\n return [\n await input.buildWithProjection(input.writerProjection),\n input.writerProjection,\n ];\n } catch (error) {\n if (\n !input.apiClient.evictDocumentWriterProjection ||\n !shouldRetrySyncWithFreshWriterProjection(error)\n ) {\n throw error;\n }\n }\n if (input.stillCurrent?.() === false) return null;\n\n // Only this document's projection was stale; evict just it so unrelated\n // documents keep their warm cache instead of a global wipe.\n input.apiClient.evictDocumentWriterProjection?.(input.documentId);\n const writerProjection = await resolveDocumentSyncWriterProjection({\n apiClient: input.apiClient,\n documentId: input.documentId,\n onSyncTrace: input.onSyncTrace,\n onTerminalFailure: input.onTerminalFailure,\n reusableWriterProjection: null,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n if (writerProjection === REMOTE_DOCUMENT_DELETED) {\n await input.onRemoteDocumentDeleted?.({ documentId: input.documentId });\n return null;\n }\n if (!writerProjection) {\n return null;\n }\n\n return [await input.buildWithProjection(writerProjection), writerProjection];\n}\n\n/**\n * Resolves the writer projection for one sync attempt, converting the two\n * unrecoverable outcomes into an abandoned (null) result with a named reason\n * so callers that turn a null sync into their own error can surface the real\n * cause.\n */\nexport async function resolveSyncAttemptWriterProjection(input: {\n apiClient: DocumentSyncApi;\n documentId: string;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncAbandoned?: ((reason: string) => void) | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n reusableWriterProjection: DocumentWriterProjectionResponse | null;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<DocumentWriterProjectionResponse | null> {\n const writerProjection = await resolveDocumentSyncWriterProjection(input);\n if (input.stillCurrent?.() === false) return null;\n if (writerProjection === REMOTE_DOCUMENT_DELETED) {\n await input.onRemoteDocumentDeleted?.({ documentId: input.documentId });\n if (input.stillCurrent?.() !== false) {\n input.onSyncAbandoned?.(\"the remote document was deleted\");\n }\n return null;\n }\n if (!writerProjection) {\n input.onSyncAbandoned?.(\n \"the document writer projection could not be fetched\",\n );\n return null;\n }\n return writerProjection;\n}\n\nexport async function refreshSyncAttemptWriterProjection(\n input: Omit<\n Parameters<typeof resolveSyncAttemptWriterProjection>[0],\n \"reusableWriterProjection\"\n > & { unavailableError?: unknown },\n): Promise<DocumentWriterProjectionResponse | null> {\n const { onRemoteDocumentDeleted, unavailableError, ...resolutionInput } =\n input;\n if (input.stillCurrent?.() === false) return null;\n if (input.apiClient.evictDocumentWriterProjection) {\n input.apiClient.evictDocumentWriterProjection(input.documentId);\n } else {\n input.apiClient.clearWriterProjectionCaches?.();\n }\n let remoteDocumentDeleted = false;\n const writerProjection = await resolveSyncAttemptWriterProjection({\n ...resolutionInput,\n onRemoteDocumentDeleted: async (deleted) => {\n remoteDocumentDeleted = true;\n await onRemoteDocumentDeleted?.(deleted);\n },\n reusableWriterProjection: null,\n });\n if (\n !writerProjection &&\n unavailableError !== undefined &&\n !remoteDocumentDeleted &&\n input.stillCurrent?.() !== false\n ) {\n throw unavailableError;\n }\n return writerProjection;\n}\n\nexport async function retrySyncPlanOrAbandon(input: {\n apiClient: DocumentSyncApi;\n buildWithProjection: (\n projection: DocumentWriterProjectionResponse,\n ) => Promise<MaterializedDocumentSyncPlan>;\n documentId: string;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncAbandoned?: ((reason: string) => void) | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n stillCurrent?: (() => boolean) | undefined;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<\n | readonly [MaterializedDocumentSyncPlan, DocumentWriterProjectionResponse]\n | null\n> {\n const planned = await retrySyncPlan(input);\n if (!planned && input.stillCurrent?.() !== false) {\n input.onSyncAbandoned?.(\n \"a sync plan could not be built against the current projection\",\n );\n }\n return planned;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"syncFailures.js","sourceRoot":"","sources":["syncFailures.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DOCUMENT_SYNC_ERROR_CODES,\n type DocumentSyncResponse,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport {\n isUpstreamDeletedDocumentSyncFailure,\n submitDocumentSync,\n} from \"../../data/documents/shared/responses\";\nimport {\n type DocumentSyncCommitLsnMode,\n type DocumentSyncPullContinuation,\n InvalidDocumentSyncPullContinuationError,\n} from \"../../data/documents/shared/syncPagination\";\nimport type {\n DocumentSyncApi,\n DocumentSyncPlan,\n DocumentSyncSubmitFailure,\n MaterializedDocumentSyncPlan,\n} from \"../../data/documents/shared/types\";\nimport type { ReferencedPrincipalPolicyWarmer } from \"../../data/keyingProjectionVerification\";\nimport type { PendingUpdateRecord } from \"../../data/sqlite/documentPersistence\";\nimport {\n canRecoverDocumentUpdateIdConflict,\n canRetryDocumentSyncConflict,\n handleUpstreamDeletedDocumentSyncFailure,\n isCheckpointCoverageConflict,\n type RemoteDocumentDeletionHandler,\n shouldRetrySyncWithFreshWriterProjection,\n type TerminalSubmitFailureHandler,\n} from \"./syncFailureClassification\";\nimport { recoverDocumentSyncPolicyRepair } from \"./syncPolicyRepair\";\nimport {\n type DocumentSyncTraceEmitter,\n traceProjectionFailed,\n traceSubmitFailed,\n} from \"./syncTrace\";\n\nconst REMOTE_DOCUMENT_DELETED = Symbol(\"remoteDocumentDeleted\");\n\nexport function assertRawContinuationCanRetry(\n historyMode: \"raw\" | undefined,\n pullContinuation: DocumentSyncPullContinuation | undefined,\n): void {\n if (historyMode === \"raw\" && pullContinuation !== undefined) {\n throw new InvalidDocumentSyncPullContinuationError(\n \"Document raw-history continuation became stale\",\n );\n }\n}\n\ntype DocumentWriterProjectionResolution =\n | DocumentWriterProjectionResponse\n | typeof REMOTE_DOCUMENT_DELETED\n | null;\n\ntype FailedDocumentSyncAction =\n | \"retry\"\n | \"stop\"\n | {\n readonly kind: \"recover_update_id_conflict\";\n readonly recoveryPendingUpdatesById: Map<string, PendingUpdateRecord>;\n }\n | { readonly kind: \"regenerate_queued_checkpoints\" };\n\ntype DocumentSyncAttemptSubmission =\n | {\n readonly kind: \"completed\";\n readonly pullComplete: boolean;\n readonly response: DocumentSyncResponse;\n }\n | FailedDocumentSyncAction\n | \"cancelled\"\n | \"blocked\";\n\nasync function resolveFailedDocumentSyncAction(input: {\n attempt: number;\n canRegenerateQueuedCheckpoints?: boolean | undefined;\n documentId: string;\n failure: DocumentSyncSubmitFailure;\n maxAttempts: number;\n onInlineRepairRefused?: (() => void) | undefined;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalSubmitFailure?: TerminalSubmitFailureHandler | undefined;\n pendingUpdates: readonly PendingUpdateRecord[];\n}): Promise<FailedDocumentSyncAction> {\n const action = await classifyFailedDocumentSyncAction(input);\n traceSubmitFailed(input.onSyncTrace, {\n action:\n action === \"retry\" || action === \"stop\"\n ? action\n : action.kind === \"recover_update_id_conflict\"\n ? \"recover-update-ids\"\n : \"regenerate-checkpoints\",\n code: input.failure.code,\n documentId: input.documentId,\n status: input.failure.status,\n });\n return action;\n}\n\nasync function classifyFailedDocumentSyncAction(input: {\n attempt: number;\n canRegenerateQueuedCheckpoints?: boolean | undefined;\n documentId: string;\n failure: DocumentSyncSubmitFailure;\n maxAttempts: number;\n onInlineRepairRefused?: (() => void) | undefined;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onTerminalSubmitFailure?: TerminalSubmitFailureHandler | undefined;\n pendingUpdates: readonly PendingUpdateRecord[];\n}): Promise<FailedDocumentSyncAction> {\n if (\n await handleUpstreamDeletedDocumentSyncFailure({\n documentId: input.documentId,\n failure: input.failure,\n onRemoteDocumentDeleted: input.onRemoteDocumentDeleted,\n })\n ) {\n return \"stop\";\n }\n\n if (\n canRetryDocumentSyncConflict({\n attempt: input.attempt,\n failure: input.failure,\n maxAttempts: input.maxAttempts,\n })\n ) {\n return \"retry\";\n }\n\n // The write rolled back whole. Its inline repairs would have stranded a\n // level above a directly granted container, and a flat rekey list cannot say\n // what each must carry: the retry commits them standalone instead.\n if (\n input.attempt < input.maxAttempts &&\n input.onInlineRepairRefused &&\n input.failure.code === DOCUMENT_SYNC_ERROR_CODES.descendantRekeysRequired\n ) {\n input.onInlineRepairRefused();\n return \"retry\";\n }\n\n if (\n canRecoverDocumentUpdateIdConflict({\n attempt: input.attempt,\n failure: input.failure,\n maxAttempts: input.maxAttempts,\n pendingUpdateCount: input.pendingUpdates.length,\n })\n ) {\n return {\n kind: \"recover_update_id_conflict\",\n recoveryPendingUpdatesById: new Map(\n input.pendingUpdates.map((update) => [update.id, update]),\n ),\n };\n }\n\n if (\n input.attempt < input.maxAttempts &&\n input.canRegenerateQueuedCheckpoints === true &&\n isCheckpointCoverageConflict(input.failure)\n ) {\n return { kind: \"regenerate_queued_checkpoints\" };\n }\n\n input.failure.report();\n await input.onTerminalSubmitFailure?.(input.failure);\n return \"stop\";\n}\n\nasync function submitDocumentSyncAttempt(input: {\n apiClient: DocumentSyncApi;\n attempt: number;\n canRegenerateQueuedCheckpoints?: boolean | undefined;\n documentId: string;\n expectedCommitLsnMode?: DocumentSyncCommitLsnMode | undefined;\n maxAttempts: number;\n onInlineRepairRefused?: (() => void) | undefined;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalSubmitFailure?: TerminalSubmitFailureHandler | undefined;\n pendingUpdates: readonly PendingUpdateRecord[];\n plan: DocumentSyncPlan;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<DocumentSyncAttemptSubmission> {\n if (input.stillCurrent?.() === false) return \"cancelled\";\n const submitted = await submitDocumentSync({\n apiClient: input.apiClient,\n expectedCommitLsnMode: input.expectedCommitLsnMode,\n plan: input.plan,\n });\n if (input.stillCurrent?.() === false) return \"cancelled\";\n if (!submitted) {\n return \"stop\";\n }\n if (submitted.ok) {\n return {\n kind: \"completed\",\n pullComplete: submitted.pullComplete,\n response: submitted.response,\n };\n }\n\n await recoverDocumentSyncPolicyRepair({\n failure: submitted,\n plan: input.plan,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n if (input.stillCurrent?.() === false) return \"cancelled\";\n\n return resolveFailedDocumentSyncAction({\n attempt: input.attempt,\n canRegenerateQueuedCheckpoints: input.canRegenerateQueuedCheckpoints,\n documentId: input.documentId,\n failure: submitted,\n maxAttempts: input.maxAttempts,\n onInlineRepairRefused: input.onInlineRepairRefused,\n onRemoteDocumentDeleted: input.onRemoteDocumentDeleted,\n onSyncTrace: input.onSyncTrace,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n pendingUpdates: input.pendingUpdates,\n });\n}\n\nexport async function submitDocumentSyncAttemptIfAllowed(\n input: Parameters<typeof submitDocumentSyncAttempt>[0] & {\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n onOutgoingUpdatesMaterialized?:\n | ((updateIds: readonly string[]) => void)\n | undefined;\n failureBlocksQueuedWrites?: boolean | undefined;\n },\n): Promise<DocumentSyncAttemptSubmission> {\n const {\n failureBlocksQueuedWrites,\n isRemoteSyncBlocked,\n onOutgoingUpdatesMaterialized,\n ...submissionInput\n } = input;\n const hasRemoteWrites =\n input.plan.request.outgoingUpdates.length > 0 ||\n (input.plan.request.containerRekeys?.length ?? 0) > 0;\n if (hasRemoteWrites && isRemoteSyncBlocked?.(input.plan.organizationId)) {\n return \"blocked\";\n }\n if (input.stillCurrent?.() === false) return \"cancelled\";\n\n onOutgoingUpdatesMaterialized?.(\n input.plan.request.outgoingUpdates.map(({ id }) => id),\n );\n\n return submitDocumentSyncAttempt({\n ...submissionInput,\n // A read-only pass carries no writes, so a terminal failure describes a\n // pull, not queued local data — recording it would flag the next local\n // edit as failed before it was ever attempted. A cursor continuation and\n // update-id recovery both submit an empty request while durable rows still\n // exist; a terminal 403 there IS what blocks the queued edits.\n onTerminalSubmitFailure:\n hasRemoteWrites || failureBlocksQueuedWrites\n ? submissionInput.onTerminalSubmitFailure\n : undefined,\n });\n}\n\nasync function resolveDocumentSyncWriterProjection(input: {\n apiClient: DocumentSyncApi;\n documentId: string;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n /**\n * Invoked when the projection fetch fails terminally. Write-bearing sync\n * passes persist this: without a writer projection their queued writes can\n * never submit, so the failure (e.g. a 403 after access revocation) is what\n * the write queue should surface.\n */\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n reusableWriterProjection: DocumentWriterProjectionResponse | null;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<DocumentWriterProjectionResolution> {\n if (input.stillCurrent?.() === false) return null;\n if (input.reusableWriterProjection) {\n return input.reusableWriterProjection;\n }\n\n const result = await input.apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (input.stillCurrent?.() === false) return null;\n if (result.ok) {\n return result.data;\n }\n if (isUpstreamDeletedDocumentSyncFailure(result)) {\n return REMOTE_DOCUMENT_DELETED;\n }\n traceProjectionFailed(input.onSyncTrace, {\n code: result.code,\n documentId: input.documentId,\n status: result.status,\n });\n result.report();\n await input.onTerminalFailure?.(result);\n return null;\n}\n\nexport async function retrySyncPlan(input: {\n apiClient: DocumentSyncApi;\n buildWithProjection: (\n projection: DocumentWriterProjectionResponse,\n ) => Promise<MaterializedDocumentSyncPlan>;\n documentId: string;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n stillCurrent?: (() => boolean) | undefined;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<\n | readonly [MaterializedDocumentSyncPlan, DocumentWriterProjectionResponse]\n | null\n> {\n try {\n return [\n await input.buildWithProjection(input.writerProjection),\n input.writerProjection,\n ];\n } catch (error) {\n if (\n !input.apiClient.evictDocumentWriterProjection ||\n !shouldRetrySyncWithFreshWriterProjection(error)\n ) {\n throw error;\n }\n }\n if (input.stillCurrent?.() === false) return null;\n\n // Only this document's projection was stale; evict just it so unrelated\n // documents keep their warm cache instead of a global wipe.\n input.apiClient.evictDocumentWriterProjection?.(input.documentId);\n const writerProjection = await resolveDocumentSyncWriterProjection({\n apiClient: input.apiClient,\n documentId: input.documentId,\n onSyncTrace: input.onSyncTrace,\n onTerminalFailure: input.onTerminalFailure,\n reusableWriterProjection: null,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n if (writerProjection === REMOTE_DOCUMENT_DELETED) {\n await input.onRemoteDocumentDeleted?.({ documentId: input.documentId });\n return null;\n }\n if (!writerProjection) {\n return null;\n }\n\n return [await input.buildWithProjection(writerProjection), writerProjection];\n}\n\n/**\n * Resolves the writer projection for one sync attempt, converting the two\n * unrecoverable outcomes into an abandoned (null) result with a named reason\n * so callers that turn a null sync into their own error can surface the real\n * cause.\n */\nexport async function resolveSyncAttemptWriterProjection(input: {\n apiClient: DocumentSyncApi;\n documentId: string;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncAbandoned?: ((reason: string) => void) | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n reusableWriterProjection: DocumentWriterProjectionResponse | null;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<DocumentWriterProjectionResponse | null> {\n const writerProjection = await resolveDocumentSyncWriterProjection(input);\n if (input.stillCurrent?.() === false) return null;\n if (writerProjection === REMOTE_DOCUMENT_DELETED) {\n await input.onRemoteDocumentDeleted?.({ documentId: input.documentId });\n if (input.stillCurrent?.() !== false) {\n input.onSyncAbandoned?.(\"the remote document was deleted\");\n }\n return null;\n }\n if (!writerProjection) {\n input.onSyncAbandoned?.(\n \"the document writer projection could not be fetched\",\n );\n return null;\n }\n return writerProjection;\n}\n\nexport async function refreshSyncAttemptWriterProjection(\n input: Omit<\n Parameters<typeof resolveSyncAttemptWriterProjection>[0],\n \"reusableWriterProjection\"\n > & { unavailableError?: unknown },\n): Promise<DocumentWriterProjectionResponse | null> {\n const { onRemoteDocumentDeleted, unavailableError, ...resolutionInput } =\n input;\n if (input.stillCurrent?.() === false) return null;\n if (input.apiClient.evictDocumentWriterProjection) {\n input.apiClient.evictDocumentWriterProjection(input.documentId);\n } else {\n input.apiClient.clearWriterProjectionCaches?.();\n }\n let remoteDocumentDeleted = false;\n const writerProjection = await resolveSyncAttemptWriterProjection({\n ...resolutionInput,\n onRemoteDocumentDeleted: async (deleted) => {\n remoteDocumentDeleted = true;\n await onRemoteDocumentDeleted?.(deleted);\n },\n reusableWriterProjection: null,\n });\n if (\n !writerProjection &&\n unavailableError !== undefined &&\n !remoteDocumentDeleted &&\n input.stillCurrent?.() !== false\n ) {\n throw unavailableError;\n }\n return writerProjection;\n}\n\nexport async function retrySyncPlanOrAbandon(input: {\n apiClient: DocumentSyncApi;\n buildWithProjection: (\n projection: DocumentWriterProjectionResponse,\n ) => Promise<MaterializedDocumentSyncPlan>;\n documentId: string;\n onRemoteDocumentDeleted?: RemoteDocumentDeletionHandler | undefined;\n onSyncAbandoned?: ((reason: string) => void) | undefined;\n onSyncTrace?: DocumentSyncTraceEmitter | undefined;\n onTerminalFailure?: TerminalSubmitFailureHandler | undefined;\n stillCurrent?: (() => boolean) | undefined;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<\n | readonly [MaterializedDocumentSyncPlan, DocumentWriterProjectionResponse]\n | null\n> {\n const planned = await retrySyncPlan(input);\n if (!planned && input.stillCurrent?.() !== false) {\n input.onSyncAbandoned?.(\n \"a sync plan could not be built against the current projection\",\n );\n }\n return planned;\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { KeyingVerificationError } from "../../internal/crypto/index.js";
|
|
2
2
|
import { isRetryableDocumentSyncConflict } from "../../data/documents/shared/responses.js";
|
|
3
|
+
import { recoverPrincipalPolicyRepair } from "../principals/policyRepair.js";
|
|
3
4
|
function principalIdentityKey(principalType, principalId) {
|
|
4
5
|
return `${principalType}:${principalId}`;
|
|
5
6
|
}
|
|
@@ -18,29 +19,30 @@ function requestedRepairPrincipalIdentities(plan) {
|
|
|
18
19
|
}
|
|
19
20
|
return identities;
|
|
20
21
|
}
|
|
21
|
-
function
|
|
22
|
+
function assertDocumentSyncPolicyRepairHeadsRequested(input) {
|
|
22
23
|
const requested = requestedRepairPrincipalIdentities(input.plan);
|
|
23
|
-
for (const
|
|
24
|
-
const { principalId, principalType } =
|
|
24
|
+
for (const head of input.heads) {
|
|
25
|
+
const { principalId, principalType } = head;
|
|
25
26
|
if (!requested.has(principalIdentityKey(principalType, principalId))) {
|
|
26
|
-
throw new KeyingVerificationError("object_mismatch", "Document sync policy repair
|
|
27
|
+
throw new KeyingVerificationError("object_mismatch", "Document sync policy repair head principal was not requested");
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
|
-
export async function
|
|
31
|
-
const
|
|
32
|
-
const
|
|
31
|
+
export async function recoverDocumentSyncPolicyRepair(input) {
|
|
32
|
+
const heads = input.failure.stalePrincipalHeads;
|
|
33
|
+
const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;
|
|
33
34
|
if (!isRetryableDocumentSyncConflict(input.failure) ||
|
|
34
35
|
(input.plan.request.containerRekeys?.length ?? 0) === 0 ||
|
|
35
|
-
!
|
|
36
|
-
|
|
37
|
-
!
|
|
36
|
+
!heads ||
|
|
37
|
+
heads.length === 0 ||
|
|
38
|
+
!resolve ||
|
|
38
39
|
input.stillCurrent?.() === false) {
|
|
39
40
|
return;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
await
|
|
43
|
-
|
|
42
|
+
assertDocumentSyncPolicyRepairHeadsRequested({ heads, plan: input.plan });
|
|
43
|
+
await recoverPrincipalPolicyRepair({
|
|
44
|
+
heads,
|
|
45
|
+
warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,
|
|
44
46
|
organizationId: input.plan.organizationId,
|
|
45
47
|
stillCurrent: input.stillCurrent,
|
|
46
48
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncPolicyRepair.js","sourceRoot":"","sources":["syncPolicyRepair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"syncPolicyRepair.js","sourceRoot":"","sources":["syncPolicyRepair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AAOxF,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAI1E,SAAS,oBAAoB,CAC3B,aAAmC,EACnC,WAAmB;IAEnB,OAAO,GAAG,aAAa,IAAI,WAAW,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,kCAAkC,CACzC,IAAsB;IAEtB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;QACvD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC7C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;YAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACvD,IACE,CAAC,aAAa,KAAK,OAAO,IAAI,aAAa,KAAK,cAAc,CAAC;gBAC/D,OAAO,WAAW,KAAK,QAAQ;gBAC/B,WAAW,CAAC,MAAM,GAAG,CAAC,EACtB,CAAC;gBACD,UAAU,CAAC,GAAG,CAAC,oBAAoB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,4CAA4C,CAAC,KAGrD;IACC,MAAM,SAAS,GAAG,kCAAkC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;QAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,oBAAoB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YACrE,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,8DAA8D,CAC/D,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CAAC,KAKrD;IACC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,+BAA+B,EAAE,gBAAgB,CAAC;IACxE,IACE,CAAC,+BAA+B,CAAC,KAAK,CAAC,OAAO,CAAC;QAC/C,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC;QACvD,CAAC,KAAK;QACN,KAAK,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,OAAO;QACR,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAChC,CAAC;QACD,OAAO;IACT,CAAC;IAED,4CAA4C,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1E,MAAM,4BAA4B,CAAC;QACjC,KAAK;QACL,+BAA+B,EAAE,KAAK,CAAC,+BAA+B;QACtE,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc;QACzC,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport type { ReferencedPrincipalStateResponse } from \"@tearleads/validators/response\";\nimport { isRetryableDocumentSyncConflict } from \"../../data/documents/shared/responses\";\nimport type {\n DocumentSyncPlan,\n DocumentSyncSubmitFailure,\n} from \"../../data/documents/shared/types\";\nimport type { ReferencedPrincipalPolicyWarmer } from \"../../data/keyingProjectionVerification\";\n\nimport { recoverPrincipalPolicyRepair } from \"../principals/policyRepair\";\n\ntype ManagedPrincipalType = \"group\" | \"organization\";\n\nfunction principalIdentityKey(\n principalType: ManagedPrincipalType,\n principalId: string,\n): string {\n return `${principalType}:${principalId}`;\n}\n\nfunction requestedRepairPrincipalIdentities(\n plan: DocumentSyncPlan,\n): Set<string> {\n const identities = new Set<string>();\n for (const rekey of plan.request.containerRekeys ?? []) {\n for (const policy of rekey.principalPolicies) {\n const principalType = Reflect.get(policy, \"principalType\");\n const principalId = Reflect.get(policy, \"principalId\");\n if (\n (principalType === \"group\" || principalType === \"organization\") &&\n typeof principalId === \"string\" &&\n principalId.length > 0\n ) {\n identities.add(principalIdentityKey(principalType, principalId));\n }\n }\n }\n return identities;\n}\n\nfunction assertDocumentSyncPolicyRepairHeadsRequested(input: {\n readonly heads: readonly ReferencedPrincipalStateResponse[];\n readonly plan: DocumentSyncPlan;\n}): void {\n const requested = requestedRepairPrincipalIdentities(input.plan);\n for (const head of input.heads) {\n const { principalId, principalType } = head;\n if (!requested.has(principalIdentityKey(principalType, principalId))) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document sync policy repair head principal was not requested\",\n );\n }\n }\n}\n\nexport async function recoverDocumentSyncPolicyRepair(input: {\n failure: DocumentSyncSubmitFailure;\n plan: DocumentSyncPlan;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<void> {\n const heads = input.failure.stalePrincipalHeads;\n const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;\n if (\n !isRetryableDocumentSyncConflict(input.failure) ||\n (input.plan.request.containerRekeys?.length ?? 0) === 0 ||\n !heads ||\n heads.length === 0 ||\n !resolve ||\n input.stillCurrent?.() === false\n ) {\n return;\n }\n\n assertDocumentSyncPolicyRepairHeadsRequested({ heads, plan: input.plan });\n await recoverPrincipalPolicyRepair({\n heads,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n organizationId: input.plan.organizationId,\n stillCurrent: input.stillCurrent,\n });\n}\n"]}
|
|
@@ -71,8 +71,10 @@ export async function prepareInitialGroupCurrentPublication(input, request, resp
|
|
|
71
71
|
...sealed,
|
|
72
72
|
policy: policy.value,
|
|
73
73
|
predecessorStage: null,
|
|
74
|
+
predecessorIndexRootHash: null,
|
|
74
75
|
previousPrefixProgress: null,
|
|
75
76
|
evidence: await preparePrincipalHistoryEvidencePage({
|
|
77
|
+
indexRootHash: appended.value.indexRootHash,
|
|
76
78
|
scopeId,
|
|
77
79
|
organizationId: input.organizationId,
|
|
78
80
|
entries: [entry],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialPrincipalCurrentPublication.js","sourceRoot":"","sources":["initialPrincipalCurrentPublication.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n verifyPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyMutationResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { AcknowledgedPrincipalCurrentPublication } from \"../../data/persistence/principalCurrentAcknowledgementPersistence\";\nimport { preparePrincipalHistoryEvidencePage } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { principalHistoryEvidenceScopeId } from \"../../data/principals/principalHistoryPrefixProtection\";\nimport { collectPrincipalPolicySignerPublicKeys } from \"../principals/policyVerification\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"../principals/principalHistoryRecoveryTypes\";\nimport {\n assertPrincipalHistoryVerificationMode,\n principalHistoryVerificationContext,\n} from \"../principals/principalHistoryRecoveryVerification\";\nimport { groupPolicyMutationHead } from \"./groupPolicyMutationHead\";\nimport { sealPrincipalCurrentPublication } from \"./principalCurrentPublicationSeal\";\nimport { assertPrincipalPolicyReceiptArtifacts } from \"./principalPolicyReceiptArtifacts\";\n\n/** Verify a newly authored group from genesis before its atomic directory publication. */\nexport async function prepareInitialGroupCurrentPublication(\n input: RecoverPrincipalPolicyHistoryOptions,\n request: PutPrincipalPolicyRequest,\n response: PrincipalPolicyMutationResponse,\n): Promise<AcknowledgedPrincipalCurrentPublication> {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const expectedHead = await groupPolicyMutationHead(request);\n if (\n request.state.principalType !== \"group\" ||\n request.state.version !== 1 ||\n request.state.prevStateHash !== null ||\n !principalHeadMatchesReference(expectedHead, input.expectedHead)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Initial group publication must begin at its exact genesis\",\n );\n assertPrincipalPolicyReceiptArtifacts({ expectedHead, request, response });\n const keys = await collectPrincipalPolicySignerPublicKeys({\n bundle: { currentState: response.currentState, previousStates: [] },\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (\"error\" in keys)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Initial group signer could not be authenticated\",\n );\n const externalAuthority = await input.loadExternalAuthority?.(\n request.state.externalAuthority ? [request.state.externalAuthority] : [],\n );\n assertProjectionVerificationCurrent(current);\n const verifier = createPrincipalPolicyHistoryVerifier({\n principalType: \"group\",\n principalId: expectedHead.principalId,\n });\n const entry = {\n state: response.currentState,\n projection: response.currentProjection,\n grants: response.currentGrants,\n };\n assertPrincipalHistoryVerificationMode(input, [entry]);\n const appended = await verifier.append({\n entries: [entry],\n signerPublicKeys: keys.signerPublicKeys,\n ...(externalAuthority ? { externalAuthority } : {}),\n });\n if (!appended.ok) throw appended.error;\n const history = verifier.finish(expectedHead);\n if (!history.ok) throw history.error;\n const policy = await verifyPrincipalPolicyCurrent({\n current: response,\n history: history.value,\n });\n if (!policy.ok) throw policy.error;\n const options = {\n ...input,\n protection: {\n ...input.protection,\n context: principalHistoryVerificationContext(input),\n },\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: input.organizationId,\n head: expectedHead,\n protection: options.protection,\n });\n const sealed = await sealPrincipalCurrentPublication(\n options,\n scopeId,\n expectedHead,\n verifier,\n response,\n );\n assertProjectionVerificationCurrent(current);\n return {\n ...sealed,\n policy: policy.value,\n predecessorStage: null,\n previousPrefixProgress: null,\n evidence: await preparePrincipalHistoryEvidencePage({\n scopeId,\n organizationId: input.organizationId,\n entries: [entry],\n nodes: appended.value.indexNodes,\n }),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"initialPrincipalCurrentPublication.js","sourceRoot":"","sources":["initialPrincipalCurrentPublication.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n verifyPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyMutationResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { AcknowledgedPrincipalCurrentPublication } from \"../../data/persistence/principalCurrentAcknowledgementPersistence\";\nimport { preparePrincipalHistoryEvidencePage } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { principalHistoryEvidenceScopeId } from \"../../data/principals/principalHistoryPrefixProtection\";\nimport { collectPrincipalPolicySignerPublicKeys } from \"../principals/policyVerification\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"../principals/principalHistoryRecoveryTypes\";\nimport {\n assertPrincipalHistoryVerificationMode,\n principalHistoryVerificationContext,\n} from \"../principals/principalHistoryRecoveryVerification\";\nimport { groupPolicyMutationHead } from \"./groupPolicyMutationHead\";\nimport { sealPrincipalCurrentPublication } from \"./principalCurrentPublicationSeal\";\nimport { assertPrincipalPolicyReceiptArtifacts } from \"./principalPolicyReceiptArtifacts\";\n\n/** Verify a newly authored group from genesis before its atomic directory publication. */\nexport async function prepareInitialGroupCurrentPublication(\n input: RecoverPrincipalPolicyHistoryOptions,\n request: PutPrincipalPolicyRequest,\n response: PrincipalPolicyMutationResponse,\n): Promise<AcknowledgedPrincipalCurrentPublication> {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const expectedHead = await groupPolicyMutationHead(request);\n if (\n request.state.principalType !== \"group\" ||\n request.state.version !== 1 ||\n request.state.prevStateHash !== null ||\n !principalHeadMatchesReference(expectedHead, input.expectedHead)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Initial group publication must begin at its exact genesis\",\n );\n assertPrincipalPolicyReceiptArtifacts({ expectedHead, request, response });\n const keys = await collectPrincipalPolicySignerPublicKeys({\n bundle: { currentState: response.currentState, previousStates: [] },\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (\"error\" in keys)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Initial group signer could not be authenticated\",\n );\n const externalAuthority = await input.loadExternalAuthority?.(\n request.state.externalAuthority ? [request.state.externalAuthority] : [],\n );\n assertProjectionVerificationCurrent(current);\n const verifier = createPrincipalPolicyHistoryVerifier({\n principalType: \"group\",\n principalId: expectedHead.principalId,\n });\n const entry = {\n state: response.currentState,\n projection: response.currentProjection,\n grants: response.currentGrants,\n };\n assertPrincipalHistoryVerificationMode(input, [entry]);\n const appended = await verifier.append({\n entries: [entry],\n signerPublicKeys: keys.signerPublicKeys,\n ...(externalAuthority ? { externalAuthority } : {}),\n });\n if (!appended.ok) throw appended.error;\n const history = verifier.finish(expectedHead);\n if (!history.ok) throw history.error;\n const policy = await verifyPrincipalPolicyCurrent({\n current: response,\n history: history.value,\n });\n if (!policy.ok) throw policy.error;\n const options = {\n ...input,\n protection: {\n ...input.protection,\n context: principalHistoryVerificationContext(input),\n },\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: input.organizationId,\n head: expectedHead,\n protection: options.protection,\n });\n const sealed = await sealPrincipalCurrentPublication(\n options,\n scopeId,\n expectedHead,\n verifier,\n response,\n );\n assertProjectionVerificationCurrent(current);\n return {\n ...sealed,\n policy: policy.value,\n predecessorStage: null,\n predecessorIndexRootHash: null,\n previousPrefixProgress: null,\n evidence: await preparePrincipalHistoryEvidencePage({\n indexRootHash: appended.value.indexRootHash,\n scopeId,\n organizationId: input.organizationId,\n entries: [entry],\n nodes: appended.value.indexNodes,\n }),\n };\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
import { ProjectionDependencyUnavailableError } from "../../data/keyingProjectionVerification/dependencyUnavailable.js";
|
|
1
2
|
import { reportKeyingVerificationErrorInCauseChain } from "../../data/keyingProjectionVerification/error.js";
|
|
2
|
-
import {
|
|
3
|
-
import { loadPrincipalPolicyBundle } from "../../data/persistence/principalPolicyPersistence.js";
|
|
4
|
-
import { loadLocalOrganizationPolicyHistory } from "./localReadModelDetails.js";
|
|
3
|
+
import { loadLocalOrganizationPolicyReference } from "./localReadModelDetails.js";
|
|
5
4
|
import { buildDetailedOrganizationPolicyHistory } from "./organizationPolicyHistoryDetails.js";
|
|
6
5
|
import { captureOrganizationPresentationAccessAttempt, isOrganizationPresentationAccessAttemptCurrent, isOrganizationPresentationAccessReadable, } from "./organizationPresentationAccessState.js";
|
|
7
6
|
import { isOrganizationPresentationAccessDeniedFailure } from "./organizationPresentationFailures.js";
|
|
@@ -13,31 +12,32 @@ export async function loadPolicyHistoryDetails(input) {
|
|
|
13
12
|
const current = () => input.stillCurrent() &&
|
|
14
13
|
isOrganizationPresentationAccessAttemptCurrent(access, attempt) &&
|
|
15
14
|
isOrganizationPresentationAccessReadable(access, "readModel");
|
|
16
|
-
const bundle = await loadPrincipalPolicyBundle(input.execSql, "organization", input.organizationId);
|
|
17
15
|
if (!current())
|
|
18
16
|
return null;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
const beforeVersion = (input.page.entries.at(-1)?.state.version ?? 0) + 1;
|
|
18
|
+
const cache = {
|
|
19
|
+
domainScope: input.domainScope,
|
|
20
|
+
access,
|
|
21
|
+
stateHash: input.head.stateHash,
|
|
22
|
+
beforeVersion,
|
|
23
|
+
};
|
|
24
24
|
const retain = async (history) => {
|
|
25
|
-
const latest = await
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
const latest = await loadLocalOrganizationPolicyReference({
|
|
26
|
+
...input,
|
|
27
|
+
principalType: "organization",
|
|
28
|
+
principalId: input.organizationId,
|
|
29
|
+
});
|
|
30
|
+
return current() && latest?.stateHash === input.head.stateHash
|
|
29
31
|
? history
|
|
30
|
-
:
|
|
32
|
+
: null;
|
|
31
33
|
};
|
|
32
|
-
const cached = loadCachedPolicyHistory(
|
|
33
|
-
domainScope: input.domainScope,
|
|
34
|
-
access,
|
|
35
|
-
stateHash: bundle.currentState.stateHash,
|
|
36
|
-
});
|
|
34
|
+
const cached = loadCachedPolicyHistory(cache);
|
|
37
35
|
if (cached)
|
|
38
36
|
return retain(cached);
|
|
37
|
+
if (!input.online)
|
|
38
|
+
return retain(input.history);
|
|
39
39
|
try {
|
|
40
|
-
const response = await input.apiClient.getOrganizationPolicyHistoryResult(input.organizationId,
|
|
40
|
+
const response = await input.apiClient.getOrganizationPolicyHistoryResult(input.organizationId, input.head.stateHash, { beforeVersion, reportErrors: false });
|
|
41
41
|
if (!input.stillCurrent())
|
|
42
42
|
return null;
|
|
43
43
|
if (!response.ok) {
|
|
@@ -46,34 +46,33 @@ export async function loadPolicyHistoryDetails(input) {
|
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
48
|
response.report();
|
|
49
|
+
if (input.olderPage)
|
|
50
|
+
throw new Error(response.message);
|
|
49
51
|
return retain(input.history);
|
|
50
52
|
}
|
|
51
53
|
const history = await buildDetailedOrganizationPolicyHistory({
|
|
52
|
-
|
|
54
|
+
head: input.head,
|
|
55
|
+
page: input.page,
|
|
53
56
|
evidence: response.data,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,
|
|
57
|
+
resolveHistory: input.resolveHistory,
|
|
58
|
+
stillCurrent: current,
|
|
57
59
|
});
|
|
58
60
|
const retained = await retain(history);
|
|
59
61
|
if (retained === history)
|
|
60
|
-
cachePolicyHistory({
|
|
61
|
-
domainScope: input.domainScope,
|
|
62
|
-
access,
|
|
63
|
-
attempt,
|
|
64
|
-
history,
|
|
65
|
-
});
|
|
62
|
+
cachePolicyHistory({ ...cache, attempt, history });
|
|
66
63
|
return retained;
|
|
67
64
|
}
|
|
68
65
|
catch (error) {
|
|
66
|
+
if (!input.olderPage &&
|
|
67
|
+
error instanceof ProjectionDependencyUnavailableError)
|
|
68
|
+
return retain(input.history);
|
|
69
69
|
await reportKeyingVerificationErrorInCauseChain(error, input.reportSecurityIncident, {
|
|
70
70
|
objectId: input.organizationId,
|
|
71
71
|
objectKind: "principal",
|
|
72
72
|
operation: "organization.policy_history.load",
|
|
73
73
|
organizationId: input.organizationId,
|
|
74
74
|
});
|
|
75
|
-
|
|
76
|
-
return retain(input.history);
|
|
75
|
+
throw error;
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
78
|
//# sourceMappingURL=loadPolicyHistoryDetails.js.map
|