@tearleads/client-sdk 0.1.112 → 0.1.114

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.
Files changed (70) hide show
  1. package/data/persistence/container-contents/containerContentsPersistence.js +3 -8
  2. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  3. package/data/persistence/container-contents/containerHydrationPersistence.js +15 -5
  4. package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
  5. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +8 -2
  6. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  7. package/data/persistence/container-contents/containerMetadataRows.js +34 -2
  8. package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
  9. package/data/persistence/container-contents/containerPersistence.d.ts +231 -0
  10. package/data/persistence/container-contents/containerPersistence.js +20 -16
  11. package/data/persistence/container-contents/containerPersistence.js.map +1 -1
  12. package/data/persistence/container-contents/containerRecoveryPersistence.js +15 -13
  13. package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
  14. package/data/persistence/container-contents/documentContainerProjectionPersistence.js +10 -2
  15. package/data/persistence/container-contents/documentContainerProjectionPersistence.js.map +1 -1
  16. package/data/persistence/container-contents/documentMoveIntentPersistence.js +29 -5
  17. package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
  18. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js +1 -1
  19. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js.map +1 -1
  20. package/data/persistence/documents/internal/documentMutationPersistence.js +15 -15
  21. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  22. package/data/persistence/documents/internal/documentRows.js +26 -10
  23. package/data/persistence/documents/internal/documentRows.js.map +1 -1
  24. package/data/persistence/documents/internal/rowQueryPersistence.js +52 -27
  25. package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
  26. package/data/persistence/documents/records/documentHistoryPersistence.js +17 -11
  27. package/data/persistence/documents/records/documentHistoryPersistence.js.map +1 -1
  28. package/data/persistence/keyingCheckpoints/keyingCheckpointAdvancePersistence.js +16 -11
  29. package/data/persistence/keyingCheckpoints/keyingCheckpointAdvancePersistence.js.map +1 -1
  30. package/data/persistence/keyingCheckpoints/keyingCheckpointPersistence.js +150 -2
  31. package/data/persistence/keyingCheckpoints/keyingCheckpointPersistence.js.map +1 -1
  32. package/data/persistence/keyingCheckpoints/principalAuthorizationCheckpoints.js +3 -2
  33. package/data/persistence/keyingCheckpoints/principalAuthorizationCheckpoints.js.map +1 -1
  34. package/data/persistence/principalHistory/principalHistoryEvidencePersistence.d.ts +14 -1
  35. package/data/persistence/principalHistory/principalHistoryEvidencePersistence.js +128 -34
  36. package/data/persistence/principalHistory/principalHistoryEvidencePersistence.js.map +1 -1
  37. package/data/persistence/principalHistory/principalHistoryNodeRetention.js +64 -24
  38. package/data/persistence/principalHistory/principalHistoryNodeRetention.js.map +1 -1
  39. package/data/persistence/principalHistory/principalHistoryPrefixPersistence.js +6 -1
  40. package/data/persistence/principalHistory/principalHistoryPrefixPersistence.js.map +1 -1
  41. package/data/persistence/principalHistory/principalHistoryRootOwnership.d.ts +45 -0
  42. package/data/persistence/principalHistory/principalHistoryRootOwnership.js +41 -4
  43. package/data/persistence/principalHistory/principalHistoryRootOwnership.js.map +1 -1
  44. package/data/persistence/principalHistory/principalHistoryStagePersistence.js +12 -8
  45. package/data/persistence/principalHistory/principalHistoryStagePersistence.js.map +1 -1
  46. package/data/persistence/principalKeys/principalGrantRetirementPersistence.js +35 -1
  47. package/data/persistence/principalKeys/principalGrantRetirementPersistence.js.map +1 -1
  48. package/data/persistence/principalPolicy/principalPolicyOrganizationPersistence.js +62 -1
  49. package/data/persistence/principalPolicy/principalPolicyOrganizationPersistence.js.map +1 -1
  50. package/data/persistence/trustedUserIdentityPinPersistence.js +46 -23
  51. package/data/persistence/trustedUserIdentityPinPersistence.js.map +1 -1
  52. package/data/persistence/verifiedManifestBundlePersistence.js +27 -10
  53. package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -1
  54. package/data/sqlite/schema/principalHistoryNodeRetentionSchema.d.ts +222 -0
  55. package/package.json +1 -1
  56. package/workflows/container-contents/documentQueries/index.js +21 -6
  57. package/workflows/container-contents/documentQueries/index.js.map +1 -1
  58. package/workflows/documents/documentMutationCommit.js +11 -12
  59. package/workflows/documents/documentMutationCommit.js.map +1 -1
  60. package/workflows/documents/documentMutationPreparation.d.ts +1 -0
  61. package/workflows/documents/documentMutationPreparation.js +1 -0
  62. package/workflows/documents/documentMutationPreparation.js.map +1 -1
  63. package/workflows/documents/documentPersistGuards.js +24 -0
  64. package/workflows/documents/documentPersistGuards.js.map +1 -1
  65. package/workflows/principals/historyRecovery/loadRecoveredPrincipalHistoryPage.js +13 -12
  66. package/workflows/principals/historyRecovery/loadRecoveredPrincipalHistoryPage.js.map +1 -1
  67. package/workflows/principals/historyRecovery/principalHistoryRecoveryReferences.js +17 -19
  68. package/workflows/principals/historyRecovery/principalHistoryRecoveryReferences.js.map +1 -1
  69. package/workflows/principals/publicHistory/selectPublicPrincipalHistory.js +8 -10
  70. package/workflows/principals/publicHistory/selectPublicPrincipalHistory.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"documentMutationPreparation.js","sourceRoot":"","sources":["documentMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport {\n type DocumentSyncPullContinuation,\n documentSyncPullContinuationsEqual,\n} from \"../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../data/keying/accessLevel\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { mergePersistedDocumentHistory } from \"./historyContent\";\n\nexport interface ExpectedDocumentSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: StoredDocumentRecord;\n}\n\nexport interface PrepareDocumentMutationInput {\n currentDoc: Parameters<typeof mergePersistedDocumentHistory>[0][\"doc\"];\n currentRecord: StoredDocumentRecord | null;\n expectedSyncState?: ExpectedDocumentSyncState | undefined;\n historyCheckpoint?:\n | {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n pruneCoveredLocalState: boolean;\n snapshot: string;\n }\n | undefined;\n historyUpdateOrigin?: \"local\" | \"remote\" | undefined;\n historyUpdates?: readonly string[] | undefined;\n localId: string;\n persistence: DocumentsPersistence;\n}\n\nfunction sameNullableDocumentValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function documentSyncSecurityContextMatches(\n current: StoredDocumentRecord | null,\n expected: StoredDocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.containerId === expected.containerId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableDocumentValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n (current.effectiveAccessLevel ?? null) ===\n (expected.effectiveAccessLevel ?? null) &&\n sameNullableDocumentValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableDocumentValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableDocumentValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nfunction patchSpecifiesContainer(\n patch: Partial<StoredDocumentRecord>,\n): boolean {\n return Object.hasOwn(patch, \"containerId\");\n}\n\nfunction documentSyncStateDiffers(\n current: StoredDocumentRecord,\n cached: StoredDocumentRecord,\n): boolean {\n return (\n !sameNullableDocumentValue(current.lastCommitLsn, cached.lastCommitLsn) ||\n current.snapshotEndVersion !== cached.snapshotEndVersion ||\n !sameNullableDocumentValue(\n current.pendingBaseVersion,\n cached.pendingBaseVersion,\n ) ||\n !documentSyncPullContinuationsEqual(\n current.pullContinuation,\n cached.pullContinuation,\n ) ||\n Boolean(current.pullContinuationRecoveryRequired) !==\n Boolean(cached.pullContinuationRecoveryRequired)\n );\n}\n\nfunction mergeMutationFrontiers(\n patch: Partial<StoredDocumentRecord>,\n durableRecord: StoredDocumentRecord,\n): Partial<StoredDocumentRecord> {\n const nextPatch = { ...patch };\n if (patch.snapshotEndVersion !== undefined) {\n nextPatch.snapshotEndVersion = mergeVersionVectors([\n durableRecord.snapshotEndVersion,\n patch.snapshotEndVersion,\n ]);\n }\n if (\n patch.pendingBaseVersion !== undefined &&\n patch.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion\n ) {\n nextPatch.pendingBaseVersion = mergeVersionVectors([\n durableRecord.pendingBaseVersion,\n patch.pendingBaseVersion,\n ]);\n }\n return nextPatch;\n}\n\nfunction ordinarySaveNeedsHistoryRebase(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n if (\n input.expectedSyncState !== undefined ||\n durableRecord === null ||\n input.currentRecord === null\n ) {\n return false;\n }\n const cachedPendingBase = input.currentRecord.pendingBaseVersion;\n const durableCoversCachedPendingBase =\n !cachedPendingBase ||\n (durableRecord.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion !== undefined &&\n satisfiesVersionVector(\n durableRecord.pendingBaseVersion,\n cachedPendingBase,\n ));\n return (\n durableRecord.id === input.currentRecord.id &&\n durableRecord.documentId === input.currentRecord.documentId &&\n satisfiesVersionVector(\n durableRecord.snapshotEndVersion,\n input.currentRecord.snapshotEndVersion,\n ) &&\n durableCoversCachedPendingBase &&\n documentSyncStateDiffers(durableRecord, input.currentRecord)\n );\n}\n\nfunction ordinarySaveIdentityWasReplaced(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n (durableRecord.id !== input.currentRecord.id ||\n durableRecord.documentId !== input.currentRecord.documentId)\n );\n}\n\nfunction ordinarySaveWriteAccessWasRevoked(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n canWriteEffectiveAccessLevel(input.currentRecord.effectiveAccessLevel) &&\n !canWriteEffectiveAccessLevel(durableRecord.effectiveAccessLevel)\n );\n}\n\nfunction recoveryGenerationWasSuperseded(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.currentRecord !== null &&\n durableRecord !== null &&\n (input.currentRecord.recoveryGeneration ?? 0) !==\n (durableRecord.recoveryGeneration ?? 0)\n );\n}\n\nfunction resolveSyncSettlementState(\n current: StoredDocumentRecord | null,\n expected: ExpectedDocumentSyncState | undefined,\n): { pullContinuationSuperseded: boolean; securityContextMatches: boolean } {\n if (!expected) {\n return { pullContinuationSuperseded: false, securityContextMatches: true };\n }\n const securityContextMatches = documentSyncSecurityContextMatches(\n current,\n expected.record,\n );\n const contentFrontiersMatch =\n sameNullableDocumentValue(\n current?.lastCommitLsn,\n expected.record.lastCommitLsn,\n ) &&\n current?.snapshotEndVersion === expected.record.snapshotEndVersion &&\n sameNullableDocumentValue(\n current?.pendingBaseVersion,\n expected.record.pendingBaseVersion,\n );\n const recoveryStateMatches =\n Boolean(current?.pullContinuationRecoveryRequired) ===\n Boolean(expected.record.pullContinuationRecoveryRequired) &&\n (current?.recoveryGeneration ?? 0) ===\n (expected.record.recoveryGeneration ?? 0);\n return {\n pullContinuationSuperseded:\n !securityContextMatches ||\n !contentFrontiersMatch ||\n !recoveryStateMatches ||\n !documentSyncPullContinuationsEqual(\n current?.pullContinuation,\n expected.pullContinuation,\n ),\n securityContextMatches,\n };\n}\n\nexport async function prepareDocumentMutation(\n input: PrepareDocumentMutationInput,\n execSql: ExecSql,\n patch: Partial<StoredDocumentRecord>,\n) {\n const durableCurrentRecord = await input.persistence.loadDocument(\n execSql,\n input.localId,\n );\n const creationSuperseded =\n input.currentRecord === null && durableCurrentRecord !== null;\n const mutationCurrentRecord = durableCurrentRecord ?? input.currentRecord;\n const identityWasReplaced = ordinarySaveIdentityWasReplaced(\n input,\n durableCurrentRecord,\n );\n const writeAccessWasRevoked = ordinarySaveWriteAccessWasRevoked(\n input,\n durableCurrentRecord,\n );\n const recoveryWasSuperseded = recoveryGenerationWasSuperseded(\n input,\n durableCurrentRecord,\n );\n const { pullContinuationSuperseded, securityContextMatches } =\n creationSuperseded || identityWasReplaced || writeAccessWasRevoked\n ? { pullContinuationSuperseded: true, securityContextMatches: false }\n : recoveryWasSuperseded\n ? { pullContinuationSuperseded: true, securityContextMatches: true }\n : resolveSyncSettlementState(\n mutationCurrentRecord,\n input.expectedSyncState,\n );\n const ordinarySaveNeedsRebase = ordinarySaveNeedsHistoryRebase(\n input,\n durableCurrentRecord,\n );\n\n if (ordinarySaveNeedsRebase && securityContextMatches) {\n await mergePersistedDocumentHistory({\n doc: input.currentDoc,\n execSql,\n localId: input.localId,\n persistence: input.persistence,\n });\n }\n const mutationPatch = pullContinuationSuperseded\n ? {}\n : ordinarySaveNeedsRebase && durableCurrentRecord\n ? mergeMutationFrontiers(patch, durableCurrentRecord)\n : patch;\n const authoritativeContainer = patchSpecifiesContainer(mutationPatch)\n ? undefined\n : await input.persistence.loadDocumentContainer(execSql, input.localId);\n return {\n creationSuperseded,\n mutationCurrentRecord,\n pullContinuationSuperseded,\n resolvedPatch:\n authoritativeContainer === undefined\n ? mutationPatch\n : { ...mutationPatch, containerId: authoritativeContainer.containerId },\n securityContextMatches,\n };\n}\n"]}
