@tearleads/client-sdk 0.1.78 → 0.1.80
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/deviceFirst/index.d.ts +1 -1
- package/client/deviceFirst/index.js +1 -1
- package/client/deviceFirst/index.js.map +1 -1
- package/client/runtime/principalMutationApi.js +1 -1
- package/client/runtime/principalMutationApi.js.map +1 -1
- package/client/runtime/principalMutationDispatch.js +1 -1
- package/client/runtime/principalMutationDispatch.js.map +1 -1
- package/client/runtime/rootContainerAdoption.js.map +1 -1
- package/client/runtime/workflowRuntime.d.ts +1 -1
- package/client/runtime/workflowRuntime.js.map +1 -1
- package/client/session/sessionPurgeRecovery.js +1 -1
- package/client/session/sessionPurgeRecovery.js.map +1 -1
- package/data/blobs/attachments/projection.js +2 -3
- package/data/blobs/attachments/projection.js.map +1 -1
- package/data/documents/documentConstants.d.ts +1 -0
- package/data/documents/documentConstants.js +1 -0
- package/data/documents/documentConstants.js.map +1 -1
- package/data/documents/shared/containerKek/containerKekEntryVerification.d.ts +3 -0
- package/data/documents/shared/containerKek/index.d.ts +5 -0
- package/data/documents/shared/containerKek/index.js +9 -0
- package/data/documents/shared/containerKek/index.js.map +1 -0
- package/data/documents/shared/projection/index.d.ts +1 -1
- package/data/documents/shared/projection/index.js +1 -1
- package/data/documents/shared/projection/index.js.map +1 -1
- package/data/{sync → documents/shared/sync}/documentSyncOutgoingBatch.d.ts +1 -1
- package/data/{sync → documents/shared/sync}/documentSyncOutgoingBatch.js +1 -1
- package/data/documents/shared/sync/syncResponseAuthorization.js +1 -1
- package/data/documents/shared/sync/syncResponseAuthorization.js.map +1 -1
- package/data/keyingProjectionVerification/container/containerCreateManifest.d.ts +12 -0
- package/data/keyingProjectionVerification/container/containerDestinationVerification.d.ts +16 -0
- package/data/keyingProjectionVerification/index.d.ts +4 -0
- package/data/keyingProjectionVerification/index.js +5 -1
- package/data/keyingProjectionVerification/index.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicy/mergeProjectionPolicyEvidence.d.ts +3 -0
- package/data/keyingProjectionVerification/principalPolicy/principalPolicyVerification.d.ts +24 -0
- package/data/persistence/container-contents/documentPlacement.js +1 -1
- package/data/persistence/container-contents/documentPlacement.js.map +1 -1
- package/data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js +1 -1
- package/data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js.map +1 -1
- package/data/persistence/documents/documentsPersistence.d.ts +1 -1
- package/data/persistence/documents/documentsPersistence.js +2 -3
- package/data/persistence/documents/documentsPersistence.js.map +1 -1
- package/data/persistence/documents/internal/containerDocumentTombstones.js +1 -1
- package/data/persistence/documents/internal/containerDocumentTombstones.js.map +1 -1
- package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js +1 -1
- package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js.map +1 -1
- package/data/persistence/documents/internal/documentDeletionPersistence.js +1 -1
- package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentMutationPersistence.js +1 -1
- package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentProjectionRows.js +1 -2
- package/data/persistence/documents/internal/documentProjectionRows.js.map +1 -1
- package/data/persistence/documents/internal/documentPullContinuationPersistence.js +1 -1
- package/data/persistence/documents/internal/documentPullContinuationPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentRows.js +1 -2
- package/data/persistence/documents/internal/documentRows.js.map +1 -1
- package/data/persistence/documents/internal/orphanSideRows.js +1 -1
- package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
- package/data/persistence/documents/internal/pendingCreateAdoption.js +1 -1
- package/data/persistence/documents/internal/pendingCreateAdoption.js.map +1 -1
- package/data/persistence/documents/internal/rowQueryPersistence.js +1 -1
- package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
- package/package.json +1 -1
- package/stores/local-projection/localProjectionStore.d.ts +1 -1
- package/stores/local-projection/localProjectionStore.js +1 -1
- package/stores/local-projection/localProjectionStore.js.map +1 -1
- package/stores/local-projection/registry.d.ts +1 -1
- package/stores/local-projection/registry.js.map +1 -1
- package/stores/local-projection/types.d.ts +1 -1
- package/stores/local-projection/types.js.map +1 -1
- package/workflows/blobs/hydration/decrypt.js +1 -2
- package/workflows/blobs/hydration/decrypt.js.map +1 -1
- package/workflows/blobs/hydration/hydrate.d.ts +1 -1
- package/workflows/blobs/hydration/hydrate.js.map +1 -1
- package/workflows/container-contents/container-state/create/createAdoption.js +1 -2
- package/workflows/container-contents/container-state/create/createAdoption.js.map +1 -1
- package/workflows/container-contents/container-state/purge/purgeTreeScope.js +1 -1
- package/workflows/container-contents/container-state/purge/purgeTreeScope.js.map +1 -1
- package/workflows/container-contents/info/documentInfo.js +1 -1
- package/workflows/container-contents/info/documentInfo.js.map +1 -1
- package/workflows/container-contents/metadata/index.js +1 -2
- package/workflows/container-contents/metadata/index.js.map +1 -1
- package/workflows/container-contents/metadata/metadataMutationPreparation.js +1 -1
- package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -1
- package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js +1 -1
- package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js.map +1 -1
- package/workflows/container-contents/metadata/metadataSyncErrors.js +1 -1
- package/workflows/container-contents/metadata/metadataSyncErrors.js.map +1 -1
- package/workflows/container-contents/metadata/metadataSyncSettlement.d.ts +1 -1
- package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -1
- package/workflows/container-contents/metadata/metadataTypes.d.ts +1 -1
- package/workflows/container-contents/metadata/metadataTypes.js.map +1 -1
- package/workflows/container-contents/pendingWrites/index.js +1 -1
- package/workflows/container-contents/pendingWrites/index.js.map +1 -1
- package/workflows/container-contents/remoteHydration/destination/verifiedDestination.js +1 -3
- package/workflows/container-contents/remoteHydration/destination/verifiedDestination.js.map +1 -1
- package/workflows/containers/child/create/index.js +1 -1
- package/workflows/containers/child/create/index.js.map +1 -1
- package/workflows/containers/child/move/moveRotation.js +1 -1
- package/workflows/containers/child/move/moveRotation.js.map +1 -1
- package/workflows/containers/child/move/moveWraps.js +1 -1
- package/workflows/containers/child/move/moveWraps.js.map +1 -1
- package/workflows/containers/child/rekey/rekeyProjection.js +1 -1
- package/workflows/containers/child/rekey/rekeyProjection.js.map +1 -1
- package/workflows/containers/child/rotation/rotationContext.js +1 -2
- package/workflows/containers/child/rotation/rotationContext.js.map +1 -1
- package/workflows/containers/child/share/shareAncestorRepair.js +1 -2
- package/workflows/containers/child/share/shareAncestorRepair.js.map +1 -1
- package/workflows/containers/index.d.ts +2 -3
- package/workflows/containers/index.js +1 -2
- package/workflows/containers/index.js.map +1 -1
- package/workflows/containers/writeRefusal.js +1 -1
- package/workflows/containers/writeRefusal.js.map +1 -1
- package/workflows/documents/index.d.ts +1 -1
- package/workflows/documents/index.js +1 -1
- package/workflows/documents/index.js.map +1 -1
- package/workflows/documents/linkSet/linkSetProjectionSeed.js +1 -1
- package/workflows/documents/linkSet/linkSetProjectionSeed.js.map +1 -1
- package/workflows/documents/sync/readOnlySync.js +1 -1
- package/workflows/documents/sync/readOnlySync.js.map +1 -1
- package/workflows/documents/sync/syncAttemptPlanning.js +1 -1
- package/workflows/documents/sync/syncAttemptPlanning.js.map +1 -1
- package/workflows/documents/syncPlan/syncPlanMaterial.js +1 -1
- package/workflows/documents/syncPlan/syncPlanMaterial.js.map +1 -1
- package/workflows/documents/syncPlan/syncPlanRequestBounds.js +1 -1
- package/workflows/documents/syncPlan/syncPlanRequestBounds.js.map +1 -1
- package/workflows/documents/syncRekeys/syncAutomaticContainerRekeys.js +1 -1
- package/workflows/documents/syncRekeys/syncAutomaticContainerRekeys.js.map +1 -1
- package/workflows/organizations/groupMetadata/groupMetadataAccess.js +1 -1
- package/workflows/organizations/groupMetadata/groupMetadataAccess.js.map +1 -1
- package/workflows/organizations/provisioning/createOrganization.d.ts +1 -1
- package/workflows/organizations/provisioning/createOrganization.js +1 -1
- package/workflows/organizations/provisioning/createOrganization.js.map +1 -1
- package/workflows/organizations/provisioning/organizationProvisioningAttempt.d.ts +1 -1
- package/workflows/organizations/provisioning/organizationProvisioningAttempt.js.map +1 -1
- package/workflows/organizations/readModel/listLocalOrganizations.js +1 -1
- package/workflows/organizations/readModel/listLocalOrganizations.js.map +1 -1
- package/workflows/registration/index.d.ts +2 -1
- package/workflows/registration/index.js +2 -1
- package/workflows/registration/index.js.map +1 -1
- package/workflows/registration/organizationProvisioning.d.ts +39 -0
- package/workflows/registration/organizationProvisioning.js +211 -0
- package/workflows/registration/organizationProvisioning.js.map +1 -0
- package/workflows/registration/organizationProvisioningArtifacts.d.ts +2 -3
- package/workflows/registration/organizationProvisioningArtifacts.js.map +1 -1
- package/workflows/registration/provisioningBootstrapBuilders.d.ts +3 -3
- package/workflows/registration/provisioningBootstrapBuilders.js +3 -4
- package/workflows/registration/provisioningBootstrapBuilders.js.map +1 -1
- package/workflows/registration/registerIdentity.d.ts +2 -39
- package/workflows/registration/registerIdentity.js +2 -207
- package/workflows/registration/registerIdentity.js.map +1 -1
- package/workflows/sync/remoteResetPlans.js +2 -2
- package/workflows/sync/remoteResetPlans.js.map +1 -1
- package/data/persistence/documents/internal/constants.d.ts +0 -1
- package/data/persistence/documents/internal/constants.js +0 -2
- package/data/persistence/documents/internal/constants.js.map +0 -1
- /package/data/{sync → documents/shared/sync}/documentSyncOutgoingBatch.js.map +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataMutationPreparation.js","sourceRoot":"","sources":["metadataMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n exportUpdatesSince,\n importUpdates,\n} from \"@tearleads/loro\";\nimport { documentSyncPullContinuationsEqual } from \"../../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../../data/keying/accessLevel\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"./containerMetadataDocument\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n sameNullableMetadataValue,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\nexport interface PersistContainerMetadataStateInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n clearSyncFailure?: boolean | undefined;\n execSql: ExecSql;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n localMetadataPatch?:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n localUpdate?: Uint8Array | undefined;\n metadataState: ContainerMetadataState;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n patch?: Partial<ContainerMetadataPatch> | undefined;\n persistence: ContainerContentsPersistence;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?:\n | Parameters<ContainerContentsPersistence[\"saveContainer\"]>[3]\n | undefined;\n stillCurrent?: (() => boolean) | undefined;\n}\n\nexport function currentMetadataPullContinuation(\n metadataState: ContainerMetadataState,\n) {\n return Object.hasOwn(metadataState, \"pullContinuation\")\n ? (metadataState.pullContinuation ?? null)\n : (metadataState.record.pullContinuation ?? null);\n}\n\nexport function resolveMetadataSecurityContext(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const currentDocumentId = metadataState.record.documentId ?? null;\n const documentId =\n patch.documentId !== undefined ? patch.documentId : currentDocumentId;\n const accessEpoch = patch.accessEpoch ?? metadataState.record.accessEpoch;\n const documentIdChanged = documentId !== currentDocumentId;\n\n return {\n accessEpoch,\n changed:\n documentIdChanged || accessEpoch !== metadataState.record.accessEpoch,\n documentId,\n documentIdChanged,\n };\n}\n\nfunction mergeDurableMetadataCheckpoint(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): void {\n const { durableRecord, metadataState, securityContext } = input;\n if (\n !durableRecord?.metadataUpdates ||\n durableRecord.documentId !== metadataState.record.documentId ||\n durableRecord.documentId !== securityContext.documentId ||\n durableRecord.accessEpoch !== metadataState.record.accessEpoch ||\n durableRecord.accessEpoch !== securityContext.accessEpoch\n ) {\n return;\n }\n\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n}\n\nexport async function loadAuthoritativeContainerMetadataState(input: {\n containerId: string;\n execSql: ExecSql;\n persistence: ContainerContentsPersistence;\n}) {\n const stored = await input.persistence.loadContainerMetadataState(\n input.execSql,\n input.containerId,\n );\n return stored?.record\n ? { container: stored.container, record: stored.record }\n : null;\n}\n\nfunction localMetadataWriteAccessWasRevoked(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n mutationInput: PersistContainerMetadataStateInput;\n}): boolean {\n return (\n input.mutationInput.expectedSyncState === undefined &&\n input.mutationInput.localUpdate !== undefined &&\n canWriteEffectiveAccessLevel(\n input.mutationInput.metadataState.container.effectiveAccessLevel,\n ) &&\n !canWriteEffectiveAccessLevel(\n input.authoritativeState.container.effectiveAccessLevel,\n )\n );\n}\n\nasync function prepareRebasedLocalMetadataMutation(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n metadataState: ContainerMetadataState;\n localMetadataPatch:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n patch: Partial<ContainerMetadataPatch>;\n}) {\n const { authoritativeState, metadataState, patch } = input;\n const replacementVersion = encodeVersionVector(metadataState.doc);\n const replacementMetadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(authoritativeState.container.parentId),\n );\n writeContainerMetadataValue(metadataState.doc, {\n ...replacementMetadata,\n ...input.localMetadataPatch,\n });\n const rebasedMetadataState = {\n ...metadataState,\n container: authoritativeState.container,\n pullContinuation: authoritativeState.record.pullContinuation ?? null,\n record: authoritativeState.record,\n };\n return {\n durableRecord: authoritativeState.record,\n mutationContainer: authoritativeState.container,\n mutationMetadataState: rebasedMetadataState,\n mutationPatch: patch,\n pendingLocalUpdate: exportUpdatesSince(\n metadataState.doc,\n replacementVersion,\n ),\n pullContinuationSuperseded: false,\n securityContext: resolveMetadataSecurityContext(\n rebasedMetadataState,\n patch,\n ),\n securityContextMatches: true,\n };\n}\n\nfunction resolveMetadataSettlementMatch(\n expectedSyncState: ExpectedContainerMetadataSyncState | undefined,\n durableRecord: DocumentRecord | null,\n) {\n if (!expectedSyncState) {\n return {\n contentStateSuperseded: false,\n pullContinuationSuperseded: false,\n securityContextMatches: true,\n };\n }\n const securityContextMatches = metadataSyncSecurityContextMatches(\n durableRecord,\n expectedSyncState.record,\n );\n const progressStateMatches =\n securityContextMatches &&\n sameNullableMetadataValue(\n durableRecord?.lastCommitLsn,\n expectedSyncState.record.lastCommitLsn,\n ) &&\n Boolean(durableRecord?.pullContinuationRecoveryRequired) ===\n Boolean(expectedSyncState.record.pullContinuationRecoveryRequired) &&\n documentSyncPullContinuationsEqual(\n durableRecord?.pullContinuation,\n expectedSyncState.pullContinuation,\n );\n const contentStateMatches =\n progressStateMatches &&\n sameNullableMetadataValue(\n durableRecord?.metadataUpdates,\n expectedSyncState.record.metadataUpdates,\n ) &&\n sameNullableMetadataValue(\n durableRecord?.snapshotEndVersion,\n expectedSyncState.record.snapshotEndVersion,\n );\n return {\n contentStateSuperseded: progressStateMatches && !contentStateMatches,\n pullContinuationSuperseded: !progressStateMatches,\n securityContextMatches,\n };\n}\n\nexport async function prepareContainerMetadataMutation(\n input: PersistContainerMetadataStateInput,\n execSql: ExecSql,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const { metadataState, persistence } = input;\n const authoritativeState = await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql,\n persistence,\n });\n if (!authoritativeState) {\n return {\n authoritativeState: null,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n if (\n localMetadataWriteAccessWasRevoked({\n authoritativeState,\n mutationInput: input,\n })\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n const durableRecord = authoritativeState.record;\n const mutationMetadataState = durableRecord\n ? {\n ...metadataState,\n pullContinuation: durableRecord.pullContinuation ?? null,\n record: durableRecord,\n }\n : metadataState;\n const capturedSecurityContextMatches =\n durableRecord !== null &&\n metadataSyncSecurityContextMatches(durableRecord, metadataState.record);\n const {\n contentStateSuperseded,\n pullContinuationSuperseded,\n securityContextMatches,\n } = resolveMetadataSettlementMatch(input.expectedSyncState, durableRecord);\n\n if (\n input.expectedSyncState === undefined &&\n !capturedSecurityContextMatches\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n if (input.localUpdate === undefined) {\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n return prepareRebasedLocalMetadataMutation({\n authoritativeState,\n localMetadataPatch: input.localMetadataPatch,\n metadataState,\n patch,\n });\n }\n const mutationPatch = pullContinuationSuperseded ? {} : patch;\n const securityContext = resolveMetadataSecurityContext(\n mutationMetadataState,\n mutationPatch,\n );\n if (\n securityContextMatches &&\n (input.expectedSyncState === undefined || contentStateSuperseded)\n ) {\n mergeDurableMetadataCheckpoint({\n durableRecord,\n metadataState,\n securityContext,\n });\n }\n return {\n durableRecord,\n mutationContainer: authoritativeState.container,\n mutationMetadataState,\n mutationPatch,\n pendingLocalUpdate: input.localUpdate,\n pullContinuationSuperseded,\n securityContext,\n securityContextMatches,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"metadataMutationPreparation.js","sourceRoot":"","sources":["metadataMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n exportUpdatesSince,\n importUpdates,\n} from \"@tearleads/loro\";\nimport { canWriteEffectiveAccessLevel } from \"../../../data/keying/accessLevel\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { documentSyncPullContinuationsEqual } from \"../../documents\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"./containerMetadataDocument\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n sameNullableMetadataValue,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\nexport interface PersistContainerMetadataStateInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n clearSyncFailure?: boolean | undefined;\n execSql: ExecSql;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n localMetadataPatch?:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n localUpdate?: Uint8Array | undefined;\n metadataState: ContainerMetadataState;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n patch?: Partial<ContainerMetadataPatch> | undefined;\n persistence: ContainerContentsPersistence;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?:\n | Parameters<ContainerContentsPersistence[\"saveContainer\"]>[3]\n | undefined;\n stillCurrent?: (() => boolean) | undefined;\n}\n\nexport function currentMetadataPullContinuation(\n metadataState: ContainerMetadataState,\n) {\n return Object.hasOwn(metadataState, \"pullContinuation\")\n ? (metadataState.pullContinuation ?? null)\n : (metadataState.record.pullContinuation ?? null);\n}\n\nexport function resolveMetadataSecurityContext(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const currentDocumentId = metadataState.record.documentId ?? null;\n const documentId =\n patch.documentId !== undefined ? patch.documentId : currentDocumentId;\n const accessEpoch = patch.accessEpoch ?? metadataState.record.accessEpoch;\n const documentIdChanged = documentId !== currentDocumentId;\n\n return {\n accessEpoch,\n changed:\n documentIdChanged || accessEpoch !== metadataState.record.accessEpoch,\n documentId,\n documentIdChanged,\n };\n}\n\nfunction mergeDurableMetadataCheckpoint(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): void {\n const { durableRecord, metadataState, securityContext } = input;\n if (\n !durableRecord?.metadataUpdates ||\n durableRecord.documentId !== metadataState.record.documentId ||\n durableRecord.documentId !== securityContext.documentId ||\n durableRecord.accessEpoch !== metadataState.record.accessEpoch ||\n durableRecord.accessEpoch !== securityContext.accessEpoch\n ) {\n return;\n }\n\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n}\n\nexport async function loadAuthoritativeContainerMetadataState(input: {\n containerId: string;\n execSql: ExecSql;\n persistence: ContainerContentsPersistence;\n}) {\n const stored = await input.persistence.loadContainerMetadataState(\n input.execSql,\n input.containerId,\n );\n return stored?.record\n ? { container: stored.container, record: stored.record }\n : null;\n}\n\nfunction localMetadataWriteAccessWasRevoked(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n mutationInput: PersistContainerMetadataStateInput;\n}): boolean {\n return (\n input.mutationInput.expectedSyncState === undefined &&\n input.mutationInput.localUpdate !== undefined &&\n canWriteEffectiveAccessLevel(\n input.mutationInput.metadataState.container.effectiveAccessLevel,\n ) &&\n !canWriteEffectiveAccessLevel(\n input.authoritativeState.container.effectiveAccessLevel,\n )\n );\n}\n\nasync function prepareRebasedLocalMetadataMutation(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n metadataState: ContainerMetadataState;\n localMetadataPatch:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n patch: Partial<ContainerMetadataPatch>;\n}) {\n const { authoritativeState, metadataState, patch } = input;\n const replacementVersion = encodeVersionVector(metadataState.doc);\n const replacementMetadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(authoritativeState.container.parentId),\n );\n writeContainerMetadataValue(metadataState.doc, {\n ...replacementMetadata,\n ...input.localMetadataPatch,\n });\n const rebasedMetadataState = {\n ...metadataState,\n container: authoritativeState.container,\n pullContinuation: authoritativeState.record.pullContinuation ?? null,\n record: authoritativeState.record,\n };\n return {\n durableRecord: authoritativeState.record,\n mutationContainer: authoritativeState.container,\n mutationMetadataState: rebasedMetadataState,\n mutationPatch: patch,\n pendingLocalUpdate: exportUpdatesSince(\n metadataState.doc,\n replacementVersion,\n ),\n pullContinuationSuperseded: false,\n securityContext: resolveMetadataSecurityContext(\n rebasedMetadataState,\n patch,\n ),\n securityContextMatches: true,\n };\n}\n\nfunction resolveMetadataSettlementMatch(\n expectedSyncState: ExpectedContainerMetadataSyncState | undefined,\n durableRecord: DocumentRecord | null,\n) {\n if (!expectedSyncState) {\n return {\n contentStateSuperseded: false,\n pullContinuationSuperseded: false,\n securityContextMatches: true,\n };\n }\n const securityContextMatches = metadataSyncSecurityContextMatches(\n durableRecord,\n expectedSyncState.record,\n );\n const progressStateMatches =\n securityContextMatches &&\n sameNullableMetadataValue(\n durableRecord?.lastCommitLsn,\n expectedSyncState.record.lastCommitLsn,\n ) &&\n Boolean(durableRecord?.pullContinuationRecoveryRequired) ===\n Boolean(expectedSyncState.record.pullContinuationRecoveryRequired) &&\n documentSyncPullContinuationsEqual(\n durableRecord?.pullContinuation,\n expectedSyncState.pullContinuation,\n );\n const contentStateMatches =\n progressStateMatches &&\n sameNullableMetadataValue(\n durableRecord?.metadataUpdates,\n expectedSyncState.record.metadataUpdates,\n ) &&\n sameNullableMetadataValue(\n durableRecord?.snapshotEndVersion,\n expectedSyncState.record.snapshotEndVersion,\n );\n return {\n contentStateSuperseded: progressStateMatches && !contentStateMatches,\n pullContinuationSuperseded: !progressStateMatches,\n securityContextMatches,\n };\n}\n\nexport async function prepareContainerMetadataMutation(\n input: PersistContainerMetadataStateInput,\n execSql: ExecSql,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const { metadataState, persistence } = input;\n const authoritativeState = await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql,\n persistence,\n });\n if (!authoritativeState) {\n return {\n authoritativeState: null,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n if (\n localMetadataWriteAccessWasRevoked({\n authoritativeState,\n mutationInput: input,\n })\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n const durableRecord = authoritativeState.record;\n const mutationMetadataState = durableRecord\n ? {\n ...metadataState,\n pullContinuation: durableRecord.pullContinuation ?? null,\n record: durableRecord,\n }\n : metadataState;\n const capturedSecurityContextMatches =\n durableRecord !== null &&\n metadataSyncSecurityContextMatches(durableRecord, metadataState.record);\n const {\n contentStateSuperseded,\n pullContinuationSuperseded,\n securityContextMatches,\n } = resolveMetadataSettlementMatch(input.expectedSyncState, durableRecord);\n\n if (\n input.expectedSyncState === undefined &&\n !capturedSecurityContextMatches\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n if (input.localUpdate === undefined) {\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n return prepareRebasedLocalMetadataMutation({\n authoritativeState,\n localMetadataPatch: input.localMetadataPatch,\n metadataState,\n patch,\n });\n }\n const mutationPatch = pullContinuationSuperseded ? {} : patch;\n const securityContext = resolveMetadataSecurityContext(\n mutationMetadataState,\n mutationPatch,\n );\n if (\n securityContextMatches &&\n (input.expectedSyncState === undefined || contentStateSuperseded)\n ) {\n mergeDurableMetadataCheckpoint({\n durableRecord,\n metadataState,\n securityContext,\n });\n }\n return {\n durableRecord,\n mutationContainer: authoritativeState.container,\n mutationMetadataState,\n mutationPatch,\n pendingLocalUpdate: input.localUpdate,\n pullContinuationSuperseded,\n securityContext,\n securityContextMatches,\n };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { base64ToBytes } from "../../../internal/encoding/index.js";
|
|
2
2
|
import { importUpdates } from "../../../internal/loro/index.js";
|
|
3
|
-
import { documentSyncPullContinuationsEqual, } from "../../../data/documents/shared/sync/syncPagination.js";
|
|
4
3
|
import { runSerializedSqlMutation } from "../../../data/sqlite/sqlSchema.js";
|
|
4
|
+
import { documentSyncPullContinuationsEqual, } from "../../documents/index.js";
|
|
5
5
|
import { currentMetadataPullContinuation } from "./metadataPersistence.js";
|
|
6
6
|
function metadataInvalidationStateMatches(input) {
|
|
7
7
|
const { accessEpoch, continuation, documentId, durableRecord, metadataState, } = input;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataPullContinuationInvalidation.js","sourceRoot":"","sources":["metadataPullContinuationInvalidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"metadataPullContinuationInvalidation.js","sourceRoot":"","sources":["metadataPullContinuationInvalidation.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport { runSerializedSqlMutation } from \"../../../data/sqlite/sqlSchema\";\nimport {\n type DocumentSyncPullContinuation,\n documentSyncPullContinuationsEqual,\n} from \"../../documents\";\nimport type { ContainerContentsWorkflowSqlRuntime } from \"../runtime\";\nimport { currentMetadataPullContinuation } from \"./metadataPersistence\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nfunction metadataInvalidationStateMatches(input: {\n accessEpoch: number;\n continuation: DocumentSyncPullContinuation;\n documentId: string;\n durableRecord: NonNullable<\n Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataRecord\"]>\n >\n >;\n metadataState: ContainerMetadataState;\n}): boolean {\n const {\n accessEpoch,\n continuation,\n documentId,\n durableRecord,\n metadataState,\n } = input;\n return (\n metadataState.record.documentId === documentId &&\n metadataState.record.accessEpoch === accessEpoch &&\n durableRecord.documentId === documentId &&\n durableRecord.accessEpoch === accessEpoch &&\n (durableRecord.accessStateHash ?? null) ===\n (metadataState.record.accessStateHash ?? null) &&\n (durableRecord.contentKeyBundle ?? null) ===\n (metadataState.record.contentKeyBundle ?? null) &&\n (durableRecord.documentKekTargets ?? null) ===\n (metadataState.record.documentKekTargets ?? null) &&\n (durableRecord.documentManifestBundle ?? null) ===\n (metadataState.record.documentManifestBundle ?? null) &&\n documentSyncPullContinuationsEqual(\n currentMetadataPullContinuation(metadataState),\n continuation,\n )\n );\n}\n\nexport async function invalidateContainerMetadataPullContinuation(input: {\n continuation: DocumentSyncPullContinuation;\n isCurrent?: (() => boolean) | undefined;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerContentsWorkflowSqlRuntime;\n}): Promise<void> {\n const { continuation, metadataState, runtime } = input;\n if (input.isCurrent?.() === false) return;\n const { accessEpoch, documentId } = metadataState.record;\n if (!documentId) return;\n\n await runSerializedSqlMutation(\n runtime.infra.execSql,\n async (lockedExecSql) => {\n if (input.isCurrent?.() === false) return;\n const durableRecord =\n await input.persistence.invalidateMetadataPullContinuation(\n lockedExecSql,\n {\n accessEpoch,\n accessStateHash: metadataState.record.accessStateHash ?? null,\n continuation,\n containerId: metadataState.container.id,\n contentKeyBundle: metadataState.record.contentKeyBundle ?? null,\n documentId,\n documentKekTargets: metadataState.record.documentKekTargets ?? null,\n documentManifestBundle:\n metadataState.record.documentManifestBundle ?? null,\n lastCommitLsn: metadataState.record.lastCommitLsn ?? null,\n stillCurrent: input.isCurrent,\n },\n );\n if (\n input.isCurrent?.() === false ||\n !durableRecord ||\n !metadataInvalidationStateMatches({\n accessEpoch,\n continuation,\n documentId,\n durableRecord,\n metadataState,\n })\n ) {\n return;\n }\n if (durableRecord.metadataUpdates) {\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n }\n const {\n pullContinuation: _stalePullContinuation,\n pullContinuationRecoveryRequired: _staleRecoveryMarker,\n ...liveRecord\n } = metadataState.record;\n metadataState.record = { ...liveRecord, ...durableRecord };\n metadataState.pullContinuation = durableRecord.pullContinuation ?? null;\n },\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isDocumentSyncUpdateIsolationError } from "../../../data/documents/shared/sync/documentSyncUpdateIsolation.js";
|
|
2
|
+
import { isPrincipalPolicyNotCachedError } from "../../../data/keyingProjectionVerification/index.js";
|
|
2
3
|
import { isKeyingVerificationError, reportKeyingVerificationErrorInCauseChain, } from "../../../data/keyingProjectionVerification/error.js";
|
|
3
|
-
import { isPrincipalPolicyNotCachedError } from "../../../data/keyingProjectionVerification/principalPolicy/principalPolicyVerification.js";
|
|
4
4
|
function isStaleContainerMetadataSecurityStateError(error) {
|
|
5
5
|
// Signed-state verification failures are terminal integrity incidents, even
|
|
6
6
|
// when their diagnostic message resembles an ordinary stale-key condition.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataSyncErrors.js","sourceRoot":"","sources":["metadataSyncErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,iEAAiE,CAAC;AACrH,OAAO,
|
|
1
|
+
{"version":3,"file":"metadataSyncErrors.js","sourceRoot":"","sources":["metadataSyncErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,iEAAiE,CAAC;AACrH,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EACL,yBAAyB,EACzB,yCAAyC,GAC1C,MAAM,kDAAkD,CAAC;AAG1D,SAAS,0CAA0C,CAAC,KAAc;IAChE,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,yBAAyB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5D,OAAO,CACL,OAAO,CAAC,UAAU,CAChB,gEAAgE,CACjE;QACD,OAAO,CAAC,UAAU,CAAC,6CAA6C,CAAC;QACjE,OAAO,CAAC,UAAU,CAAC,sCAAsC,CAAC;QAC1D,OAAO,CAAC,UAAU,CAAC,iDAAiD,CAAC;QACrE,OAAO,CAAC,UAAU,CAAC,gCAAgC,CAAC;QACpD,OAAO,KAAK,oCAAoC;QAChD,OAAO,KAAK,4CAA4C,CACzD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAUvD;IACC,IAAI,kCAAkC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,yCAAyC,CAC7C,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,EACzC;YACE,QAAQ,EAAE,KAAK,CAAC,WAAW;YAC3B,UAAU,EAAE,WAAW;YACvB,SAAS,EAAE,yBAAyB;YACpC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc;SAClD,CACF,CAAC;QACF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,iEAAiE,KAAK,CAAC,WAAW,kEAAkE,CACrJ,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,0CAA0C,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,KAAK,CAAC,WAAW,6CAA6C,CACjH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,+BAA+B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,KAAK,CAAC,WAAW,2DAA2D,CAC/H,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,CAAC,KAAK,CAAC;AACpB,CAAC","sourcesContent":["import { isDocumentSyncUpdateIsolationError } from \"../../../data/documents/shared/sync/documentSyncUpdateIsolation\";\nimport { isPrincipalPolicyNotCachedError } from \"../../../data/keyingProjectionVerification\";\nimport {\n isKeyingVerificationError,\n reportKeyingVerificationErrorInCauseChain,\n} from \"../../../data/keyingProjectionVerification/error\";\nimport type { SecurityIncidentReporter } from \"../../../data/shared/securityIncidents\";\n\nfunction isStaleContainerMetadataSecurityStateError(error: unknown): boolean {\n // Signed-state verification failures are terminal integrity incidents, even\n // when their diagnostic message resembles an ordinary stale-key condition.\n if (isKeyingVerificationError(error)) return false;\n const message = error instanceof Error ? error.message : \"\";\n\n return (\n message.startsWith(\n \"Document authorizing container KEK path could not be unwrapped\",\n ) ||\n message.startsWith(\"Document content key could not be unwrapped\") ||\n message.startsWith(\"Document content-key bundle is stale\") ||\n message.startsWith(\"Document content-key re-wrap KEK is unavailable\") ||\n message.startsWith(\"Document stale-bundle recovery\") ||\n message === \"Document sync target hash mismatch\" ||\n message === \"Document sync content-key targets mismatch\"\n );\n}\n\nexport async function deferRecoverableMetadataSyncError(input: {\n containerId: string;\n error: unknown;\n runtime: {\n auth: { organizationId: string | null };\n util: {\n log: (message: string) => void;\n reportSecurityIncident: SecurityIncidentReporter;\n };\n };\n}): Promise<null> {\n if (isDocumentSyncUpdateIsolationError(input.error)) {\n await reportKeyingVerificationErrorInCauseChain(\n input.error,\n input.runtime.util.reportSecurityIncident,\n {\n objectId: input.containerId,\n objectKind: \"container\",\n operation: \"container.metadata.sync\",\n organizationId: input.runtime.auth.organizationId,\n },\n );\n input.runtime.util.log(\n `Container contents: quarantined incoming metadata updates for ${input.containerId}; deferred this container without blocking later metadata syncs.`,\n );\n return null;\n }\n\n if (isStaleContainerMetadataSecurityStateError(input.error)) {\n input.runtime.util.log(\n `Container contents: deferred metadata sync for ${input.containerId} because its content-key targets are stale.`,\n );\n return null;\n }\n\n // A cold principal-policy cache is transient: warming already ran and failed\n // within this attempt. Keep the needing-sync state set for the next trigger.\n if (isPrincipalPolicyNotCachedError(input.error)) {\n input.runtime.util.log(\n `Container contents: deferred metadata sync for ${input.containerId} because a referenced principal policy is not cached yet.`,\n );\n return null;\n }\n\n throw input.error;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DocumentSyncPullContinuation } from "
|
|
1
|
+
import type { DocumentSyncPullContinuation } from "../../documents/index.js";
|
|
2
2
|
import type { ContainerDocumentRecord as DocumentRecord } from "../containerPersistence.js";
|
|
3
3
|
import type { ContainerMetadataState } from "./metadataTypes.js";
|
|
4
4
|
export interface ExpectedContainerMetadataSyncState {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataSyncSettlement.js","sourceRoot":"","sources":["metadataSyncSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAC;AAQ9E,MAAM,UAAU,yBAAyB,CACvC,IAA+B,EAC/B,KAAgC;IAEhC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,OAA8B,EAC9B,QAAwB;IAExB,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;QAC1C,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;QAC5C,yBAAyB,CACvB,OAAO,CAAC,eAAe,EACvB,QAAQ,CAAC,eAAe,CACzB;QACD,yBAAyB,CACvB,OAAO,CAAC,gBAAgB,EACxB,QAAQ,CAAC,gBAAgB,CAC1B;QACD,yBAAyB,CACvB,OAAO,CAAC,kBAAkB,EAC1B,QAAQ,CAAC,kBAAkB,CAC5B;QACD,yBAAyB,CACvB,OAAO,CAAC,sBAAsB,EAC9B,QAAQ,CAAC,sBAAsB,CAChC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAGvD;IACC,MAAM,cAAc,GAAG,MAAM,+BAA+B,CAC1D,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CACjC,CAAC;IACF,IAAI,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC;QACzC,aAAa,CAAC,cAAc,EAAE;YAC5B,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,cAAc,CAAC;IACzC,KAAK,CAAC,aAAa,CAAC,wBAAwB,GAAG,IAAI,CAAC;AACtD,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport type { DocumentSyncPullContinuation } from \"
|
|
1
|
+
{"version":3,"file":"metadataSyncSettlement.js","sourceRoot":"","sources":["metadataSyncSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAC;AAQ9E,MAAM,UAAU,yBAAyB,CACvC,IAA+B,EAC/B,KAAgC;IAEhC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,OAA8B,EAC9B,QAAwB;IAExB,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;QAC1C,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;QAC5C,yBAAyB,CACvB,OAAO,CAAC,eAAe,EACvB,QAAQ,CAAC,eAAe,CACzB;QACD,yBAAyB,CACvB,OAAO,CAAC,gBAAgB,EACxB,QAAQ,CAAC,gBAAgB,CAC1B;QACD,yBAAyB,CACvB,OAAO,CAAC,kBAAkB,EAC1B,QAAQ,CAAC,kBAAkB,CAC5B;QACD,yBAAyB,CACvB,OAAO,CAAC,sBAAsB,EAC9B,QAAQ,CAAC,sBAAsB,CAChC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAGvD;IACC,MAAM,cAAc,GAAG,MAAM,+BAA+B,CAC1D,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CACjC,CAAC;IACF,IAAI,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC;QACzC,aAAa,CAAC,cAAc,EAAE;YAC5B,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,cAAc,CAAC;IACzC,KAAK,CAAC,aAAa,CAAC,wBAAwB,GAAG,IAAI,CAAC;AACtD,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport type { DocumentSyncPullContinuation } from \"../../documents\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport { createContainerMetadataDocument } from \"./containerMetadataDocument\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface ExpectedContainerMetadataSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: DocumentRecord;\n}\n\nexport function sameNullableMetadataValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function metadataSyncSecurityContextMatches(\n current: DocumentRecord | null,\n expected: DocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableMetadataValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n sameNullableMetadataValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableMetadataValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableMetadataValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nexport async function replaceSupersededMetadataIdentity(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n}): Promise<void> {\n const replacementDoc = await createContainerMetadataDocument(\n input.metadataState.container.id,\n );\n if (input.durableRecord?.metadataUpdates) {\n importUpdates(replacementDoc, [\n base64ToBytes(input.durableRecord.metadataUpdates),\n ]);\n }\n input.metadataState.doc = replacementDoc;\n input.metadataState.metadataWriterProjection = null;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DocumentWriterProjectionResponse } from "../../../internal/validators/response/index.js";
|
|
2
|
-
import type { DocumentSyncPullContinuation } from "../../../data/documents/shared/sync/syncPagination.js";
|
|
3
2
|
import type { ContainerMetadataRecord } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
4
3
|
import type { ContainerRecord } from "../../../data/persistence/container-contents/containerPersistence.js";
|
|
4
|
+
import type { DocumentSyncPullContinuation } from "../../documents/index.js";
|
|
5
5
|
import type { ContainerMetadataDocument } from "./containerMetadataDocument.js";
|
|
6
6
|
export interface ContainerMetadataState {
|
|
7
7
|
container: ContainerRecord;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataTypes.js","sourceRoot":"","sources":["metadataTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type {
|
|
1
|
+
{"version":3,"file":"metadataTypes.js","sourceRoot":"","sources":["metadataTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { ContainerMetadataRecord } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/container-contents/containerPersistence\";\nimport type { DocumentSyncPullContinuation } from \"../../documents\";\nimport type { ContainerMetadataDocument } from \"./containerMetadataDocument\";\n\nexport interface ContainerMetadataState {\n container: ContainerRecord;\n doc: ContainerMetadataDocument;\n metadataWriterProjection?:\n | DocumentWriterProjectionResponse\n | null\n | undefined;\n /** See `ContainerState.writerProjectionGeneration`; shared by both caches. */\n writerProjectionGeneration?: number | undefined;\n /** Durable continuation mirrored from the metadata document record. */\n pullContinuation?: DocumentSyncPullContinuation | null | undefined;\n record: ContainerMetadataRecord;\n /**\n * Consecutive completed sync passes that re-keyed conflicted pending updates\n * without settling anything; bounds the rekey-driven follow-up sync. See\n * shouldReArmAfterOutgoingSettlement.\n */\n rekeyOnlyPassCount?: number | undefined;\n}\n\nexport interface ContainerMetadataPatch {\n accessEpoch: number;\n accessStateHash: string | null;\n effectiveAccessLevel: ContainerRecord[\"effectiveAccessLevel\"];\n documentId: string | null;\n icon: string | null;\n lastCommitLsn: string | null;\n metadataDocumentId: string | null;\n systemSlot: ContainerRecord[\"systemSlot\"];\n metadataUpdates: string;\n name: string;\n organizationId: string;\n parentId: string | null;\n pullContinuation: DocumentSyncPullContinuation | null;\n contentKeyBundle: string | null;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n}\n\nexport interface PersistedContainerMetadataState {\n container: ContainerRecord;\n createIntentSettled?: true;\n moveIntentSettled?: true;\n mutationSuperseded?: true;\n pullContinuationSuperseded?: true;\n record: ContainerMetadataRecord;\n syncIdentitySuperseded?: true;\n}\n\nexport interface SyncedContainerMetadataState\n extends PersistedContainerMetadataState {\n shouldRequestFollowupSync: boolean;\n}\n\nexport interface MissingContainerMetadataState {\n missing: true;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { DOCUMENTS_APP_KIND } from "../../../data/documents/documentConstants.js";
|
|
1
2
|
import { CONTAINER_METADATA_APP_KIND } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
2
3
|
import { sqlDocumentMoveIntentPersistence } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
3
4
|
import { sqlDocumentsPersistence } from "../../../data/persistence/documents/documentsPersistence.js";
|
|
4
|
-
import { DOCUMENTS_APP_KIND } from "../../../data/persistence/documents/internal/constants.js";
|
|
5
5
|
import { clearDocumentSyncFailure, resetDocumentPendingUpdateRekeyBudget, } from "../../../data/sqlite/documentPersistence/index.js";
|
|
6
6
|
import { documentPlacementIntentTables, documentTables, LOCAL_INTENT_LANES, } from "../../../data/sqlite/schema/index.js";
|
|
7
7
|
import { ensureSqlTables } from "../../../data/sqlite/sqlSchema.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { DOCUMENTS_APP_KIND } from \"../../../data/documents/documentConstants\";\nimport { CONTAINER_METADATA_APP_KIND } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentsPersistence } from \"../../../data/persistence/documents/documentsPersistence\";\nimport {\n clearDocumentSyncFailure,\n resetDocumentPendingUpdateRekeyBudget,\n} from \"../../../data/sqlite/documentPersistence\";\nimport {\n documentPlacementIntentTables,\n documentTables,\n LOCAL_INTENT_LANES,\n} from \"../../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../../data/sqlite/sqlSchema\";\nimport { defaultContainerContentsPersistence } from \"../containerPersistence\";\nimport { groupPendingWriteCandidates } from \"./aggregation\";\nimport {\n hasDeferredTailScopeWork,\n listDeferredPendingWriteCandidates,\n} from \"./deferredTails\";\nimport type { PendingWriteQueueItem } from \"./pendingWritesTypes\";\nimport { listPersistedPendingWriteCandidates } from \"./sources\";\n\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\n/**\n * List identity-wide local state that still requires a remote write. The\n * returned diagnostic contains only navigation/display metadata and aggregate\n * counts; serialized updates, local storage keys, and upload crypto stay below\n * the workflow boundary.\n */\nexport async function listPendingWrites(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingWriteQueueItem>> {\n await defaultContainerContentsPersistence.ensureSchema(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await sqlDocumentMoveIntentPersistence.ensureSchema(execSql);\n\n const [persisted, deferred] = await Promise.all([\n listPersistedPendingWriteCandidates(execSql),\n listDeferredPendingWriteCandidates(execSql),\n ]);\n return groupPendingWriteCandidates([...persisted, ...deferred]);\n}\n\n/**\n * Explicit manual retry for one write-queue item: reset the durable re-key\n * budget for the item's ACTUAL pending-update scope (container metadata and\n * unknown document namespaces re-key through the same recovery path as\n * ordinary documents) and clear the recorded terminal failure — the next\n * pass re-records both if they still hold. The cap protects against a\n * server driving a network-speed re-key loop; a deliberate user retry is\n * the rate-limited signal that conditions have changed (e.g. an outage that\n * burned the budget has healed). The caller re-arms the sync lanes.\n */\nexport async function resetPendingWriteRetryState(\n execSql: ExecSql,\n input: {\n localId: string;\n /** The item's `namespace` — the unrecognized documents.app_kind, if any. */\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n },\n): Promise<void> {\n const appKind =\n input.objectKind === \"container\"\n ? CONTAINER_METADATA_APP_KIND\n : (input.namespace ??\n (input.objectKind === \"document\" ? DOCUMENTS_APP_KIND : null));\n if (appKind === null) {\n // An unknown object kind with no namespace: there is no scope to reset,\n // and guessing one could clear an unrelated scope sharing the localId.\n return;\n }\n const scope = { appKind, localId: input.localId };\n await resetDocumentPendingUpdateRekeyBudget(execSql, scope);\n if (appKind === DOCUMENTS_APP_KIND) {\n // A deliberate retry is the rate-limited signal that conditions changed:\n // a parked permission-denied move (row 7) replays once, like row 11's\n // re-key budget reset.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql, {\n localId: input.localId,\n });\n }\n // Clearing the failure row is part of the re-key budget reset (edge-case\n // row 11) and only makes sense alongside queued work. A failure-only item\n // (a refused revalidation, row 13) has no queued work: its row is the\n // priming ticket that re-drives the store, so it must survive the retry\n // and clear on the next clean pass instead of vanishing with no request.\n if (await hasQueuedScopeWork(execSql, scope)) {\n await clearDocumentSyncFailure(execSql, scope);\n }\n}\n\n/**\n * Whether ANY durable outbound work exists for the scope — CRDT updates,\n * staged attachment uploads, move intents, a never-created local document, or\n * a deferred write whose only durable content is the history tail ahead of\n * its covered frontier. Mirrors the queue's own document candidate sources,\n * so \"failure-only\" here agrees with the item the panel rendered.\n */\nasync function hasQueuedScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentPlacementIntentTables,\n ]);\n const rows = await execSql(\n `SELECT 1 AS present\n WHERE EXISTS (\n SELECT 1 FROM document_history_updates pending\n WHERE pending.app_kind = ? AND pending.local_id = ?\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1 FROM document_pending_attachments attachment\n WHERE attachment.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM local_intents intent\n WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'\n AND intent.local_id = ?\n AND intent.intent_type IN ('document.move', 'document.link')\n )\n OR EXISTS (\n SELECT 1 FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.document_id IS NULL\n )\n LIMIT 1`,\n [\n scope.appKind,\n scope.localId,\n scope.localId,\n scope.localId,\n scope.appKind,\n scope.localId,\n ],\n );\n if (rows.length > 0) {\n return true;\n }\n // The queue's deferred-update source has no queued rows to probe: the\n // write lives in the durable history tail, detectable only by the\n // version-vector coverage check.\n return hasDeferredTailScopeWork(execSql, scope);\n}\n"]}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { KeyingVerificationError, } from "../../../../internal/crypto/index.js";
|
|
2
2
|
import { deriveOrganizationMetadataContainerSystemSlot } from "../../../../internal/validators/containerSystemSlot.js";
|
|
3
|
-
import { verifiedContainerCreateManifest } from "../../../../data/keyingProjectionVerification/
|
|
4
|
-
import { verifyContainerDestinationProjection } from "../../../../data/keyingProjectionVerification/container/containerDestinationVerification.js";
|
|
5
|
-
import { verifyContainerWriterProjection } from "../../../../data/keyingProjectionVerification/container/containerProjectionVerification.js";
|
|
3
|
+
import { verifiedContainerCreateManifest, verifyContainerDestinationProjection, verifyContainerWriterProjection, } from "../../../../data/keyingProjectionVerification/index.js";
|
|
6
4
|
import { isKeyingVerificationError, reportKeyingVerificationErrorInCauseChain, runWithSecurityIncidentReporting, } from "../../../../data/keyingProjectionVerification/error.js";
|
|
7
5
|
import { listingRepeatsHeldOrdinaryBinding, } from "../../../../data/persistence/container-contents/containerBinding.js";
|
|
8
6
|
import { verifyRuntimeGroupMetadataAuthority } from "../../../organizations/groupMetadata/runtimeGroupMetadataAuthority.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verifiedDestination.js","sourceRoot":"","sources":["verifiedDestination.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport { deriveOrganizationMetadataContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport { verifiedContainerCreateManifest } from \"../../../../data/keyingProjectionVerification/container/containerCreateManifest\";\nimport { verifyContainerDestinationProjection } from \"../../../../data/keyingProjectionVerification/container/containerDestinationVerification\";\nimport { verifyContainerWriterProjection } from \"../../../../data/keyingProjectionVerification/container/containerProjectionVerification\";\nimport {\n isKeyingVerificationError,\n reportKeyingVerificationErrorInCauseChain,\n runWithSecurityIncidentReporting,\n} from \"../../../../data/keyingProjectionVerification/error\";\nimport {\n type HeldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../../../data/persistence/container-contents/containerBinding\";\nimport { verifyRuntimeGroupMetadataAuthority } from \"../../../organizations/groupMetadata/runtimeGroupMetadataAuthority\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../../principals/runtimePolicyWarmer\";\nimport type {\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationState,\n} from \"../types\";\nimport type { PrefetchedDestinationProjection } from \"./destinationPrefetch\";\nimport {\n cachedDestinationRole,\n type DestinationRole,\n rememberDestinationRole,\n} from \"./destinationRoleCache\";\nimport { resolveWithMetadataRootReload } from \"./destinationRootReload\";\nimport { assertPermittedDestinationBinding } from \"./replacementBinding\";\n\n/** The identity a role is verified and cached under. */\ntype DestinationIdentity = Pick<RemoteContainer, \"id\" | \"organizationId\">;\n\nasync function destinationRoleFromPath(input: {\n listed: DestinationIdentity;\n path: readonly VerifiedContainerAccessManifest[];\n verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): Promise<{ role: DestinationRole; parentId: string | null }> {\n const { listed, path } = input;\n const head = path.at(-1);\n if (\n !head ||\n head.state.containerId !== listed.id ||\n head.state.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination manifest has the wrong identity\",\n );\n }\n const metadataSlot = await deriveOrganizationMetadataContainerSystemSlot({\n organizationId: listed.organizationId,\n });\n if (\n head.state.systemSlot !== null &&\n path.length !== (head.state.systemSlot === metadataSlot ? 1 : 2)\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"system destination has the wrong signed topology\",\n );\n }\n // The head may be a later grant signed by any admin; only the epoch-1\n // create names the creator, and roots are always created by the org owner.\n const created = verifiedContainerCreateManifest({\n head,\n label: \"Container destination\",\n verifiedByHash: input.verifiedByHash,\n });\n const root = path[0];\n if (!root) throw new Error(\"Destination root is unavailable\");\n const rootCreated = verifiedContainerCreateManifest({\n head: root,\n label: \"Destination root\",\n verifiedByHash: input.verifiedByHash,\n });\n return {\n parentId: head.state.parentContainerId,\n role: {\n createSignerUserId: created.event.event.signerUserId,\n rootContainerId: rootCreated.state.containerId,\n rootCreateManifestHash: rootCreated.manifestHash,\n rootMetadataDocumentId: rootCreated.state.metadataDocumentId,\n metadataDocumentId: head.state.metadataDocumentId,\n ...(head.state.parentContainerId === null ||\n head.state.systemSlot !== null\n ? { parentId: head.state.parentContainerId }\n : {}),\n systemSlot: head.state.systemSlot,\n },\n };\n}\n\n/**\n * The session's root id arrives in an unsigned login response, so the root it\n * names must prove it belongs to this user: every acknowledged organization was\n * created by the session user, whose device signed the root's `container.create`.\n * A verified root created by anyone else is a substitution, never the merge\n * target for pre-login local content, whatever grants it carries. The check\n * runs on cache reuse too, since the cache is not scoped to the session user.\n */\nfunction assertRootCreatedBySessionUser(\n role: DestinationRole,\n runtime: RemoteContainerHydrationState[\"runtime\"],\n): void {\n if (role.systemSlot !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"acknowledged session root cannot be a system container\",\n );\n }\n if (role.createSignerUserId !== runtime.auth.userId) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"acknowledged session root was not created by the session user\",\n );\n }\n}\n\nfunction assertAcknowledgedRootSigner(input: {\n listed: DestinationIdentity;\n role: DestinationRole;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): void {\n const { listed, role, runtime } = input;\n if (role.parentId !== null || listed.id !== runtime.auth.rootContainerId) {\n return;\n }\n assertRootCreatedBySessionUser(role, runtime);\n}\n\n/**\n * Authenticate destination roles before admitting a binding or advancing any\n * placement pin. Shared rehomes additionally require signed replacement evidence.\n */\nasync function verifyDestinationRole(input: {\n heldBinding: HeldContainerBinding | null;\n prefetched: PrefetchedDestinationProjection | undefined;\n verifyCurrentPlacement: boolean;\n onVerifiedCheckpoint:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n isCurrent?: (() => boolean) | undefined;\n listed: DestinationIdentity;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): Promise<{ role: DestinationRole; parentId: string | null } | null> {\n const { isCurrent, listed, runtime } = input;\n const projection = input.prefetched\n ? input.prefetched.projection\n : await runtime.apiClient.getContainerWriterProjection(listed.id);\n if (!projection || isCurrent?.() === false) return null;\n if (\n projection.containerId !== listed.id ||\n projection.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination projection has the wrong identity\",\n );\n }\n const verificationInput = {\n execSql: runtime.infra.execSql,\n projection,\n resolveUserKey: runtime.resolveTrustedUserIdentity,\n stillCurrent: isCurrent,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n };\n const { path, verifiedByHash } =\n await verifyContainerDestinationProjection(verificationInput);\n if (isCurrent?.() === false) return null;\n const destination = await destinationRoleFromPath({\n listed,\n path,\n verifiedByHash,\n });\n const { role } = destination;\n // Refuse a rebinding before group checks or placement pins run for it.\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (role.parentId === null && role.systemSlot !== null) {\n const head = path.at(-1);\n if (!head) throw new Error(\"Metadata root manifest is unavailable\");\n await verifyRuntimeGroupMetadataAuthority({\n runtime,\n organizationId: listed.organizationId,\n organizationReference: projection.policyEvidence.organization?.head,\n state: head.state,\n stillCurrent: isCurrent ?? (() => true),\n });\n }\n if (isCurrent?.() === false) return null;\n if (input.verifyCurrentPlacement) {\n // Check the immutable role before allowing current placement to advance pins.\n assertAcknowledgedRootSigner({ listed, role, runtime });\n const currentPath = await verifyContainerWriterProjection({\n ...verificationInput,\n stillCurrent: isCurrent,\n });\n const currentHead = currentPath.at(-1);\n if (!currentHead)\n throw new Error(\"Recovery placement manifest is unavailable\");\n input.onVerifiedCheckpoint?.(currentHead.checkpoint);\n }\n if (isCurrent?.() === false) return null;\n return destination;\n}\n\ntype VerifyRemoteContainerDestinationInput = {\n heldBinding: HeldContainerBinding | null;\n /** The held folder was re-homed away from the listed organization. */\n supersededListing?: boolean | undefined;\n /** Fetched ahead by page hydration; ignored when placement is refreshed. */\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n refresh?: boolean;\n onVerifiedCheckpoint?:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n isCurrent?: (() => boolean) | undefined;\n};\n\n/** A cached immutable role, or a freshly verified one with its signed parent. */\nasync function resolveDestinationRole(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<{\n freshlyVerified: boolean;\n parentId: string | null | undefined;\n role: DestinationRole;\n} | null> {\n const { remoteContainer: listed, isCurrent } = input;\n const runtime = input.state.runtime;\n const cached = input.refresh\n ? undefined\n : cachedDestinationRole(runtime.infra.execSql, listed);\n // Ordinary parent edges are not immutable. A refresh authenticates current\n // placement; a forged root hint must also be corrected from a signed path.\n if (cached && !(cached.parentId === undefined && listed.parentId === null)) {\n return { freshlyVerified: false, parentId: cached.parentId, role: cached };\n }\n const verified = await verifyDestinationRole({\n heldBinding: input.heldBinding,\n prefetched: input.refresh ? undefined : input.prefetchedProjection,\n isCurrent,\n listed,\n runtime,\n verifyCurrentPlacement: input.refresh === true,\n onVerifiedCheckpoint: input.onVerifiedCheckpoint,\n });\n if (!verified) return null;\n return {\n freshlyVerified: true,\n parentId:\n input.refresh || listed.parentId === null\n ? verified.parentId\n : verified.role.parentId,\n role: verified.role,\n };\n}\n\n/**\n * Listing hints never establish a metadata target or a system/root role, and a\n * held folder keeps its organization and metadata target unless its own user\n * re-created it or its pinned founder authorized a verified replacement.\n * A conflicting proof is refused before placement pins\n * advance or its role is cached.\n */\nexport async function verifyRemoteContainerDestination(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<RemoteContainer | null> {\n const { remoteContainer: listed, state, isCurrent } = input;\n const runtime = state.runtime;\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: listed.id,\n objectKind: \"container\",\n operation: \"container.destination.verify\",\n organizationId: listed.organizationId,\n },\n async () => {\n if (input.supersededListing) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container was re-homed away from the listed organization\",\n );\n }\n // A held ordinary binding was verified (or signed by this device) when\n // it was stored; a listing that repeats it needs no second proof.\n if (\n !input.refresh &&\n listingRepeatsHeldOrdinaryBinding(input.heldBinding, listed)\n ) {\n return { ...listed, systemSlot: null };\n }\n if (input.refresh)\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n // A metadata root read before a reserved-group commit is reloaded once.\n const resolved = await resolveWithMetadataRootReload(\n input,\n resolveDestinationRole,\n () => runtime.apiClient.evictContainerWriterProjection(listed.id),\n ).catch((error: unknown) => {\n // Never re-serve a cached projection that failed verification.\n if (isKeyingVerificationError(error))\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n throw error;\n });\n if (!resolved || isCurrent?.() === false) return null;\n const { role, parentId } = resolved;\n // Fresh verification checked this binding before any placement pins.\n // A cached role still needs the held binding and replacement proof checked.\n if (!resolved.freshlyVerified)\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (resolved.freshlyVerified)\n rememberDestinationRole(runtime.infra.execSql, listed, role);\n assertAcknowledgedRootSigner({ listed, role, runtime });\n return {\n ...listed,\n metadataDocumentId: role.metadataDocumentId,\n parentId: parentId === undefined ? listed.parentId : parentId,\n systemSlot: role.systemSlot,\n };\n },\n );\n}\n\n/** The root the unsigned login answer named, in the expected organization. */\nexport function isSessionRootState(\n remoteRootState: ContainerState,\n state: RemoteContainerHydrationState,\n): boolean {\n const { container } = remoteRootState;\n const { auth } = state.runtime;\n return (\n container.parentId === null &&\n !container.systemSlot &&\n container.id === auth.rootContainerId &&\n container.organizationId === auth.organizationId\n );\n}\n\n/**\n * Whether the session root may absorb the pre-login local roots. The unsigned\n * login answer only names the root; the merge target must also be the verified\n * root whose epoch-1 `container.create` the session user signed. A row persisted\n * earlier as an ordinary shared container (another user's root this device once\n * hydrated) never passed that check for this session, so the creator is checked\n * here, at the reconciliation boundary itself, before any local content is\n * re-parented. The role comes only from the cache remote hydration fills when\n * it verifies the destination: this gate never fetches, so a local refresh stays\n * independent of the network. Without a cached role the merge is left pending\n * (no incident) until hydration verifies the root and reconciles from the\n * cache. A different creator is a `signer_mismatch` incident and never a merge;\n * the refusal is the \"no merge\" outcome, so the refresh that carried it\n * completes with the local content left in place.\n */\nexport async function isVerifiedLocalRootReconciliationTarget(input: {\n remoteRootState: ContainerState;\n state: RemoteContainerHydrationState;\n}): Promise<boolean> {\n const { remoteRootState, state } = input;\n const { container } = remoteRootState;\n const runtime = state.runtime;\n if (!isSessionRootState(remoteRootState, state)) return false;\n const role = cachedDestinationRole(runtime.infra.execSql, container);\n if (!role) return false;\n try {\n if (role.parentId !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"session root reconciliation target is not a verified root\",\n );\n }\n assertRootCreatedBySessionUser(role, runtime);\n return true;\n } catch (error) {\n const reported = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: container.id,\n objectKind: \"container\",\n operation: \"container.root.reconcile\",\n organizationId: container.organizationId,\n },\n );\n if (!reported) throw error;\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"verifiedDestination.js","sourceRoot":"","sources":["verifiedDestination.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport { deriveOrganizationMetadataContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport {\n verifiedContainerCreateManifest,\n verifyContainerDestinationProjection,\n verifyContainerWriterProjection,\n} from \"../../../../data/keyingProjectionVerification\";\nimport {\n isKeyingVerificationError,\n reportKeyingVerificationErrorInCauseChain,\n runWithSecurityIncidentReporting,\n} from \"../../../../data/keyingProjectionVerification/error\";\nimport {\n type HeldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../../../data/persistence/container-contents/containerBinding\";\nimport { verifyRuntimeGroupMetadataAuthority } from \"../../../organizations/groupMetadata/runtimeGroupMetadataAuthority\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../../principals/runtimePolicyWarmer\";\nimport type {\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationState,\n} from \"../types\";\nimport type { PrefetchedDestinationProjection } from \"./destinationPrefetch\";\nimport {\n cachedDestinationRole,\n type DestinationRole,\n rememberDestinationRole,\n} from \"./destinationRoleCache\";\nimport { resolveWithMetadataRootReload } from \"./destinationRootReload\";\nimport { assertPermittedDestinationBinding } from \"./replacementBinding\";\n\n/** The identity a role is verified and cached under. */\ntype DestinationIdentity = Pick<RemoteContainer, \"id\" | \"organizationId\">;\n\nasync function destinationRoleFromPath(input: {\n listed: DestinationIdentity;\n path: readonly VerifiedContainerAccessManifest[];\n verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): Promise<{ role: DestinationRole; parentId: string | null }> {\n const { listed, path } = input;\n const head = path.at(-1);\n if (\n !head ||\n head.state.containerId !== listed.id ||\n head.state.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination manifest has the wrong identity\",\n );\n }\n const metadataSlot = await deriveOrganizationMetadataContainerSystemSlot({\n organizationId: listed.organizationId,\n });\n if (\n head.state.systemSlot !== null &&\n path.length !== (head.state.systemSlot === metadataSlot ? 1 : 2)\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"system destination has the wrong signed topology\",\n );\n }\n // The head may be a later grant signed by any admin; only the epoch-1\n // create names the creator, and roots are always created by the org owner.\n const created = verifiedContainerCreateManifest({\n head,\n label: \"Container destination\",\n verifiedByHash: input.verifiedByHash,\n });\n const root = path[0];\n if (!root) throw new Error(\"Destination root is unavailable\");\n const rootCreated = verifiedContainerCreateManifest({\n head: root,\n label: \"Destination root\",\n verifiedByHash: input.verifiedByHash,\n });\n return {\n parentId: head.state.parentContainerId,\n role: {\n createSignerUserId: created.event.event.signerUserId,\n rootContainerId: rootCreated.state.containerId,\n rootCreateManifestHash: rootCreated.manifestHash,\n rootMetadataDocumentId: rootCreated.state.metadataDocumentId,\n metadataDocumentId: head.state.metadataDocumentId,\n ...(head.state.parentContainerId === null ||\n head.state.systemSlot !== null\n ? { parentId: head.state.parentContainerId }\n : {}),\n systemSlot: head.state.systemSlot,\n },\n };\n}\n\n/**\n * The session's root id arrives in an unsigned login response, so the root it\n * names must prove it belongs to this user: every acknowledged organization was\n * created by the session user, whose device signed the root's `container.create`.\n * A verified root created by anyone else is a substitution, never the merge\n * target for pre-login local content, whatever grants it carries. The check\n * runs on cache reuse too, since the cache is not scoped to the session user.\n */\nfunction assertRootCreatedBySessionUser(\n role: DestinationRole,\n runtime: RemoteContainerHydrationState[\"runtime\"],\n): void {\n if (role.systemSlot !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"acknowledged session root cannot be a system container\",\n );\n }\n if (role.createSignerUserId !== runtime.auth.userId) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"acknowledged session root was not created by the session user\",\n );\n }\n}\n\nfunction assertAcknowledgedRootSigner(input: {\n listed: DestinationIdentity;\n role: DestinationRole;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): void {\n const { listed, role, runtime } = input;\n if (role.parentId !== null || listed.id !== runtime.auth.rootContainerId) {\n return;\n }\n assertRootCreatedBySessionUser(role, runtime);\n}\n\n/**\n * Authenticate destination roles before admitting a binding or advancing any\n * placement pin. Shared rehomes additionally require signed replacement evidence.\n */\nasync function verifyDestinationRole(input: {\n heldBinding: HeldContainerBinding | null;\n prefetched: PrefetchedDestinationProjection | undefined;\n verifyCurrentPlacement: boolean;\n onVerifiedCheckpoint:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n isCurrent?: (() => boolean) | undefined;\n listed: DestinationIdentity;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): Promise<{ role: DestinationRole; parentId: string | null } | null> {\n const { isCurrent, listed, runtime } = input;\n const projection = input.prefetched\n ? input.prefetched.projection\n : await runtime.apiClient.getContainerWriterProjection(listed.id);\n if (!projection || isCurrent?.() === false) return null;\n if (\n projection.containerId !== listed.id ||\n projection.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination projection has the wrong identity\",\n );\n }\n const verificationInput = {\n execSql: runtime.infra.execSql,\n projection,\n resolveUserKey: runtime.resolveTrustedUserIdentity,\n stillCurrent: isCurrent,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n };\n const { path, verifiedByHash } =\n await verifyContainerDestinationProjection(verificationInput);\n if (isCurrent?.() === false) return null;\n const destination = await destinationRoleFromPath({\n listed,\n path,\n verifiedByHash,\n });\n const { role } = destination;\n // Refuse a rebinding before group checks or placement pins run for it.\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (role.parentId === null && role.systemSlot !== null) {\n const head = path.at(-1);\n if (!head) throw new Error(\"Metadata root manifest is unavailable\");\n await verifyRuntimeGroupMetadataAuthority({\n runtime,\n organizationId: listed.organizationId,\n organizationReference: projection.policyEvidence.organization?.head,\n state: head.state,\n stillCurrent: isCurrent ?? (() => true),\n });\n }\n if (isCurrent?.() === false) return null;\n if (input.verifyCurrentPlacement) {\n // Check the immutable role before allowing current placement to advance pins.\n assertAcknowledgedRootSigner({ listed, role, runtime });\n const currentPath = await verifyContainerWriterProjection({\n ...verificationInput,\n stillCurrent: isCurrent,\n });\n const currentHead = currentPath.at(-1);\n if (!currentHead)\n throw new Error(\"Recovery placement manifest is unavailable\");\n input.onVerifiedCheckpoint?.(currentHead.checkpoint);\n }\n if (isCurrent?.() === false) return null;\n return destination;\n}\n\ntype VerifyRemoteContainerDestinationInput = {\n heldBinding: HeldContainerBinding | null;\n /** The held folder was re-homed away from the listed organization. */\n supersededListing?: boolean | undefined;\n /** Fetched ahead by page hydration; ignored when placement is refreshed. */\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n refresh?: boolean;\n onVerifiedCheckpoint?:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n isCurrent?: (() => boolean) | undefined;\n};\n\n/** A cached immutable role, or a freshly verified one with its signed parent. */\nasync function resolveDestinationRole(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<{\n freshlyVerified: boolean;\n parentId: string | null | undefined;\n role: DestinationRole;\n} | null> {\n const { remoteContainer: listed, isCurrent } = input;\n const runtime = input.state.runtime;\n const cached = input.refresh\n ? undefined\n : cachedDestinationRole(runtime.infra.execSql, listed);\n // Ordinary parent edges are not immutable. A refresh authenticates current\n // placement; a forged root hint must also be corrected from a signed path.\n if (cached && !(cached.parentId === undefined && listed.parentId === null)) {\n return { freshlyVerified: false, parentId: cached.parentId, role: cached };\n }\n const verified = await verifyDestinationRole({\n heldBinding: input.heldBinding,\n prefetched: input.refresh ? undefined : input.prefetchedProjection,\n isCurrent,\n listed,\n runtime,\n verifyCurrentPlacement: input.refresh === true,\n onVerifiedCheckpoint: input.onVerifiedCheckpoint,\n });\n if (!verified) return null;\n return {\n freshlyVerified: true,\n parentId:\n input.refresh || listed.parentId === null\n ? verified.parentId\n : verified.role.parentId,\n role: verified.role,\n };\n}\n\n/**\n * Listing hints never establish a metadata target or a system/root role, and a\n * held folder keeps its organization and metadata target unless its own user\n * re-created it or its pinned founder authorized a verified replacement.\n * A conflicting proof is refused before placement pins\n * advance or its role is cached.\n */\nexport async function verifyRemoteContainerDestination(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<RemoteContainer | null> {\n const { remoteContainer: listed, state, isCurrent } = input;\n const runtime = state.runtime;\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: listed.id,\n objectKind: \"container\",\n operation: \"container.destination.verify\",\n organizationId: listed.organizationId,\n },\n async () => {\n if (input.supersededListing) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container was re-homed away from the listed organization\",\n );\n }\n // A held ordinary binding was verified (or signed by this device) when\n // it was stored; a listing that repeats it needs no second proof.\n if (\n !input.refresh &&\n listingRepeatsHeldOrdinaryBinding(input.heldBinding, listed)\n ) {\n return { ...listed, systemSlot: null };\n }\n if (input.refresh)\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n // A metadata root read before a reserved-group commit is reloaded once.\n const resolved = await resolveWithMetadataRootReload(\n input,\n resolveDestinationRole,\n () => runtime.apiClient.evictContainerWriterProjection(listed.id),\n ).catch((error: unknown) => {\n // Never re-serve a cached projection that failed verification.\n if (isKeyingVerificationError(error))\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n throw error;\n });\n if (!resolved || isCurrent?.() === false) return null;\n const { role, parentId } = resolved;\n // Fresh verification checked this binding before any placement pins.\n // A cached role still needs the held binding and replacement proof checked.\n if (!resolved.freshlyVerified)\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (resolved.freshlyVerified)\n rememberDestinationRole(runtime.infra.execSql, listed, role);\n assertAcknowledgedRootSigner({ listed, role, runtime });\n return {\n ...listed,\n metadataDocumentId: role.metadataDocumentId,\n parentId: parentId === undefined ? listed.parentId : parentId,\n systemSlot: role.systemSlot,\n };\n },\n );\n}\n\n/** The root the unsigned login answer named, in the expected organization. */\nexport function isSessionRootState(\n remoteRootState: ContainerState,\n state: RemoteContainerHydrationState,\n): boolean {\n const { container } = remoteRootState;\n const { auth } = state.runtime;\n return (\n container.parentId === null &&\n !container.systemSlot &&\n container.id === auth.rootContainerId &&\n container.organizationId === auth.organizationId\n );\n}\n\n/**\n * Whether the session root may absorb the pre-login local roots. The unsigned\n * login answer only names the root; the merge target must also be the verified\n * root whose epoch-1 `container.create` the session user signed. A row persisted\n * earlier as an ordinary shared container (another user's root this device once\n * hydrated) never passed that check for this session, so the creator is checked\n * here, at the reconciliation boundary itself, before any local content is\n * re-parented. The role comes only from the cache remote hydration fills when\n * it verifies the destination: this gate never fetches, so a local refresh stays\n * independent of the network. Without a cached role the merge is left pending\n * (no incident) until hydration verifies the root and reconciles from the\n * cache. A different creator is a `signer_mismatch` incident and never a merge;\n * the refusal is the \"no merge\" outcome, so the refresh that carried it\n * completes with the local content left in place.\n */\nexport async function isVerifiedLocalRootReconciliationTarget(input: {\n remoteRootState: ContainerState;\n state: RemoteContainerHydrationState;\n}): Promise<boolean> {\n const { remoteRootState, state } = input;\n const { container } = remoteRootState;\n const runtime = state.runtime;\n if (!isSessionRootState(remoteRootState, state)) return false;\n const role = cachedDestinationRole(runtime.infra.execSql, container);\n if (!role) return false;\n try {\n if (role.parentId !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"session root reconciliation target is not a verified root\",\n );\n }\n assertRootCreatedBySessionUser(role, runtime);\n return true;\n } catch (error) {\n const reported = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: container.id,\n objectKind: \"container\",\n operation: \"container.root.reconcile\",\n organizationId: container.organizationId,\n },\n );\n if (!reported) throw error;\n return false;\n }\n}\n"]}
|
|
@@ -4,7 +4,7 @@ import { assertContainerChildPathFits } from "../../../../data/containers/shared
|
|
|
4
4
|
import { buildContainerCreateBody, buildContainerCreateKeyEpoch, buildParentRecipientTargets, deriveContainerCreateManifest, resolveContainerKekEpochId, signContainerCreateEvent, } from "../../../../data/containers/shared/events.js";
|
|
5
5
|
import { acknowledgeContainerMutation } from "../../../../data/containers/shared/mutationAcknowledgement.js";
|
|
6
6
|
import { containerManifestRef, getParentCreateContext, readContainerState, wrapContainerKeyToManagedPrincipal, wrapContainerKeyToParent, } from "../../../../data/containers/shared/projection.js";
|
|
7
|
-
import { assertContainerKekPathCurrent } from "../../../../data/documents/shared/containerKek/
|
|
7
|
+
import { assertContainerKekPathCurrent } from "../../../../data/documents/shared/containerKek/index.js";
|
|
8
8
|
import { unwrapContainerKekPath } from "../../../../data/documents/shared/projection/index.js";
|
|
9
9
|
import { projectionVerificationOptions, } from "../../../../data/documents/shared/types.js";
|
|
10
10
|
import { readCanonicalRecord } from "../../../../data/keying/canonicalJson.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n type ContainerCreateAccessEventBody,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n deriveContainerKekWrappingPublicKey,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../../data/containers/shared/containerPathLimits\";\nimport {\n buildContainerCreateBody,\n buildContainerCreateKeyEpoch,\n buildParentRecipientTargets,\n deriveContainerCreateManifest,\n resolveContainerKekEpochId,\n signContainerCreateEvent,\n} from \"../../../../data/containers/shared/events\";\nimport { acknowledgeContainerMutation } from \"../../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n containerManifestRef,\n getParentCreateContext,\n readContainerState,\n wrapContainerKeyToManagedPrincipal,\n wrapContainerKeyToParent,\n} from \"../../../../data/containers/shared/projection\";\nimport type {\n BuildContainerCreatePlanInput,\n ContainerCreatePlan,\n ContainerCreatePlanContext,\n ContainerMutationAuthor,\n CreateRemoteContainerResult,\n MaterializedContainerCreatePlan,\n} from \"../../../../data/containers/shared/types\";\nimport { assertContainerKekPathCurrent } from \"../../../../data/documents/shared/containerKek/containerKekCurrency\";\nimport { unwrapContainerKekPath } from \"../../../../data/documents/shared/projection\";\nimport {\n type ProjectionVerificationOptions,\n projectionVerificationOptions,\n} from \"../../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../../data/keying/canonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../../data/principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../../../data/sqlite/sqlSchema\";\nimport { PrincipalPolicyRepairBudget } from \"../../../principals/policyRepairBudget\";\nimport { containerMutationRequestCore } from \"../mutationRequestCore\";\nimport { requireUnwrappedKek } from \"../rotation/rotationContext\";\nimport {\n type ContainerCreateRepairState,\n type RemoteContainerCreateInput,\n repairContainerCreateFailure,\n submitRemoteContainerCreate,\n} from \"./createSubmission\";\n\nfunction assertContainerCreatePlanInput(input: {\n containerKey: Uint8Array;\n}): void {\n if (input.containerKey.byteLength !== 32) {\n throw new Error(\"Container KEK material must be 32 bytes\");\n }\n // The child container's organization is derived from the parent projection\n // (see buildContainerCreatePlan), so it always matches the parent by\n // construction — a member writing under another org's shared root is the\n // expected case, not an error. The author supplies only the signer identity.\n}\n\nfunction buildContainerCreateRequest(input: {\n body: ContainerCreateAccessEventBody;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n parentKek: ContainerKekResponse;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"create\", {\n ...input,\n userRecipientKeys: [],\n }),\n previousManifestRef: null,\n parentContainerPathRefs:\n input.parentProjection.path.map(containerManifestRef),\n predecessorBridge: null,\n keyring: null,\n parentKekState: readCanonicalRecord(\n input.parentKek,\n \"Container create parent KEK state\",\n ),\n };\n}\n\nasync function resolveContainerCreatePlanContext(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlanContext> {\n assertContainerCreatePlanInput(input);\n assertContainerKekPathCurrent(input.parentProjection.containerKeks);\n const containerId = input.containerId ?? crypto.randomUUID();\n\n return {\n ...input,\n containerId,\n containerKeyPublicKey: await deriveContainerKekWrappingPublicKey({\n containerId,\n keyMaterial: input.containerKey,\n }),\n containerKeyEpochId: await resolveContainerKekEpochId({\n containerId,\n keyEpoch: 1,\n keyMaterial: input.containerKey,\n override: input.containerKeyEpochId,\n }),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parent: getParentCreateContext(input.parentProjection),\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n}\n\nfunction buildChildContainerCreateBody(\n context: ContainerCreatePlanContext,\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"],\n): ContainerCreateAccessEventBody {\n const baseBody = buildContainerCreateBody({\n systemSlot: context.systemSlot ?? null,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId: context.parentProjection.containerId,\n parentManifestHash: context.parent.manifest.manifestHash,\n });\n if (!managedGrant) {\n return baseBody;\n }\n return {\n ...baseBody,\n directGrants: [\n {\n accessLevel: managedGrant.accessLevel,\n subjectId: managedGrant.principalHead.principalId,\n subjectType: managedGrant.principalHead.principalType,\n },\n ],\n referencedPrincipalHeads: [managedGrant.principalHead],\n };\n}\n\n// A managed-principal grant adds a second recipient: the group/organization key\n// wrap alongside the parent-inheritance wrap. The server derives both targets\n// (parent inheritance + directGrant) and requires exactly one wrap each; target\n// order is irrelevant since the key-target hash is normalized.\nasync function buildChildContainerWrapsAndTargets(input: {\n context: ContainerCreatePlanContext;\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n manifestHash: string;\n}): Promise<{\n recipientTargets: ContainerKekRecipientTarget[];\n wraps: ContainerKeyWrap[];\n}> {\n const { context, managedGrant, manifestHash } = input;\n const parentPublicKey = readContainerState(\n context.parent.manifest,\n ).containerKeyPublicKey;\n if (!parentPublicKey)\n throw new Error(\"Container parent wrapping public key is missing\");\n const parentWrap = await wrapContainerKeyToParent({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n parentKek: context.parent.kek,\n parentPublicKey,\n });\n const parentTargets = buildParentRecipientTargets(context.parent.kek);\n if (!managedGrant) {\n return { recipientTargets: parentTargets, wraps: [parentWrap] };\n }\n const managedRecipient = await wrapContainerKeyToManagedPrincipal({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n principalEncapsulationPublicKey:\n managedGrant.principalEncapsulationPublicKey,\n principalHead: managedGrant.principalHead,\n });\n return {\n recipientTargets: [...parentTargets, managedRecipient.recipientTarget],\n wraps: [parentWrap, managedRecipient.wrap],\n };\n}\n\nexport async function buildContainerCreatePlan(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlan> {\n const context = await resolveContainerCreatePlanContext(input);\n const parentContainerId = context.parentProjection.containerId;\n const parentManifestHash = context.parent.manifest.manifestHash;\n const managedGrant = input.managedPrincipalGrant;\n const body = buildChildContainerCreateBody(context, managedGrant);\n // The new container belongs to the parent's organization, not the author's.\n // A member writing under another org's shared root mints a container owned by\n // that org; the author only supplies the signer identity.\n const organizationId = context.parentProjection.organizationId;\n const { event, eventHash } = await signContainerCreateEvent({\n author: context.author,\n body,\n containerId: context.containerId,\n eventId: context.eventId,\n organizationId,\n parentPath: context.parentProjection.path,\n signedAt: context.signedAt,\n });\n const { manifest, manifestHash, state } = await deriveContainerCreateManifest(\n {\n systemSlot: context.systemSlot ?? null,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n directGrants: body.directGrants,\n eventHash,\n metadataDocumentId: context.metadataDocumentId,\n organizationId,\n parentContainerId,\n parentManifestHash,\n referencedPrincipalHeads: body.referencedPrincipalHeads,\n },\n );\n const keyEpoch = buildContainerCreateKeyEpoch({\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n eventHash,\n manifestHash,\n parentContainerKeyEpochId: context.parent.kek.containerKeyEpochId,\n });\n const { recipientTargets, wraps } = await buildChildContainerWrapsAndTargets({\n context,\n managedGrant,\n manifestHash,\n });\n const keyTargetHash =\n await computeContainerKekRecipientTargetHash(recipientTargets);\n const keyEpochHash = await computeContainerKeyEpochHash(keyEpoch);\n return {\n body,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n event,\n eventHash,\n keyEpoch,\n keyEpochHash,\n keyTargetHash,\n manifest,\n manifestHash,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId,\n parentManifestHash,\n recipientTargets,\n request: buildContainerCreateRequest({\n body,\n event,\n keyEpoch,\n manifest,\n manifestHash,\n parentKek: context.parent.kek,\n parentProjection: context.parentProjection,\n principalPolicies: context.principalPolicies ?? [],\n wraps,\n }),\n state,\n wraps,\n };\n}\n\nexport async function buildMaterializedContainerCreatePlan(\n input: {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n managedPrincipalGrant?: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n parentSecretKey: Uint8Array;\n signedAt?: string | undefined;\n // Fetches the parent path's referenced principal policies on demand when\n // they are not cached locally — lets a member create under another org's\n // shared root without having first hydrated that org's group policy.\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedContainerCreatePlan> {\n const containerKey =\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32));\n\n const parentKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.parentProjection,\n secretKey: input.parentSecretKey,\n ...projectionVerificationOptions(input),\n });\n const parent = getParentCreateContext(input.parentProjection);\n requireUnwrappedKek(parentKeksByEpochId, parent.kek, \"Container parent\");\n // Checked on the path verification just accepted, never on the raw response.\n assertContainerChildPathFits(input.parentProjection.path);\n const principalPolicies = input.resolveProjectionUserKey\n ? await collectContainerWriterProjectionPrincipalPolicies({\n execSql: input.execSql,\n projection: input.parentProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })\n : [];\n if (input.resolveProjectionUserKey) {\n assertContainerAuthorAccess({\n author: {\n ...input.author,\n organizationId: input.parentProjection.organizationId,\n },\n projection: input.parentProjection,\n principalPolicies,\n minimumAccess: input.systemSlot ? \"admin\" : \"write\",\n });\n }\n const plan = await buildContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey,\n containerKeyEpochId: input.containerKeyEpochId,\n eventId: input.eventId,\n managedPrincipalGrant: input.managedPrincipalGrant,\n metadataDocumentId: input.metadataDocumentId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n principalPolicies,\n signedAt: input.signedAt,\n });\n\n return {\n containerKey,\n plan,\n };\n}\n\nexport { childContainerWriterProjectionFromCreatePlan } from \"./createProjection\";\n\nasync function createRemoteContainerWithRepairs(input: {\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly eventId: string;\n readonly metadataDocumentId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly request: RemoteContainerCreateInput;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly signedAt: string;\n}): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n let parentProjection = input.parentProjection;\n const repairState: ContainerCreateRepairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const materializedPlan = await buildMaterializedContainerCreatePlan({\n author: input.request.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n containerKeyEpochId: input.request.containerKeyEpochId,\n eventId: input.eventId,\n execSql: input.request.execSql,\n metadataDocumentId: input.metadataDocumentId,\n parentProjection,\n parentSecretKey: input.request.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.request.stillCurrent,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n });\n const submitted = await submitRemoteContainerCreate({\n apiClient: input.request.apiClient,\n plan: materializedPlan.plan,\n stillCurrent: input.request.stillCurrent,\n });\n if (!submitted) return null;\n if (!submitted.ok) {\n const repair = await repairContainerCreateFailure({\n apiClient: input.request.apiClient,\n failure: submitted,\n parentContainerId: input.request.parentContainerId,\n parentProjection,\n state: repairState,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n stillCurrent: input.request.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") {\n return null;\n }\n submitted.report();\n return null;\n }\n const acknowledged = await acknowledgeContainerMutation({\n execSql: input.request.execSql,\n plan: materializedPlan.plan,\n response: submitted.response,\n stillCurrent: input.request.stillCurrent,\n });\n return {\n acknowledged,\n result: {\n containerKey: materializedPlan.containerKey,\n containerId: submitted.response.containerId,\n metadataDocumentId: materializedPlan.plan.metadataDocumentId,\n plan: materializedPlan.plan,\n response: submitted.response,\n },\n };\n }\n}\n\nasync function createRemoteContainerOutcome(\n input: RemoteContainerCreateInput,\n): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container create\",\n );\n const parentProjection =\n input.parentProjection ??\n (await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n ));\n if (!parentProjection) {\n return null;\n }\n return nullOnProjectionVerificationCancellation(() =>\n createRemoteContainerWithRepairs({\n containerId: input.containerId ?? crypto.randomUUID(),\n containerKey:\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32)),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parentProjection,\n request: input,\n resolveProjectionUserKey,\n signedAt: input.signedAt ?? new Date().toISOString(),\n }),\n );\n}\n\nexport async function createRemoteContainer(\n input: RemoteContainerCreateInput,\n): Promise<CreateRemoteContainerResult | null> {\n const outcome = await createRemoteContainerOutcome(input);\n return outcome?.acknowledged && input.stillCurrent?.() !== false\n ? outcome.result\n : null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n type ContainerCreateAccessEventBody,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n deriveContainerKekWrappingPublicKey,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../../data/containers/shared/containerPathLimits\";\nimport {\n buildContainerCreateBody,\n buildContainerCreateKeyEpoch,\n buildParentRecipientTargets,\n deriveContainerCreateManifest,\n resolveContainerKekEpochId,\n signContainerCreateEvent,\n} from \"../../../../data/containers/shared/events\";\nimport { acknowledgeContainerMutation } from \"../../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n containerManifestRef,\n getParentCreateContext,\n readContainerState,\n wrapContainerKeyToManagedPrincipal,\n wrapContainerKeyToParent,\n} from \"../../../../data/containers/shared/projection\";\nimport type {\n BuildContainerCreatePlanInput,\n ContainerCreatePlan,\n ContainerCreatePlanContext,\n ContainerMutationAuthor,\n CreateRemoteContainerResult,\n MaterializedContainerCreatePlan,\n} from \"../../../../data/containers/shared/types\";\nimport { assertContainerKekPathCurrent } from \"../../../../data/documents/shared/containerKek\";\nimport { unwrapContainerKekPath } from \"../../../../data/documents/shared/projection\";\nimport {\n type ProjectionVerificationOptions,\n projectionVerificationOptions,\n} from \"../../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../../data/keying/canonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../../data/principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../../../data/sqlite/sqlSchema\";\nimport { PrincipalPolicyRepairBudget } from \"../../../principals/policyRepairBudget\";\nimport { containerMutationRequestCore } from \"../mutationRequestCore\";\nimport { requireUnwrappedKek } from \"../rotation/rotationContext\";\nimport {\n type ContainerCreateRepairState,\n type RemoteContainerCreateInput,\n repairContainerCreateFailure,\n submitRemoteContainerCreate,\n} from \"./createSubmission\";\n\nfunction assertContainerCreatePlanInput(input: {\n containerKey: Uint8Array;\n}): void {\n if (input.containerKey.byteLength !== 32) {\n throw new Error(\"Container KEK material must be 32 bytes\");\n }\n // The child container's organization is derived from the parent projection\n // (see buildContainerCreatePlan), so it always matches the parent by\n // construction — a member writing under another org's shared root is the\n // expected case, not an error. The author supplies only the signer identity.\n}\n\nfunction buildContainerCreateRequest(input: {\n body: ContainerCreateAccessEventBody;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n parentKek: ContainerKekResponse;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"create\", {\n ...input,\n userRecipientKeys: [],\n }),\n previousManifestRef: null,\n parentContainerPathRefs:\n input.parentProjection.path.map(containerManifestRef),\n predecessorBridge: null,\n keyring: null,\n parentKekState: readCanonicalRecord(\n input.parentKek,\n \"Container create parent KEK state\",\n ),\n };\n}\n\nasync function resolveContainerCreatePlanContext(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlanContext> {\n assertContainerCreatePlanInput(input);\n assertContainerKekPathCurrent(input.parentProjection.containerKeks);\n const containerId = input.containerId ?? crypto.randomUUID();\n\n return {\n ...input,\n containerId,\n containerKeyPublicKey: await deriveContainerKekWrappingPublicKey({\n containerId,\n keyMaterial: input.containerKey,\n }),\n containerKeyEpochId: await resolveContainerKekEpochId({\n containerId,\n keyEpoch: 1,\n keyMaterial: input.containerKey,\n override: input.containerKeyEpochId,\n }),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parent: getParentCreateContext(input.parentProjection),\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n}\n\nfunction buildChildContainerCreateBody(\n context: ContainerCreatePlanContext,\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"],\n): ContainerCreateAccessEventBody {\n const baseBody = buildContainerCreateBody({\n systemSlot: context.systemSlot ?? null,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId: context.parentProjection.containerId,\n parentManifestHash: context.parent.manifest.manifestHash,\n });\n if (!managedGrant) {\n return baseBody;\n }\n return {\n ...baseBody,\n directGrants: [\n {\n accessLevel: managedGrant.accessLevel,\n subjectId: managedGrant.principalHead.principalId,\n subjectType: managedGrant.principalHead.principalType,\n },\n ],\n referencedPrincipalHeads: [managedGrant.principalHead],\n };\n}\n\n// A managed-principal grant adds a second recipient: the group/organization key\n// wrap alongside the parent-inheritance wrap. The server derives both targets\n// (parent inheritance + directGrant) and requires exactly one wrap each; target\n// order is irrelevant since the key-target hash is normalized.\nasync function buildChildContainerWrapsAndTargets(input: {\n context: ContainerCreatePlanContext;\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n manifestHash: string;\n}): Promise<{\n recipientTargets: ContainerKekRecipientTarget[];\n wraps: ContainerKeyWrap[];\n}> {\n const { context, managedGrant, manifestHash } = input;\n const parentPublicKey = readContainerState(\n context.parent.manifest,\n ).containerKeyPublicKey;\n if (!parentPublicKey)\n throw new Error(\"Container parent wrapping public key is missing\");\n const parentWrap = await wrapContainerKeyToParent({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n parentKek: context.parent.kek,\n parentPublicKey,\n });\n const parentTargets = buildParentRecipientTargets(context.parent.kek);\n if (!managedGrant) {\n return { recipientTargets: parentTargets, wraps: [parentWrap] };\n }\n const managedRecipient = await wrapContainerKeyToManagedPrincipal({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n principalEncapsulationPublicKey:\n managedGrant.principalEncapsulationPublicKey,\n principalHead: managedGrant.principalHead,\n });\n return {\n recipientTargets: [...parentTargets, managedRecipient.recipientTarget],\n wraps: [parentWrap, managedRecipient.wrap],\n };\n}\n\nexport async function buildContainerCreatePlan(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlan> {\n const context = await resolveContainerCreatePlanContext(input);\n const parentContainerId = context.parentProjection.containerId;\n const parentManifestHash = context.parent.manifest.manifestHash;\n const managedGrant = input.managedPrincipalGrant;\n const body = buildChildContainerCreateBody(context, managedGrant);\n // The new container belongs to the parent's organization, not the author's.\n // A member writing under another org's shared root mints a container owned by\n // that org; the author only supplies the signer identity.\n const organizationId = context.parentProjection.organizationId;\n const { event, eventHash } = await signContainerCreateEvent({\n author: context.author,\n body,\n containerId: context.containerId,\n eventId: context.eventId,\n organizationId,\n parentPath: context.parentProjection.path,\n signedAt: context.signedAt,\n });\n const { manifest, manifestHash, state } = await deriveContainerCreateManifest(\n {\n systemSlot: context.systemSlot ?? null,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n directGrants: body.directGrants,\n eventHash,\n metadataDocumentId: context.metadataDocumentId,\n organizationId,\n parentContainerId,\n parentManifestHash,\n referencedPrincipalHeads: body.referencedPrincipalHeads,\n },\n );\n const keyEpoch = buildContainerCreateKeyEpoch({\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n eventHash,\n manifestHash,\n parentContainerKeyEpochId: context.parent.kek.containerKeyEpochId,\n });\n const { recipientTargets, wraps } = await buildChildContainerWrapsAndTargets({\n context,\n managedGrant,\n manifestHash,\n });\n const keyTargetHash =\n await computeContainerKekRecipientTargetHash(recipientTargets);\n const keyEpochHash = await computeContainerKeyEpochHash(keyEpoch);\n return {\n body,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n event,\n eventHash,\n keyEpoch,\n keyEpochHash,\n keyTargetHash,\n manifest,\n manifestHash,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId,\n parentManifestHash,\n recipientTargets,\n request: buildContainerCreateRequest({\n body,\n event,\n keyEpoch,\n manifest,\n manifestHash,\n parentKek: context.parent.kek,\n parentProjection: context.parentProjection,\n principalPolicies: context.principalPolicies ?? [],\n wraps,\n }),\n state,\n wraps,\n };\n}\n\nexport async function buildMaterializedContainerCreatePlan(\n input: {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n managedPrincipalGrant?: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n parentSecretKey: Uint8Array;\n signedAt?: string | undefined;\n // Fetches the parent path's referenced principal policies on demand when\n // they are not cached locally — lets a member create under another org's\n // shared root without having first hydrated that org's group policy.\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedContainerCreatePlan> {\n const containerKey =\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32));\n\n const parentKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.parentProjection,\n secretKey: input.parentSecretKey,\n ...projectionVerificationOptions(input),\n });\n const parent = getParentCreateContext(input.parentProjection);\n requireUnwrappedKek(parentKeksByEpochId, parent.kek, \"Container parent\");\n // Checked on the path verification just accepted, never on the raw response.\n assertContainerChildPathFits(input.parentProjection.path);\n const principalPolicies = input.resolveProjectionUserKey\n ? await collectContainerWriterProjectionPrincipalPolicies({\n execSql: input.execSql,\n projection: input.parentProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })\n : [];\n if (input.resolveProjectionUserKey) {\n assertContainerAuthorAccess({\n author: {\n ...input.author,\n organizationId: input.parentProjection.organizationId,\n },\n projection: input.parentProjection,\n principalPolicies,\n minimumAccess: input.systemSlot ? \"admin\" : \"write\",\n });\n }\n const plan = await buildContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey,\n containerKeyEpochId: input.containerKeyEpochId,\n eventId: input.eventId,\n managedPrincipalGrant: input.managedPrincipalGrant,\n metadataDocumentId: input.metadataDocumentId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n principalPolicies,\n signedAt: input.signedAt,\n });\n\n return {\n containerKey,\n plan,\n };\n}\n\nexport { childContainerWriterProjectionFromCreatePlan } from \"./createProjection\";\n\nasync function createRemoteContainerWithRepairs(input: {\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly eventId: string;\n readonly metadataDocumentId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly request: RemoteContainerCreateInput;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly signedAt: string;\n}): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n let parentProjection = input.parentProjection;\n const repairState: ContainerCreateRepairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const materializedPlan = await buildMaterializedContainerCreatePlan({\n author: input.request.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n containerKeyEpochId: input.request.containerKeyEpochId,\n eventId: input.eventId,\n execSql: input.request.execSql,\n metadataDocumentId: input.metadataDocumentId,\n parentProjection,\n parentSecretKey: input.request.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.request.stillCurrent,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n });\n const submitted = await submitRemoteContainerCreate({\n apiClient: input.request.apiClient,\n plan: materializedPlan.plan,\n stillCurrent: input.request.stillCurrent,\n });\n if (!submitted) return null;\n if (!submitted.ok) {\n const repair = await repairContainerCreateFailure({\n apiClient: input.request.apiClient,\n failure: submitted,\n parentContainerId: input.request.parentContainerId,\n parentProjection,\n state: repairState,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n stillCurrent: input.request.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") {\n return null;\n }\n submitted.report();\n return null;\n }\n const acknowledged = await acknowledgeContainerMutation({\n execSql: input.request.execSql,\n plan: materializedPlan.plan,\n response: submitted.response,\n stillCurrent: input.request.stillCurrent,\n });\n return {\n acknowledged,\n result: {\n containerKey: materializedPlan.containerKey,\n containerId: submitted.response.containerId,\n metadataDocumentId: materializedPlan.plan.metadataDocumentId,\n plan: materializedPlan.plan,\n response: submitted.response,\n },\n };\n }\n}\n\nasync function createRemoteContainerOutcome(\n input: RemoteContainerCreateInput,\n): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container create\",\n );\n const parentProjection =\n input.parentProjection ??\n (await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n ));\n if (!parentProjection) {\n return null;\n }\n return nullOnProjectionVerificationCancellation(() =>\n createRemoteContainerWithRepairs({\n containerId: input.containerId ?? crypto.randomUUID(),\n containerKey:\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32)),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parentProjection,\n request: input,\n resolveProjectionUserKey,\n signedAt: input.signedAt ?? new Date().toISOString(),\n }),\n );\n}\n\nexport async function createRemoteContainer(\n input: RemoteContainerCreateInput,\n): Promise<CreateRemoteContainerResult | null> {\n const outcome = await createRemoteContainerOutcome(input);\n return outcome?.acknowledged && input.stillCurrent?.() !== false\n ? outcome.result\n : null;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createContainerKekPredecessorBridge, KeyingVerificationError, normalizeContainerKekKeyring, openContainerKekKeyring, sealContainerKekKeyring, } from "../../../../internal/crypto/index.js";
|
|
2
2
|
import { resolveContainerKekEpochId } from "../../../../data/containers/shared/events.js";
|
|
3
|
-
import { verifyContainerKekEntries } from "../../../../data/documents/shared/containerKek/
|
|
3
|
+
import { verifyContainerKekEntries } from "../../../../data/documents/shared/containerKek/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* A rotation must never launder history it did not verify: an
|
|
6
6
|
* authenticated-but-poisoned keyring (sealed by a prior authorized writer
|