1
+ {"version":3,"file":"documentMutationPreparation.js","sourceRoot":"","sources":["documentMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport {\n type DocumentSyncPullContinuation,\n documentSyncPullContinuationsEqual,\n} from \"../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../data/keying/accessLevel\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { mergePersistedDocumentHistory } from \"./historyContent\";\n\nexport interface ExpectedDocumentSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: StoredDocumentRecord;\n}\n\nexport interface PrepareDocumentMutationInput {\n currentDoc: Parameters<typeof mergePersistedDocumentHistory>[0][\"doc\"];\n currentRecord: StoredDocumentRecord | null;\n expectedSyncState?: ExpectedDocumentSyncState | undefined;\n historyCheckpoint?:\n | {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n pruneCoveredLocalState: boolean;\n snapshot: string;\n }\n | undefined;\n historyUpdateOrigin?: \"local\" | \"remote\" | undefined;\n historyUpdates?: readonly string[] | undefined;\n localId: string;\n persistence: DocumentsPersistence;\n}\n\nfunction sameNullableDocumentValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function documentSyncSecurityContextMatches(\n current: StoredDocumentRecord | null,\n expected: StoredDocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.containerId === expected.containerId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableDocumentValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n (current.effectiveAccessLevel ?? null) ===\n (expected.effectiveAccessLevel ?? null) &&\n sameNullableDocumentValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableDocumentValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableDocumentValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nfunction patchSpecifiesContainer(\n patch: Partial<StoredDocumentRecord>,\n): boolean {\n return Object.hasOwn(patch, \"containerId\");\n}\n\nfunction documentSyncStateDiffers(\n current: StoredDocumentRecord,\n cached: StoredDocumentRecord,\n): boolean {\n return (\n !sameNullableDocumentValue(current.lastCommitLsn, cached.lastCommitLsn) ||\n current.snapshotEndVersion !== cached.snapshotEndVersion ||\n !sameNullableDocumentValue(\n current.pendingBaseVersion,\n cached.pendingBaseVersion,\n ) ||\n !documentSyncPullContinuationsEqual(\n current.pullContinuation,\n cached.pullContinuation,\n ) ||\n Boolean(current.pullContinuationRecoveryRequired) !==\n Boolean(cached.pullContinuationRecoveryRequired)\n );\n}\n\nfunction mergeMutationFrontiers(\n patch: Partial<StoredDocumentRecord>,\n durableRecord: StoredDocumentRecord,\n): Partial<StoredDocumentRecord> {\n const nextPatch = { ...patch };\n if (patch.snapshotEndVersion !== undefined) {\n nextPatch.snapshotEndVersion = mergeVersionVectors([\n durableRecord.snapshotEndVersion,\n patch.snapshotEndVersion,\n ]);\n }\n if (\n patch.pendingBaseVersion !== undefined &&\n patch.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion\n ) {\n nextPatch.pendingBaseVersion = mergeVersionVectors([\n durableRecord.pendingBaseVersion,\n patch.pendingBaseVersion,\n ]);\n }\n return nextPatch;\n}\n\nfunction ordinarySaveNeedsHistoryRebase(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n if (\n input.expectedSyncState !== undefined ||\n durableRecord === null ||\n input.currentRecord === null\n ) {\n return false;\n }\n const cachedPendingBase = input.currentRecord.pendingBaseVersion;\n const durableCoversCachedPendingBase =\n !cachedPendingBase ||\n (durableRecord.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion !== undefined &&\n satisfiesVersionVector(\n durableRecord.pendingBaseVersion,\n cachedPendingBase,\n ));\n return (\n durableRecord.id === input.currentRecord.id &&\n durableRecord.documentId === input.currentRecord.documentId &&\n satisfiesVersionVector(\n durableRecord.snapshotEndVersion,\n input.currentRecord.snapshotEndVersion,\n ) &&\n durableCoversCachedPendingBase &&\n documentSyncStateDiffers(durableRecord, input.currentRecord)\n );\n}\n\nfunction ordinarySaveIdentityWasReplaced(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n (durableRecord.id !== input.currentRecord.id ||\n durableRecord.documentId !== input.currentRecord.documentId)\n );\n}\n\nfunction ordinarySaveWriteAccessWasRevoked(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n canWriteEffectiveAccessLevel(input.currentRecord.effectiveAccessLevel) &&\n !canWriteEffectiveAccessLevel(durableRecord.effectiveAccessLevel)\n );\n}\n\nfunction recoveryGenerationWasSuperseded(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.currentRecord !== null &&\n durableRecord !== null &&\n (input.currentRecord.recoveryGeneration ?? 0) !==\n (durableRecord.recoveryGeneration ?? 0)\n );\n}\n\nfunction resolveSyncSettlementState(\n current: StoredDocumentRecord | null,\n expected: ExpectedDocumentSyncState | undefined,\n): { pullContinuationSuperseded: boolean; securityContextMatches: boolean } {\n if (!expected) {\n return { pullContinuationSuperseded: false, securityContextMatches: true };\n }\n const securityContextMatches = documentSyncSecurityContextMatches(\n current,\n expected.record,\n );\n const contentFrontiersMatch =\n sameNullableDocumentValue(\n current?.lastCommitLsn,\n expected.record.lastCommitLsn,\n ) &&\n current?.snapshotEndVersion === expected.record.snapshotEndVersion &&\n sameNullableDocumentValue(\n current?.pendingBaseVersion,\n expected.record.pendingBaseVersion,\n );\n const recoveryStateMatches =\n Boolean(current?.pullContinuationRecoveryRequired) ===\n Boolean(expected.record.pullContinuationRecoveryRequired) &&\n (current?.recoveryGeneration ?? 0) ===\n (expected.record.recoveryGeneration ?? 0);\n return {\n pullContinuationSuperseded:\n !securityContextMatches ||\n !contentFrontiersMatch ||\n !recoveryStateMatches ||\n !documentSyncPullContinuationsEqual(\n current?.pullContinuation,\n expected.pullContinuation,\n ),\n securityContextMatches,\n };\n}\n\nexport async function prepareDocumentMutation(\n input: PrepareDocumentMutationInput,\n execSql: ExecSql,\n patch: Partial<StoredDocumentRecord>,\n) {\n const durableCurrentRecord = await input.persistence.loadDocument(\n execSql,\n input.localId,\n );\n const creationSuperseded =\n input.currentRecord === null && durableCurrentRecord !== null;\n const mutationCurrentRecord = durableCurrentRecord ?? input.currentRecord;\n const identityWasReplaced = ordinarySaveIdentityWasReplaced(\n input,\n durableCurrentRecord,\n );\n const writeAccessWasRevoked = ordinarySaveWriteAccessWasRevoked(\n input,\n durableCurrentRecord,\n );\n const recoveryWasSuperseded = recoveryGenerationWasSuperseded(\n input,\n durableCurrentRecord,\n );\n const { pullContinuationSuperseded, securityContextMatches } =\n creationSuperseded || identityWasReplaced || writeAccessWasRevoked\n ? { pullContinuationSuperseded: true, securityContextMatches: false }\n : recoveryWasSuperseded\n ? { pullContinuationSuperseded: true, securityContextMatches: true }\n : resolveSyncSettlementState(\n mutationCurrentRecord,\n input.expectedSyncState,\n );\n const ordinarySaveNeedsRebase = ordinarySaveNeedsHistoryRebase(\n input,\n durableCurrentRecord,\n );\n\n if (ordinarySaveNeedsRebase && securityContextMatches) {\n await mergePersistedDocumentHistory({\n doc: input.currentDoc,\n execSql,\n localId: input.localId,\n persistence: input.persistence,\n });\n }\n const mutationPatch = pullContinuationSuperseded\n ? {}\n : ordinarySaveNeedsRebase && durableCurrentRecord\n ? mergeMutationFrontiers(patch, durableCurrentRecord)\n : patch;\n const authoritativeContainer = patchSpecifiesContainer(mutationPatch)\n ? undefined\n : await input.persistence.loadDocumentContainer(execSql, input.localId);\n return {\n creationSuperseded,\n durableCurrentRecord,\n mutationCurrentRecord,\n pullContinuationSuperseded,\n resolvedPatch:\n authoritativeContainer === undefined\n ? mutationPatch\n : { ...mutationPatch, containerId: authoritativeContainer.containerId },\n securityContextMatches,\n };\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_DOCUMENT_KIND } from "../../data/documents/documentConstants.js";
2
+ import { prepareDocumentMutation, } from "./documentMutationPreparation.js";
2
3
  /** Refuse a queued update after another subsystem deleted its canonical row. */
3
4
  export async function refuseDeletedDocumentPersist(input) {
4
5
  const { currentRecord } = input;
@@ -12,4 +13,27 @@ export async function refuseDeletedDocumentPersist(input) {
12
13
  });
13
14
  });
14
15
  }
16
+ /**
17
+ * The preparation read doubles as the first look for a deleted row: only when
18
+ * it finds none does the guard open its own transaction, which reads again
19
+ * under the write lock before it refuses. A row it then finds (or an alias it
20
+ * must keep) is prepared afresh, as before the guard moved.
21
+ */
22
+ export async function prepareDocumentMutationUnlessDeleted(input) {
23
+ const { lockedExecSql, persistInput } = input;
24
+ const prepare = () => prepareDocumentMutation(persistInput, lockedExecSql, input.patch);
25
+ const mutation = await prepare();
26
+ if (!input.guard ||
27
+ persistInput.currentRecord === null ||
28
+ mutation.durableCurrentRecord !== null)
29
+ return mutation;
30
+ const refused = await refuseDeletedDocumentPersist({
31
+ currentRecord: persistInput.currentRecord,
32
+ documentProjectors: input.documentProjectors,
33
+ execSql: lockedExecSql,
34
+ localId: persistInput.localId,
35
+ persistence: persistInput.persistence,
36
+ });
37
+ return refused ? null : prepare();
38
+ }
15
39
  //# sourceMappingURL=documentPersistGuards.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"documentPersistGuards.js","sourceRoot":"","sources":["documentPersistGuards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAQ/E,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAMlD;IACC,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,KAAK,CAAC,WAAW,CAAC,8BAA8B,CACrD,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,UAAU,EACxB,KAAK,EAAE,kBAAkB,EAAE,EAAE;QAC3B,MAAM,KAAK,CAAC,kBAAkB,CAAC,oCAAoC,CAAC;YAClE,YAAY,EAAE,aAAa,CAAC,YAAY,IAAI,qBAAqB;YACjE,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { DocumentProjectorRegistry } from \"../../data/documents/documentKinds\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\n/** Refuse a queued update after another subsystem deleted its canonical row. */\nexport async function refuseDeletedDocumentPersist(input: {\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n execSql: ExecSql;\n localId: string;\n persistence: DocumentsPersistence;\n}): Promise<boolean> {\n const { currentRecord } = input;\n if (!currentRecord) return false;\n return input.persistence.deleteDocumentSideRowsIfAbsent(\n input.execSql,\n input.localId,\n currentRecord.documentId,\n async (transactionExecSql) => {\n await input.documentProjectors.deleteStoredDocumentClientProjection({\n documentKind: currentRecord.documentKind ?? DEFAULT_DOCUMENT_KIND,\n execSql: transactionExecSql,\n localId: input.localId,\n });\n },\n );\n}\n"]}
1
+ {"version":3,"file":"documentPersistGuards.js","sourceRoot":"","sources":["documentPersistGuards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAO/E,OAAO,EAEL,uBAAuB,GACxB,MAAM,+BAA+B,CAAC;AAEvC,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAMlD;IACC,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,KAAK,CAAC,WAAW,CAAC,8BAA8B,CACrD,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,UAAU,EACxB,KAAK,EAAE,kBAAkB,EAAE,EAAE;QAC3B,MAAM,KAAK,CAAC,kBAAkB,CAAC,oCAAoC,CAAC;YAClE,YAAY,EAAE,aAAa,CAAC,YAAY,IAAI,qBAAqB;YACjE,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,KAM1D;IACC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAC9C,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,uBAAuB,CAAC,YAAY,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAC;IACjC,IACE,CAAC,KAAK,CAAC,KAAK;QACZ,YAAY,CAAC,aAAa,KAAK,IAAI;QACnC,QAAQ,CAAC,oBAAoB,KAAK,IAAI;QAEtC,OAAO,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,MAAM,4BAA4B,CAAC;QACjD,aAAa,EAAE,YAAY,CAAC,aAAa;QACzC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,WAAW,EAAE,YAAY,CAAC,WAAW;KACtC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AACpC,CAAC","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { DocumentProjectorRegistry } from \"../../data/documents/documentKinds\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport {\n type PrepareDocumentMutationInput,\n prepareDocumentMutation,\n} from \"./documentMutationPreparation\";\n\n/** Refuse a queued update after another subsystem deleted its canonical row. */\nexport async function refuseDeletedDocumentPersist(input: {\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n execSql: ExecSql;\n localId: string;\n persistence: DocumentsPersistence;\n}): Promise<boolean> {\n const { currentRecord } = input;\n if (!currentRecord) return false;\n return input.persistence.deleteDocumentSideRowsIfAbsent(\n input.execSql,\n input.localId,\n currentRecord.documentId,\n async (transactionExecSql) => {\n await input.documentProjectors.deleteStoredDocumentClientProjection({\n documentKind: currentRecord.documentKind ?? DEFAULT_DOCUMENT_KIND,\n execSql: transactionExecSql,\n localId: input.localId,\n });\n },\n );\n}\n\n/**\n * The preparation read doubles as the first look for a deleted row: only when\n * it finds none does the guard open its own transaction, which reads again\n * under the write lock before it refuses. A row it then finds (or an alias it\n * must keep) is prepared afresh, as before the guard moved.\n */\nexport async function prepareDocumentMutationUnlessDeleted(input: {\n documentProjectors: DocumentProjectorRegistry;\n guard: boolean;\n lockedExecSql: ExecSql;\n patch: Partial<StoredDocumentRecord>;\n persistInput: PrepareDocumentMutationInput & { localId: string };\n}) {\n const { lockedExecSql, persistInput } = input;\n const prepare = () =>\n prepareDocumentMutation(persistInput, lockedExecSql, input.patch);\n const mutation = await prepare();\n if (\n !input.guard ||\n persistInput.currentRecord === null ||\n mutation.durableCurrentRecord !== null\n )\n return mutation;\n const refused = await refuseDeletedDocumentPersist({\n currentRecord: persistInput.currentRecord,\n documentProjectors: input.documentProjectors,\n execSql: lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n });\n return refused ? null : prepare();\n}\n"]}
@@ -2,7 +2,7 @@ import { KeyingVerificationError, verifyPrincipalPolicyHistoryReferences, } from
2
2
  import { isPrincipalPolicyStateChainEntryResponse, PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE, } from "../../../internal/validators/response/index.js";
3
3
  import { assertProjectionVerificationCurrent } from "../../../data/keyingProjectionVerification/types.js";
4
4
  import { loadPrincipalPolicyCheckpoint } from "../../../data/persistence/keyingCheckpoints/keyingCheckpointPersistence.js";
5
- import { loadPrincipalHistoryReference } from "../../../data/persistence/principalHistory/principalHistoryEvidencePersistence.js";
5
+ import { loadPrincipalHistoryReferences } from "../../../data/persistence/principalHistory/principalHistoryEvidencePersistence.js";
6
6
  import { principalHistoryEvidenceScopeId } from "../../../data/principals/principalHistoryPrefixProtection.js";
7
7
  import { ownPrincipalHistoryProtection } from "../../../data/principals/principalHistoryProtection.js";
8
8
  import { loadVerifiedPrincipalHistoryPrefix } from "./principalHistoryRecoveryPrefix.js";
@@ -34,20 +34,21 @@ async function readPage(options, beforeVersion) {
34
34
  const checkpoint = await loadPrincipalPolicyCheckpoint(options.execSql, options.expectedHead.principalType, options.expectedHead.principalId);
35
35
  if (checkpoint && checkpoint.version > options.expectedHead.version)
36
36
  throw new PrincipalHistoryRecoveryRaceError("Principal checkpoint advanced beyond the selected display history");
37
- const load = (version) => loadPageReference({
37
+ const firstVersion = Math.max(1, beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE);
38
+ const pageVersions = [];
39
+ for (let version = Math.max(1, firstVersion - 1); version < beforeVersion; version += 1)
40
+ pageVersions.push(version);
41
+ assertProjectionVerificationCurrent(current);
42
+ const loaded = await loadPageReferences({
38
43
  execSql: options.execSql,
39
44
  scopeId,
40
45
  history,
41
- version,
46
+ versions: checkpoint ? [...pageVersions, checkpoint.version] : pageVersions,
42
47
  });
43
- const firstVersion = Math.max(1, beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE);
44
- const references = [];
45
- for (let version = Math.max(1, firstVersion - 1); version < beforeVersion; version += 1) {
46
- assertProjectionVerificationCurrent(current);
47
- references.push(await load(version));
48
- }
48
+ assertProjectionVerificationCurrent(current);
49
+ const references = loaded.slice(0, pageVersions.length);
49
50
  const checkpointReference = checkpoint
50
- ? await load(checkpoint.version)
51
+ ? loaded[pageVersions.length]
51
52
  : undefined;
52
53
  if (checkpointReference &&
53
54
  checkpointReference.reference.stateHash !== checkpoint?.stateHash)
@@ -76,9 +77,9 @@ async function assertDisplayCheckpointCurrent(options, checkpoint) {
76
77
  latest?.stateHash !== checkpoint?.stateHash)
77
78
  throw new PrincipalHistoryRecoveryRaceError("Principal checkpoint changed while reading display history");
78
79
  }
79
- async function loadPageReference(input) {
80
+ async function loadPageReferences(input) {
80
81
  try {
81
- return await loadPrincipalHistoryReference(input);
82
+ return await loadPrincipalHistoryReferences(input);
82
83
  }
83
84
  catch (error) {
84
85
  if (error instanceof KeyingVerificationError)
@@ -1 +1 @@
1
- {"version":3,"file":"loadRecoveredPrincipalHistoryPage.js","sourceRoot":"","sources":["loadRecoveredPrincipalHistoryPage.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyHistoryReferenceProof,\n type PrincipalPolicyStateChainEntry,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport {\n isPrincipalPolicyStateChainEntryResponse,\n PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE,\n type PrincipalPolicyStateChainEntryResponse,\n} from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalPolicyCheckpoint } from \"../../../data/persistence/keyingCheckpoints/keyingCheckpointPersistence\";\nimport { loadPrincipalHistoryReference } from \"../../../data/persistence/principalHistory/principalHistoryEvidencePersistence\";\nimport { principalHistoryEvidenceScopeId } from \"../../../data/principals/principalHistoryPrefixProtection\";\nimport { ownPrincipalHistoryProtection } from \"../../../data/principals/principalHistoryProtection\";\nimport { loadVerifiedPrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport { PrincipalHistoryEvidenceUnavailableError } from \"./principalHistoryRecoveryReferences\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport { principalHistoryVerificationContext } from \"./principalHistoryRecoveryVerification\";\n\nexport interface RecoveredPrincipalHistoryPage {\n /** Ascending entries, with the immediate predecessor kept separately for diffs. */\n readonly entries: readonly PrincipalPolicyStateChainEntryResponse[];\n readonly predecessor: PrincipalPolicyStateChainEntryResponse | null;\n readonly nextBeforeVersion: number | null;\n}\n\n/** Read a bounded historical window from an already recovered, exact private root. */\nexport async function loadRecoveredPrincipalHistoryPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion = options.expectedHead.version + 1,\n): Promise<RecoveredPrincipalHistoryPage> {\n const owned = {\n ...options,\n expectedHead: structuredClone(options.expectedHead),\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n return await readPage(owned, beforeVersion);\n } finally {\n owned.protection.localKey.fill(0);\n }\n}\n\nasync function readPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion: number,\n): Promise<RecoveredPrincipalHistoryPage> {\n if (\n !Number.isSafeInteger(beforeVersion) ||\n beforeVersion <= 1 ||\n beforeVersion > options.expectedHead.version + 1\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal history page cursor is outside the selected history\",\n );\n const current = () => !options.signal?.aborted && options.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const { scopeId, history } = await restoreReadRoot(options, current);\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n options.execSql,\n options.expectedHead.principalType,\n options.expectedHead.principalId,\n );\n if (checkpoint && checkpoint.version > options.expectedHead.version)\n throw new PrincipalHistoryRecoveryRaceError(\n \"Principal checkpoint advanced beyond the selected display history\",\n );\n const load = (version: number) =>\n loadPageReference({\n execSql: options.execSql,\n scopeId,\n history,\n version,\n });\n const firstVersion = Math.max(\n 1,\n beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE,\n );\n const references: PrincipalPolicyHistoryReferenceProof[] = [];\n for (\n let version = Math.max(1, firstVersion - 1);\n version < beforeVersion;\n version += 1\n ) {\n assertProjectionVerificationCurrent(current);\n references.push(await load(version));\n }\n const checkpointReference = checkpoint\n ? await load(checkpoint.version)\n : undefined;\n if (\n checkpointReference &&\n checkpointReference.reference.stateHash !== checkpoint?.stateHash\n )\n throw new KeyingVerificationError(\n \"equivocation\",\n \"Principal history page conflicts with its durable checkpoint\",\n );\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok)\n throw new PrincipalHistoryEvidenceUnavailableError(selected.error);\n await assertDisplayCheckpointCurrent(options, checkpoint);\n assertProjectionVerificationCurrent(current);\n // These exact rows passed inclusion and commitment verification above. Keep\n // their display-only server timestamps, which the private current strips.\n const retained = references.map(({ entry }) => responseEntry(entry));\n return {\n entries: retained.filter(\n ({ state }) =>\n state.version >= firstVersion && state.version < beforeVersion,\n ),\n predecessor:\n retained.find(({ state }) => state.version === firstVersion - 1) ?? null,\n nextBeforeVersion: firstVersion > 1 ? firstVersion : null,\n };\n}\n\nasync function assertDisplayCheckpointCurrent(\n options: RecoverPrincipalPolicyHistoryOptions,\n checkpoint: Awaited<ReturnType<typeof loadPrincipalPolicyCheckpoint>>,\n) {\n const latest = await loadPrincipalPolicyCheckpoint(\n options.execSql,\n options.expectedHead.principalType,\n options.expectedHead.principalId,\n );\n if (\n latest?.version !== checkpoint?.version ||\n latest?.stateHash !== checkpoint?.stateHash\n )\n throw new PrincipalHistoryRecoveryRaceError(\n \"Principal checkpoint changed while reading display history\",\n );\n}\n\nasync function loadPageReference(\n input: Parameters<typeof loadPrincipalHistoryReference>[0],\n) {\n try {\n return await loadPrincipalHistoryReference(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n}\n\nfunction responseEntry(\n entry: PrincipalPolicyStateChainEntry,\n): PrincipalPolicyStateChainEntryResponse {\n if (!isPrincipalPolicyStateChainEntryResponse(entry))\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history display metadata is unavailable\",\n );\n return entry;\n}\n\nasync function restoreReadRoot(\n options: RecoverPrincipalPolicyHistoryOptions,\n current: () => boolean,\n) {\n const normalized = {\n ...options,\n protection: {\n ...options.protection,\n context: principalHistoryVerificationContext(options),\n },\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: options.organizationId,\n head: options.expectedHead,\n protection: normalized.protection,\n });\n const prefix = await loadVerifiedPrincipalHistoryPrefix(\n normalized,\n {\n principalType: options.expectedHead.principalType,\n principalId: options.expectedHead.principalId,\n },\n scopeId,\n );\n assertProjectionVerificationCurrent(current);\n if (!prefix)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history page requires a recovered private prefix\",\n );\n const finished = prefix.verifier.finish(options.expectedHead);\n if (!finished.ok) throw finished.error;\n return { scopeId, history: finished.value };\n}\n"]}
1
+ {"version":3,"file":"loadRecoveredPrincipalHistoryPage.js","sourceRoot":"","sources":["loadRecoveredPrincipalHistoryPage.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyStateChainEntry,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport {\n isPrincipalPolicyStateChainEntryResponse,\n PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE,\n type PrincipalPolicyStateChainEntryResponse,\n} from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalPolicyCheckpoint } from \"../../../data/persistence/keyingCheckpoints/keyingCheckpointPersistence\";\nimport { loadPrincipalHistoryReferences } from \"../../../data/persistence/principalHistory/principalHistoryEvidencePersistence\";\nimport { principalHistoryEvidenceScopeId } from \"../../../data/principals/principalHistoryPrefixProtection\";\nimport { ownPrincipalHistoryProtection } from \"../../../data/principals/principalHistoryProtection\";\nimport { loadVerifiedPrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport { PrincipalHistoryEvidenceUnavailableError } from \"./principalHistoryRecoveryReferences\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport { principalHistoryVerificationContext } from \"./principalHistoryRecoveryVerification\";\n\nexport interface RecoveredPrincipalHistoryPage {\n /** Ascending entries, with the immediate predecessor kept separately for diffs. */\n readonly entries: readonly PrincipalPolicyStateChainEntryResponse[];\n readonly predecessor: PrincipalPolicyStateChainEntryResponse | null;\n readonly nextBeforeVersion: number | null;\n}\n\n/** Read a bounded historical window from an already recovered, exact private root. */\nexport async function loadRecoveredPrincipalHistoryPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion = options.expectedHead.version + 1,\n): Promise<RecoveredPrincipalHistoryPage> {\n const owned = {\n ...options,\n expectedHead: structuredClone(options.expectedHead),\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n return await readPage(owned, beforeVersion);\n } finally {\n owned.protection.localKey.fill(0);\n }\n}\n\nasync function readPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion: number,\n): Promise<RecoveredPrincipalHistoryPage> {\n if (\n !Number.isSafeInteger(beforeVersion) ||\n beforeVersion <= 1 ||\n beforeVersion > options.expectedHead.version + 1\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal history page cursor is outside the selected history\",\n );\n const current = () => !options.signal?.aborted && options.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const { scopeId, history } = await restoreReadRoot(options, current);\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n options.execSql,\n options.expectedHead.principalType,\n options.expectedHead.principalId,\n );\n if (checkpoint && checkpoint.version > options.expectedHead.version)\n throw new PrincipalHistoryRecoveryRaceError(\n \"Principal checkpoint advanced beyond the selected display history\",\n );\n const firstVersion = Math.max(\n 1,\n beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE,\n );\n const pageVersions: number[] = [];\n for (\n let version = Math.max(1, firstVersion - 1);\n version < beforeVersion;\n version += 1\n )\n pageVersions.push(version);\n assertProjectionVerificationCurrent(current);\n const loaded = await loadPageReferences({\n execSql: options.execSql,\n scopeId,\n history,\n versions: checkpoint ? [...pageVersions, checkpoint.version] : pageVersions,\n });\n assertProjectionVerificationCurrent(current);\n const references = loaded.slice(0, pageVersions.length);\n const checkpointReference = checkpoint\n ? loaded[pageVersions.length]\n : undefined;\n if (\n checkpointReference &&\n checkpointReference.reference.stateHash !== checkpoint?.stateHash\n )\n throw new KeyingVerificationError(\n \"equivocation\",\n \"Principal history page conflicts with its durable checkpoint\",\n );\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok)\n throw new PrincipalHistoryEvidenceUnavailableError(selected.error);\n await assertDisplayCheckpointCurrent(options, checkpoint);\n assertProjectionVerificationCurrent(current);\n // These exact rows passed inclusion and commitment verification above. Keep\n // their display-only server timestamps, which the private current strips.\n const retained = references.map(({ entry }) => responseEntry(entry));\n return {\n entries: retained.filter(\n ({ state }) =>\n state.version >= firstVersion && state.version < beforeVersion,\n ),\n predecessor:\n retained.find(({ state }) => state.version === firstVersion - 1) ?? null,\n nextBeforeVersion: firstVersion > 1 ? firstVersion : null,\n };\n}\n\nasync function assertDisplayCheckpointCurrent(\n options: RecoverPrincipalPolicyHistoryOptions,\n checkpoint: Awaited<ReturnType<typeof loadPrincipalPolicyCheckpoint>>,\n) {\n const latest = await loadPrincipalPolicyCheckpoint(\n options.execSql,\n options.expectedHead.principalType,\n options.expectedHead.principalId,\n );\n if (\n latest?.version !== checkpoint?.version ||\n latest?.stateHash !== checkpoint?.stateHash\n )\n throw new PrincipalHistoryRecoveryRaceError(\n \"Principal checkpoint changed while reading display history\",\n );\n}\n\nasync function loadPageReferences(\n input: Parameters<typeof loadPrincipalHistoryReferences>[0],\n) {\n try {\n return await loadPrincipalHistoryReferences(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n}\n\nfunction responseEntry(\n entry: PrincipalPolicyStateChainEntry,\n): PrincipalPolicyStateChainEntryResponse {\n if (!isPrincipalPolicyStateChainEntryResponse(entry))\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history display metadata is unavailable\",\n );\n return entry;\n}\n\nasync function restoreReadRoot(\n options: RecoverPrincipalPolicyHistoryOptions,\n current: () => boolean,\n) {\n const normalized = {\n ...options,\n protection: {\n ...options.protection,\n context: principalHistoryVerificationContext(options),\n },\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: options.organizationId,\n head: options.expectedHead,\n protection: normalized.protection,\n });\n const prefix = await loadVerifiedPrincipalHistoryPrefix(\n normalized,\n {\n principalType: options.expectedHead.principalType,\n principalId: options.expectedHead.principalId,\n },\n scopeId,\n );\n assertProjectionVerificationCurrent(current);\n if (!prefix)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history page requires a recovered private prefix\",\n );\n const finished = prefix.verifier.finish(options.expectedHead);\n if (!finished.ok) throw finished.error;\n return { scopeId, history: finished.value };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { KeyingVerificationError, verifyPrincipalPolicyHistoryReferences, } from "../../../internal/crypto/index.js";
2
2
  import { assertProjectionVerificationCurrent } from "../../../data/keyingProjectionVerification/types.js";
3
- import { loadPrincipalHistoryReference } from "../../../data/persistence/principalHistory/principalHistoryEvidencePersistence.js";
3
+ import { loadPrincipalHistoryReferences } from "../../../data/persistence/principalHistory/principalHistoryEvidencePersistence.js";
4
4
  import { principalHeadMatchesReference } from "../../../data/principals/organizationAuthorityDescriptor.js";
5
5
  export class PrincipalHistoryEvidenceUnavailableError extends Error {
6
6
  verificationError;
@@ -13,29 +13,27 @@ export class PrincipalHistoryEvidenceUnavailableError extends Error {
13
13
  async function selectReferences(input) {
14
14
  const { options, scopeId, history } = input;
15
15
  const current = () => !options.signal?.aborted && options.stillCurrent();
16
- const base = { execSql: options.execSql, scopeId, history };
17
- const references = [];
18
- for (const reference of options.retainedReferences ?? []) {
19
- assertProjectionVerificationCurrent(current);
20
- references.push(await loadPrincipalHistoryReference({
21
- ...base,
22
- version: reference.version,
23
- }));
24
- }
25
- const versions = new Set((options.retainedReferences ?? []).map((reference) => reference.version));
16
+ const versions = (options.retainedReferences ?? []).map((reference) => reference.version);
17
+ const cited = new Set(versions);
26
18
  for (const version of options.retainedVersions ?? []) {
27
- if (versions.has(version))
19
+ if (cited.has(version))
28
20
  continue;
29
- versions.add(version);
30
- assertProjectionVerificationCurrent(current);
31
- references.push(await loadPrincipalHistoryReference({ ...base, version }));
21
+ cited.add(version);
22
+ versions.push(version);
32
23
  }
33
24
  assertProjectionVerificationCurrent(current);
25
+ const loaded = await loadPrincipalHistoryReferences({
26
+ execSql: options.execSql,
27
+ scopeId,
28
+ history,
29
+ versions: input.checkpoint
30
+ ? [...versions, input.checkpoint.version]
31
+ : versions,
32
+ });
33
+ assertProjectionVerificationCurrent(current);
34
+ const references = loaded.slice(0, versions.length);
34
35
  const checkpointReference = input.checkpoint
35
- ? await loadPrincipalHistoryReference({
36
- ...base,
37
- version: input.checkpoint.version,
38
- })
36
+ ? loaded[versions.length]
39
37
  : undefined;
40
38
  const selected = await verifyPrincipalPolicyHistoryReferences({
41
39
  history,
@@ -1 +1 @@
1
- {"version":3,"file":"principalHistoryRecoveryReferences.js","sourceRoot":"","sources":["principalHistoryRecoveryReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryReferenceProof,\n type VerifiedPrincipalPolicyHistory,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../../data/persistence/principalHistory/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../../data/principals/organizationAuthorityDescriptor\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"./principalHistoryRecoveryTypes\";\n\nexport interface PrincipalHistorySelectionOptions\n extends RecoverPrincipalPolicyHistoryOptions {\n /** Internal page selection by version; every selected row still needs a private-root proof. */\n readonly retainedVersions?: readonly number[] | undefined;\n}\n\nexport class PrincipalHistoryEvidenceUnavailableError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"PrincipalHistoryEvidenceUnavailableError\";\n }\n}\n\nasync function selectReferences(input: {\n readonly options: PrincipalHistorySelectionOptions;\n readonly scopeId: string;\n readonly history: VerifiedPrincipalPolicyHistory;\n readonly checkpoint: PrincipalPolicyCheckpoint | null;\n}): Promise<VerifiedPrincipalPolicyHistory> {\n const { options, scopeId, history } = input;\n const current = () => !options.signal?.aborted && options.stillCurrent();\n const base = { execSql: options.execSql, scopeId, history };\n const references: PrincipalPolicyHistoryReferenceProof[] = [];\n for (const reference of options.retainedReferences ?? []) {\n assertProjectionVerificationCurrent(current);\n references.push(\n await loadPrincipalHistoryReference({\n ...base,\n version: reference.version,\n }),\n );\n }\n const versions = new Set(\n (options.retainedReferences ?? []).map((reference) => reference.version),\n );\n for (const version of options.retainedVersions ?? []) {\n if (versions.has(version)) continue;\n versions.add(version);\n assertProjectionVerificationCurrent(current);\n references.push(await loadPrincipalHistoryReference({ ...base, version }));\n }\n assertProjectionVerificationCurrent(current);\n const checkpointReference = input.checkpoint\n ? await loadPrincipalHistoryReference({\n ...base,\n version: input.checkpoint.version,\n })\n : undefined;\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok) throw selected.error;\n assertProjectionVerificationCurrent(current);\n return selected.value;\n}\n\nexport async function selectRecoveredPrincipalHistory(\n input: Parameters<typeof selectReferences>[0],\n): Promise<VerifiedPrincipalPolicyHistory> {\n let selected: VerifiedPrincipalPolicyHistory;\n try {\n selected = await selectReferences(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n // First authenticate the stored entry against the private root. Only then\n // compare the caller's citation, so a bad request is not treated as cache loss.\n for (const reference of input.options.retainedReferences ?? []) {\n if (\n !selected.retainedEntries.some(({ state }) =>\n principalHeadMatchesReference(state, reference),\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Requested citation does not match the verified principal history\",\n );\n }\n return selected;\n}\n"]}
1
+ {"version":3,"file":"principalHistoryRecoveryReferences.js","sourceRoot":"","sources":["principalHistoryRecoveryReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyCheckpoint,\n type VerifiedPrincipalPolicyHistory,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReferences } from \"../../../data/persistence/principalHistory/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../../data/principals/organizationAuthorityDescriptor\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"./principalHistoryRecoveryTypes\";\n\nexport interface PrincipalHistorySelectionOptions\n extends RecoverPrincipalPolicyHistoryOptions {\n /** Internal page selection by version; every selected row still needs a private-root proof. */\n readonly retainedVersions?: readonly number[] | undefined;\n}\n\nexport class PrincipalHistoryEvidenceUnavailableError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"PrincipalHistoryEvidenceUnavailableError\";\n }\n}\n\nasync function selectReferences(input: {\n readonly options: PrincipalHistorySelectionOptions;\n readonly scopeId: string;\n readonly history: VerifiedPrincipalPolicyHistory;\n readonly checkpoint: PrincipalPolicyCheckpoint | null;\n}): Promise<VerifiedPrincipalPolicyHistory> {\n const { options, scopeId, history } = input;\n const current = () => !options.signal?.aborted && options.stillCurrent();\n const versions = (options.retainedReferences ?? []).map(\n (reference) => reference.version,\n );\n const cited = new Set(versions);\n for (const version of options.retainedVersions ?? []) {\n if (cited.has(version)) continue;\n cited.add(version);\n versions.push(version);\n }\n assertProjectionVerificationCurrent(current);\n const loaded = await loadPrincipalHistoryReferences({\n execSql: options.execSql,\n scopeId,\n history,\n versions: input.checkpoint\n ? [...versions, input.checkpoint.version]\n : versions,\n });\n assertProjectionVerificationCurrent(current);\n const references = loaded.slice(0, versions.length);\n const checkpointReference = input.checkpoint\n ? loaded[versions.length]\n : undefined;\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok) throw selected.error;\n assertProjectionVerificationCurrent(current);\n return selected.value;\n}\n\nexport async function selectRecoveredPrincipalHistory(\n input: Parameters<typeof selectReferences>[0],\n): Promise<VerifiedPrincipalPolicyHistory> {\n let selected: VerifiedPrincipalPolicyHistory;\n try {\n selected = await selectReferences(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n // First authenticate the stored entry against the private root. Only then\n // compare the caller's citation, so a bad request is not treated as cache loss.\n for (const reference of input.options.retainedReferences ?? []) {\n if (\n !selected.retainedEntries.some(({ state }) =>\n principalHeadMatchesReference(state, reference),\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Requested citation does not match the verified principal history\",\n );\n }\n return selected;\n}\n"]}
@@ -1,18 +1,16 @@
1
1
  import { KeyingVerificationError, PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT, selectPrincipalPolicyAuthorization, verifyPrincipalPolicyCheckpoint, verifyPrincipalPolicyHistoryReferences, } from "../../../internal/crypto/index.js";
2
2
  import { assertProjectionVerificationCurrent } from "../../../data/keyingProjectionVerification/types.js";
3
- import { loadPrincipalHistoryReference } from "../../../data/persistence/principalHistory/principalHistoryEvidencePersistence.js";
3
+ import { loadPrincipalHistoryReference, loadPrincipalHistoryReferences, } from "../../../data/persistence/principalHistory/principalHistoryEvidencePersistence.js";
4
4
  import { principalHeadMatchesReference } from "../../../data/principals/organizationAuthorityDescriptor.js";
5
5
  import { PrincipalHistoryEvidenceUnavailableError } from "../historyRecovery/principalHistoryRecoveryReferences.js";
6
6
  async function selectBatch(input, versions, checkpointReference) {
7
- const proofs = [];
8
- for (const version of versions) {
9
- assertProjectionVerificationCurrent(input.stillCurrent);
10
- proofs.push(await loadPrincipalHistoryReference({
11
- execSql: input.execSql,
12
- ...input.recovered,
13
- version,
14
- }));
15
- }
7
+ assertProjectionVerificationCurrent(input.stillCurrent);
8
+ const proofs = await loadPrincipalHistoryReferences({
9
+ execSql: input.execSql,
10
+ ...input.recovered,
11
+ versions,
12
+ });
13
+ assertProjectionVerificationCurrent(input.stillCurrent);
16
14
  const selected = await verifyPrincipalPolicyHistoryReferences({
17
15
  history: input.recovered.history,
18
16
  references: proofs,
@@ -1 +1 @@
1
- {"version":3,"file":"selectPublicPrincipalHistory.js","sourceRoot":"","sources":["selectPublicPrincipalHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryReferenceProof,\n type ReferencedPrincipalHead,\n selectPrincipalPolicyAuthorization,\n type VerifiedPrincipalPolicySelection,\n verifyPrincipalPolicyCheckpoint,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../../data/persistence/principalHistory/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../../data/principals/organizationAuthorityDescriptor\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { PrincipalHistoryEvidenceUnavailableError } from \"../historyRecovery/principalHistoryRecoveryReferences\";\nimport type { RecoveredPublicPrincipalHistory } from \"./publicPrincipalHistoryTypes\";\n\ninterface PublicHistorySelectionInput {\n readonly execSql: ExecSql;\n readonly recovered: RecoveredPublicPrincipalHistory;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly checkpoint: PrincipalPolicyCheckpoint | null;\n readonly deferCheckpointCheck?: boolean | undefined;\n readonly includeGenesis?: boolean;\n readonly stillCurrent: () => boolean;\n}\n\nasync function selectBatch(\n input: PublicHistorySelectionInput,\n versions: readonly number[],\n checkpointReference: PrincipalPolicyHistoryReferenceProof | undefined,\n) {\n const proofs: PrincipalPolicyHistoryReferenceProof[] = [];\n for (const version of versions) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n proofs.push(\n await loadPrincipalHistoryReference({\n execSql: input.execSql,\n ...input.recovered,\n version,\n }),\n );\n }\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history: input.recovered.history,\n references: proofs,\n checkpointReference,\n });\n if (!selected.ok) throw selected.error;\n return selected.value;\n}\n\nasync function loadCheckpointProof(\n input: PublicHistorySelectionInput,\n checkpoint: PrincipalPolicyCheckpoint | null,\n): Promise<PrincipalPolicyHistoryReferenceProof | undefined> {\n let checkpointReference: PrincipalPolicyHistoryReferenceProof | undefined;\n try {\n if (checkpoint)\n checkpointReference = await loadPrincipalHistoryReference({\n execSql: input.execSql,\n ...input.recovered,\n version: checkpoint.version,\n });\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n return checkpointReference;\n}\n\nfunction checkSelectedReferences(\n input: PublicHistorySelectionInput,\n references: readonly ReferencedPrincipalHead[],\n batch: readonly number[],\n selected: Awaited<ReturnType<typeof selectBatch>>,\n checkpoint: PrincipalPolicyCheckpoint | null,\n) {\n // Authenticate the disposable proof before comparing caller citations or pins.\n for (const reference of references.filter(({ version }) =>\n batch.includes(version),\n ))\n if (\n !selected.retainedEntries.some(({ state }) =>\n principalHeadMatchesReference(state, reference),\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history citation differs from its verified entry\",\n );\n if (!input.deferCheckpointCheck)\n verifyPrincipalPolicyCheckpoint({\n chain: selected.retainedEntries.map((entry) => ({\n ...entry,\n projection: [...entry.projection],\n grants: [...entry.grants],\n })),\n currentState: selected.currentEntry.state,\n localCheckpoint: checkpoint,\n });\n}\n\n/** Select bounded proof batches without admitting or advancing durable pins. */\nexport async function selectPublicPrincipalHistory(\n input: PublicHistorySelectionInput,\n): Promise<VerifiedPrincipalPolicySelection[]> {\n const references = structuredClone(input.references);\n const checkpoint = input.checkpoint && { ...input.checkpoint };\n const head = input.recovered.history.currentEntry.state;\n if (\n !input.deferCheckpointCheck &&\n checkpoint &&\n checkpoint.version > head.version\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Public history cannot connect to the newer durable checkpoint\",\n );\n if (\n references.some(\n (reference) =>\n reference.principalType !== head.principalType ||\n reference.principalId !== head.principalId ||\n reference.version > head.version,\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history reference is outside the verified prefix\",\n );\n const versions = [\n ...new Set([\n ...(input.includeGenesis ? [1] : []),\n ...references.map(({ version }) => version),\n head.version,\n ]),\n ];\n const policies: VerifiedPrincipalPolicySelection[] = [];\n const checkpointReference = await loadCheckpointProof(\n input,\n checkpoint && checkpoint.version <= head.version ? checkpoint : null,\n );\n for (\n let offset = 0;\n offset < versions.length;\n offset += PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT\n ) {\n const batch = versions.slice(\n offset,\n offset + PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n );\n const selected = await selectBatch(input, batch, checkpointReference).catch(\n (error: unknown) => {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n },\n );\n checkSelectedReferences(input, references, batch, selected, checkpoint);\n const policy = await selectPrincipalPolicyAuthorization(selected);\n if (!policy.ok) throw policy.error;\n policies.push(policy.value);\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n return policies;\n}\n"]}
1
+ {"version":3,"file":"selectPublicPrincipalHistory.js","sourceRoot":"","sources":["selectPublicPrincipalHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryReferenceProof,\n type ReferencedPrincipalHead,\n selectPrincipalPolicyAuthorization,\n type VerifiedPrincipalPolicySelection,\n verifyPrincipalPolicyCheckpoint,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport {\n loadPrincipalHistoryReference,\n loadPrincipalHistoryReferences,\n} from \"../../../data/persistence/principalHistory/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../../data/principals/organizationAuthorityDescriptor\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { PrincipalHistoryEvidenceUnavailableError } from \"../historyRecovery/principalHistoryRecoveryReferences\";\nimport type { RecoveredPublicPrincipalHistory } from \"./publicPrincipalHistoryTypes\";\n\ninterface PublicHistorySelectionInput {\n readonly execSql: ExecSql;\n readonly recovered: RecoveredPublicPrincipalHistory;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly checkpoint: PrincipalPolicyCheckpoint | null;\n readonly deferCheckpointCheck?: boolean | undefined;\n readonly includeGenesis?: boolean;\n readonly stillCurrent: () => boolean;\n}\n\nasync function selectBatch(\n input: PublicHistorySelectionInput,\n versions: readonly number[],\n checkpointReference: PrincipalPolicyHistoryReferenceProof | undefined,\n) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const proofs = await loadPrincipalHistoryReferences({\n execSql: input.execSql,\n ...input.recovered,\n versions,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history: input.recovered.history,\n references: proofs,\n checkpointReference,\n });\n if (!selected.ok) throw selected.error;\n return selected.value;\n}\n\nasync function loadCheckpointProof(\n input: PublicHistorySelectionInput,\n checkpoint: PrincipalPolicyCheckpoint | null,\n): Promise<PrincipalPolicyHistoryReferenceProof | undefined> {\n let checkpointReference: PrincipalPolicyHistoryReferenceProof | undefined;\n try {\n if (checkpoint)\n checkpointReference = await loadPrincipalHistoryReference({\n execSql: input.execSql,\n ...input.recovered,\n version: checkpoint.version,\n });\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n return checkpointReference;\n}\n\nfunction checkSelectedReferences(\n input: PublicHistorySelectionInput,\n references: readonly ReferencedPrincipalHead[],\n batch: readonly number[],\n selected: Awaited<ReturnType<typeof selectBatch>>,\n checkpoint: PrincipalPolicyCheckpoint | null,\n) {\n // Authenticate the disposable proof before comparing caller citations or pins.\n for (const reference of references.filter(({ version }) =>\n batch.includes(version),\n ))\n if (\n !selected.retainedEntries.some(({ state }) =>\n principalHeadMatchesReference(state, reference),\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history citation differs from its verified entry\",\n );\n if (!input.deferCheckpointCheck)\n verifyPrincipalPolicyCheckpoint({\n chain: selected.retainedEntries.map((entry) => ({\n ...entry,\n projection: [...entry.projection],\n grants: [...entry.grants],\n })),\n currentState: selected.currentEntry.state,\n localCheckpoint: checkpoint,\n });\n}\n\n/** Select bounded proof batches without admitting or advancing durable pins. */\nexport async function selectPublicPrincipalHistory(\n input: PublicHistorySelectionInput,\n): Promise<VerifiedPrincipalPolicySelection[]> {\n const references = structuredClone(input.references);\n const checkpoint = input.checkpoint && { ...input.checkpoint };\n const head = input.recovered.history.currentEntry.state;\n if (\n !input.deferCheckpointCheck &&\n checkpoint &&\n checkpoint.version > head.version\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Public history cannot connect to the newer durable checkpoint\",\n );\n if (\n references.some(\n (reference) =>\n reference.principalType !== head.principalType ||\n reference.principalId !== head.principalId ||\n reference.version > head.version,\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history reference is outside the verified prefix\",\n );\n const versions = [\n ...new Set([\n ...(input.includeGenesis ? [1] : []),\n ...references.map(({ version }) => version),\n head.version,\n ]),\n ];\n const policies: VerifiedPrincipalPolicySelection[] = [];\n const checkpointReference = await loadCheckpointProof(\n input,\n checkpoint && checkpoint.version <= head.version ? checkpoint : null,\n );\n for (\n let offset = 0;\n offset < versions.length;\n offset += PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT\n ) {\n const batch = versions.slice(\n offset,\n offset + PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n );\n const selected = await selectBatch(input, batch, checkpointReference).catch(\n (error: unknown) => {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n },\n );\n checkSelectedReferences(input, references, batch, selected, checkpoint);\n const policy = await selectPrincipalPolicyAuthorization(selected);\n if (!policy.ok) throw policy.error;\n policies.push(policy.value);\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n return policies;\n}\n"]}