@tearleads/client-sdk 0.1.19 → 0.1.21

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 (238) hide show
  1. package/client/organizations/index.js +2 -2
  2. package/client/organizations/index.js.map +1 -1
  3. package/client/organizations/organizationHistory.js +66 -0
  4. package/client/organizations/organizationHistory.js.map +1 -0
  5. package/client/organizations/organizationReadModels.d.ts +1 -1
  6. package/client/organizations/organizationReadModels.js +7 -27
  7. package/client/organizations/organizationReadModels.js.map +1 -1
  8. package/client/organizations/organizationsTypes.d.ts +1 -1
  9. package/client/organizations/organizationsTypes.js.map +1 -1
  10. package/data/containers/shared/types.d.ts +2 -2
  11. package/data/containers/shared/types.js.map +1 -1
  12. package/data/documents/shared/syncSubmitFailure.d.ts +2 -2
  13. package/data/documents/shared/syncSubmitFailure.js.map +1 -1
  14. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js +34 -8
  15. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js.map +1 -1
  16. package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
  17. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js +17 -0
  18. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js.map +1 -0
  19. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js +55 -0
  20. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js.map +1 -0
  21. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js +25 -13
  22. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js.map +1 -1
  23. package/data/keyingProjectionVerification/documentPurgeProofVerification.d.ts +5 -3
  24. package/data/keyingProjectionVerification/documentPurgeProofVerification.js +52 -8
  25. package/data/keyingProjectionVerification/documentPurgeProofVerification.js.map +1 -1
  26. package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
  27. package/data/keyingProjectionVerification/types.d.ts +4 -0
  28. package/data/keyingProjectionVerification/types.js.map +1 -1
  29. package/data/persistence/organizations/organizationReadModelProjection.js +2 -2
  30. package/data/persistence/organizations/organizationReadModelProjection.js.map +1 -1
  31. package/data/persistence/principalAuthorizationCheckpoints.js +1 -1
  32. package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -1
  33. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +1 -0
  34. package/data/persistence/principalCurrentAcknowledgementPersistence.js +58 -12
  35. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  36. package/data/persistence/principalHistoryEvidencePersistence.d.ts +2 -0
  37. package/data/persistence/principalHistoryEvidencePersistence.js +2 -0
  38. package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -1
  39. package/data/persistence/principalHistoryIncompleteRetention.js +32 -0
  40. package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -0
  41. package/data/persistence/principalHistoryNodeRetention.js +76 -0
  42. package/data/persistence/principalHistoryNodeRetention.js.map +1 -0
  43. package/data/persistence/principalHistoryPrefixPersistence.d.ts +1 -0
  44. package/data/persistence/principalHistoryPrefixPersistence.js +30 -1
  45. package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
  46. package/data/persistence/principalHistoryRootOwnership.js +71 -0
  47. package/data/persistence/principalHistoryRootOwnership.js.map +1 -0
  48. package/data/persistence/principalHistoryStagePersistence.js +45 -0
  49. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  50. package/data/persistence/principalHistoryStageRetention.js +44 -0
  51. package/data/persistence/principalHistoryStageRetention.js.map +1 -0
  52. package/data/persistence/principalHistoryUnpublishedRetention.js +71 -0
  53. package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -0
  54. package/data/persistence/principalKeyEnvelopeArchivePersistence.js +63 -0
  55. package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +1 -0
  56. package/data/persistence/principalKeyEnvelopeCandidates.js +10 -1
  57. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
  58. package/data/persistence/principalPolicyReferencePersistence.js +2 -2
  59. package/data/persistence/principalPolicyReferencePersistence.js.map +1 -1
  60. package/data/sqlite/principalHistoryEvidenceSchema.js +2 -0
  61. package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -1
  62. package/data/sqlite/principalHistoryNodeRetentionSchema.js +30 -0
  63. package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +1 -0
  64. package/data/sqlite/principalHistoryRetentionSchema.js +40 -0
  65. package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -0
  66. package/data/sqlite/principalHistoryStageSchema.js +2 -0
  67. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  68. package/data/sqlite/schema.d.ts +453 -0
  69. package/data/sqlite/schema.js +6 -0
  70. package/data/sqlite/schema.js.map +1 -1
  71. package/data/sqlite/sqliteCommitGuards.js +49 -0
  72. package/data/sqlite/sqliteCommitGuards.js.map +1 -0
  73. package/data/sqlite/sqlitePersistenceRuntime.js +14 -2
  74. package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
  75. package/index.d.ts +3 -1
  76. package/index.js.map +1 -1
  77. package/internal/api-client/ApiClient.d.ts +60 -137
  78. package/internal/api-client/ApiClient.js +7 -5
  79. package/internal/api-client/ApiClient.js.map +1 -1
  80. package/internal/api-client/apiRequestRuntime.js +7 -7
  81. package/internal/api-client/apiRequestRuntime.js.map +1 -1
  82. package/internal/api-client/documentPurge.js +25 -0
  83. package/internal/api-client/documentPurge.js.map +1 -0
  84. package/internal/api-client/organizationPolicyHistory.d.ts +53 -0
  85. package/internal/api-client/organizationPolicyHistory.js +15 -0
  86. package/internal/api-client/organizationPolicyHistory.js.map +1 -0
  87. package/internal/api-client/requestInternals.js +4 -4
  88. package/internal/api-client/requestInternals.js.map +1 -1
  89. package/internal/api-client/types.d.ts +2 -2
  90. package/internal/api-client/types.js.map +1 -1
  91. package/internal/crypto/keying/accessEvent.js +11 -9
  92. package/internal/crypto/keying/accessEvent.js.map +1 -1
  93. package/internal/crypto/keying/principalPolicyChainEntry.js +3 -0
  94. package/internal/crypto/keying/principalPolicyChainEntry.js.map +1 -1
  95. package/internal/crypto/keying/principalPolicyHistory.js +4 -0
  96. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  97. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
  98. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  99. package/internal/crypto/keying/principalPolicyTransition.d.ts +2 -1
  100. package/internal/crypto/keying/principalPolicyTransition.js +5 -0
  101. package/internal/crypto/keying/principalPolicyTransition.js.map +1 -1
  102. package/internal/crypto/principalState.js +2 -2
  103. package/internal/crypto/principalState.js.map +1 -1
  104. package/internal/validators/operation/containerMutations.d.ts +448 -6528
  105. package/internal/validators/operation/documentMutations.d.ts +323 -579
  106. package/internal/validators/operation/documentMutations.js +22 -4
  107. package/internal/validators/operation/documentMutations.js.map +1 -1
  108. package/internal/validators/operation/documentSync.d.ts +26 -406
  109. package/internal/validators/operation/organizationPolicyHistory.d.ts +188 -310
  110. package/internal/validators/operation/organizationPolicyHistory.js +17 -3
  111. package/internal/validators/operation/organizationPolicyHistory.js.map +1 -1
  112. package/internal/validators/operation/organizations.d.ts +2 -2
  113. package/internal/validators/request/principal.js +2 -2
  114. package/internal/validators/request/principal.js.map +1 -1
  115. package/internal/validators/response/containerMutationError.d.ts +28 -408
  116. package/internal/validators/response/documentMutation.d.ts +232 -544
  117. package/internal/validators/response/documentMutation.js +1 -2
  118. package/internal/validators/response/documentMutation.js.map +1 -1
  119. package/internal/validators/response/documentSyncError.d.ts +26 -406
  120. package/internal/validators/response/documentSyncError.js +4 -3
  121. package/internal/validators/response/documentSyncError.js.map +1 -1
  122. package/internal/validators/response/index.d.ts +1 -1
  123. package/internal/validators/response/index.js +1 -1
  124. package/internal/validators/response/index.js.map +1 -1
  125. package/internal/validators/response/organization.d.ts +1 -1
  126. package/internal/validators/response/organization.js +1 -1
  127. package/internal/validators/response/organization.js.map +1 -1
  128. package/internal/validators/response/organizationPolicyHistory.d.ts +127 -309
  129. package/internal/validators/response/organizationPolicyHistory.js +10 -4
  130. package/internal/validators/response/organizationPolicyHistory.js.map +1 -1
  131. package/internal/validators/response/organizationReadModel.d.ts +5 -5
  132. package/internal/validators/response/principal.d.ts +28 -408
  133. package/internal/validators/response/principal.js +3 -1
  134. package/internal/validators/response/principal.js.map +1 -1
  135. package/internal/validators/response/principalReference.d.ts +1 -1
  136. package/internal/validators/response/principalReference.js +1 -1
  137. package/internal/validators/response/principalReference.js.map +1 -1
  138. package/internal/validators/response/principalSnapshot.js +4 -4
  139. package/internal/validators/response/principalSnapshot.js.map +1 -1
  140. package/internal/validators/util/index.d.ts +1 -1
  141. package/internal/validators/util/index.js +1 -1
  142. package/internal/validators/util/index.js.map +1 -1
  143. package/internal/validators/util/principalHistoryWire.d.ts +2 -0
  144. package/internal/validators/util/principalHistoryWire.js +2 -0
  145. package/internal/validators/util/principalHistoryWire.js.map +1 -1
  146. package/package.json +1 -1
  147. package/workflows/container-contents/container-state/createWithMetadata.js +19 -49
  148. package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
  149. package/workflows/container-contents/container-state/groupGrantVerification.js +29 -0
  150. package/workflows/container-contents/container-state/groupGrantVerification.js.map +1 -1
  151. package/workflows/container-contents/container-state/groupShareEpoch.js +33 -0
  152. package/workflows/container-contents/container-state/groupShareEpoch.js.map +1 -0
  153. package/workflows/container-contents/container-state/remote.js +4 -1
  154. package/workflows/container-contents/container-state/remote.js.map +1 -1
  155. package/workflows/container-contents/container-state/share.js +2 -24
  156. package/workflows/container-contents/container-state/share.js.map +1 -1
  157. package/workflows/container-contents/documentTombstoneEvidence.js +23 -12
  158. package/workflows/container-contents/documentTombstoneEvidence.js.map +1 -1
  159. package/workflows/containers/child/create.js +1 -3
  160. package/workflows/containers/child/create.js.map +1 -1
  161. package/workflows/containers/child/createSubmission.d.ts +1 -3
  162. package/workflows/containers/child/createSubmission.js +13 -15
  163. package/workflows/containers/child/createSubmission.js.map +1 -1
  164. package/workflows/containers/child/currentShareGrantMutation.js +82 -0
  165. package/workflows/containers/child/currentShareGrantMutation.js.map +1 -0
  166. package/workflows/containers/child/currentSharePrincipalPolicy.js +83 -0
  167. package/workflows/containers/child/currentSharePrincipalPolicy.js.map +1 -0
  168. package/workflows/containers/child/mutationSubmit.js +1 -1
  169. package/workflows/containers/child/mutationSubmit.js.map +1 -1
  170. package/workflows/containers/child/runtimeCurrentGroupShare.js +82 -0
  171. package/workflows/containers/child/runtimeCurrentGroupShare.js.map +1 -0
  172. package/workflows/containers/child/share.js +1 -14
  173. package/workflows/containers/child/share.js.map +1 -1
  174. package/workflows/containers/child/shareProjection.js +15 -0
  175. package/workflows/containers/child/shareProjection.js.map +1 -0
  176. package/workflows/containers/mutationResponse.js +1 -1
  177. package/workflows/containers/mutationResponse.js.map +1 -1
  178. package/workflows/documents/purge.d.ts +3 -0
  179. package/workflows/documents/purge.js +13 -0
  180. package/workflows/documents/purge.js.map +1 -1
  181. package/workflows/documents/sync.js +2 -0
  182. package/workflows/documents/sync.js.map +1 -1
  183. package/workflows/documents/syncFailures.js +2 -2
  184. package/workflows/documents/syncFailures.js.map +1 -1
  185. package/workflows/documents/syncPolicyRepair.js +15 -13
  186. package/workflows/documents/syncPolicyRepair.js.map +1 -1
  187. package/workflows/organizations/initialPrincipalCurrentPublication.js +2 -0
  188. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -1
  189. package/workflows/organizations/loadPolicyHistoryDetails.js +31 -32
  190. package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
  191. package/workflows/organizations/organizationPolicyHistoryDetails.js +37 -15
  192. package/workflows/organizations/organizationPolicyHistoryDetails.js.map +1 -1
  193. package/workflows/organizations/organizationPolicyHistoryVerification.js +56 -69
  194. package/workflows/organizations/organizationPolicyHistoryVerification.js.map +1 -1
  195. package/workflows/organizations/policyHistoryCache.js +5 -2
  196. package/workflows/organizations/policyHistoryCache.js.map +1 -1
  197. package/workflows/organizations/policyHistoryTypes.d.ts +1 -0
  198. package/workflows/organizations/policyHistoryTypes.js.map +1 -1
  199. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +4 -1
  200. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
  201. package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +0 -1
  202. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +1 -2
  203. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -1
  204. package/workflows/principals/policyRepair.js +38 -0
  205. package/workflows/principals/policyRepair.js.map +1 -0
  206. package/workflows/principals/policyRepairBudget.d.ts +2 -2
  207. package/workflows/principals/policyRepairBudget.js +3 -3
  208. package/workflows/principals/policyRepairBudget.js.map +1 -1
  209. package/workflows/principals/principalHistoryRecoveryPrefix.js +4 -0
  210. package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -1
  211. package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
  212. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
  213. package/workflows/principals/publicPrincipalHistoryPage.js +1 -0
  214. package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -1
  215. package/workflows/principals/publicPrincipalHistoryProgress.js +1 -0
  216. package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -1
  217. package/workflows/principals/publicPrincipalHistoryTypes.d.ts +2 -0
  218. package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -1
  219. package/workflows/principals/publicProjectionPrincipal.js +1 -0
  220. package/workflows/principals/publicProjectionPrincipal.js.map +1 -1
  221. package/workflows/principals/recoverPrincipalHistoryPage.js +2 -1
  222. package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -1
  223. package/workflows/principals/recoverPrincipalPolicyHistory.js +1 -0
  224. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  225. package/workflows/principals/recoverPublicPrincipalHistory.js +2 -0
  226. package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
  227. package/workflows/principals/runtimePolicyRecovery.js +2 -1
  228. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  229. package/workflows/principals/selectPublicPrincipalHistory.js +21 -15
  230. package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -1
  231. package/workflows/sync/remoteResetPrincipalScope.js +6 -0
  232. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  233. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js +0 -208
  234. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js.map +0 -1
  235. package/data/keyingProjectionVerification/snapshotVerificationCache.js +0 -39
  236. package/data/keyingProjectionVerification/snapshotVerificationCache.js.map +0 -1
  237. package/workflows/containers/child/policyRepair.js +0 -23
  238. package/workflows/containers/child/policyRepair.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"documentPurgeCheckpointCurrency.js","sourceRoot":"","sources":["documentPurgeCheckpointCurrency.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n VerifiedAccessManifestCheckpointEvidence,\n VerifiedPrincipalPolicySnapshot,\n} from \"@tearleads/crypto\";\nimport type { DocumentPurgeCheckpoint } from \"../persistence/documentPurgeCheckpointPersistence\";\nimport { validateAccessManifestCheckpointEvidence } from \"../persistence/keyingCheckpointEvidence\";\nimport {\n accessManifestObjectKey,\n loadAccessManifestCheckpoint,\n} from \"../persistence/keyingCheckpointPersistence\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, runSerializedSqlMutation } from \"../sqlite/sqlSchema\";\nimport { validateAccessManifestCheckpoints } from \"./accessManifestCheckpointEnforcement\";\nimport {\n commitProjectionCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { enforcePrincipalPolicySnapshotCheckpoints } from \"./principalPolicySnapshotVerification\";\n\ninterface PurgeCheckpointInput {\n readonly context: ProjectionCheckpointContext;\n readonly execSql: ExecSql;\n readonly principalPolicies: readonly VerifiedPrincipalPolicySnapshot[];\n}\n\n/** All artifacts must already be authenticated before currency is considered. */\nasync function currentContainerHeads(input: PurgeCheckpointInput) {\n const current: VerifiedAccessManifestCheckpointEvidence[] = [];\n let superseded = false;\n for (const head of input.context.verifiedHeads) {\n const checkpoint = head.checkpoint;\n const local =\n checkpoint.objectKind === \"container\"\n ? await loadAccessManifestCheckpoint(\n input.execSql,\n \"container\",\n checkpoint.organizationId,\n checkpoint.objectId,\n )\n : null;\n if (!local || checkpoint.epoch >= local.epoch) {\n current.push(head);\n continue;\n }\n // A newer head does not order this separately signed purge event. Still\n // reject signed forks visible in the supplied evidence before deferring.\n const key = accessManifestObjectKey(checkpoint);\n validateAccessManifestCheckpointEvidence({\n head,\n localCheckpoint: local,\n predecessors: input.context.verifiedManifests.filter(\n (evidence) =>\n accessManifestObjectKey(evidence.checkpoint) === key &&\n evidence.manifestHash !== head.manifestHash,\n ),\n });\n superseded = true;\n }\n return { current, superseded };\n}\n\nasync function checkPurgeCheckpointCurrency(\n input: PurgeCheckpointInput,\n documentPurgeCheckpoint?: DocumentPurgeCheckpoint,\n): Promise<void> {\n // Keep comparison and optional advancement in the same immediate transaction.\n // Pass the locked executor through nested readers and checkpoint commits.\n await runSerializedSqlMutation(input.execSql, async (execSql) => {\n await getClientSQLitePersistenceRuntime(execSql).transaction(\n async () => {\n const policies = await enforcePrincipalPolicySnapshotCheckpoints({\n execSql,\n policies: input.principalPolicies,\n });\n const { current, superseded } = await currentContainerHeads({\n ...input,\n execSql,\n });\n // An older container must not conceal a document fork, a policy fork, or\n // conflicting current evidence for another container in the same proof.\n await validateAccessManifestCheckpoints({\n execSql,\n policies,\n verifiedHeads: current,\n verifiedManifests: input.context.verifiedManifests,\n });\n if (superseded) {\n throw new ProjectionDependencyUnavailableError(\n \"Document purge cannot be ordered against a newer container checkpoint\",\n );\n }\n if (documentPurgeCheckpoint) {\n await commitProjectionCheckpoints(\n { ...input.context, policies },\n {\n documentPurgeCheckpoint,\n execSql,\n },\n );\n }\n },\n { behavior: \"immediate\" },\n );\n });\n}\n\nexport function validateDocumentPurgeCheckpoints(\n input: PurgeCheckpointInput,\n): Promise<void> {\n return checkPurgeCheckpointCurrency(input);\n}\n\nexport function commitDocumentPurgeCheckpoints(\n input: PurgeCheckpointInput & {\n readonly documentPurgeCheckpoint: DocumentPurgeCheckpoint;\n },\n): Promise<void> {\n return checkPurgeCheckpointCurrency(input, input.documentPurgeCheckpoint);\n}\n"]}
1
+ {"version":3,"file":"documentPurgeCheckpointCurrency.js","sourceRoot":"","sources":["documentPurgeCheckpointCurrency.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ReferencedPrincipalHead,\n VerifiedAccessManifestCheckpointEvidence,\n VerifiedPrincipalPolicySelection,\n} from \"@tearleads/crypto\";\nimport type { DocumentPurgeCheckpoint } from \"../persistence/documentPurgeCheckpointPersistence\";\nimport { validateAccessManifestCheckpointEvidence } from \"../persistence/keyingCheckpointEvidence\";\nimport {\n accessManifestObjectKey,\n loadAccessManifestCheckpoint,\n} from \"../persistence/keyingCheckpointPersistence\";\nimport {\n PrincipalAuthorizationCheckpointUnavailableError,\n validatePrincipalAuthorizationCheckpoints,\n} from \"../persistence/principalAuthorizationCheckpoints\";\nimport { ensurePrincipalPolicyTables } from \"../persistence/principalPolicyPersistence\";\nimport { registerClientSQLiteCommitGuard } from \"../sqlite/sqliteCommitGuards\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, runSerializedSqlMutation } from \"../sqlite/sqlSchema\";\nimport { validateAccessManifestCheckpoints } from \"./accessManifestCheckpointEnforcement\";\nimport {\n commitProjectionCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { admitDocumentPurgePolicyCheckpoints } from \"./documentPurgePolicyCheckpoints\";\nimport type { PurgePolicyCurrencyEvidence } from \"./documentPurgePolicyCurrency\";\nimport { projectionLifetimeGuard } from \"./projectionLifetimes\";\nimport { assertProjectionVerificationCurrent } from \"./types\";\n\ninterface PurgeCheckpointInput {\n readonly context: ProjectionCheckpointContext;\n readonly execSql: ExecSql;\n readonly principalPolicies: readonly VerifiedPrincipalPolicySelection[];\n readonly currencyPolicies: readonly PurgePolicyCurrencyEvidence[];\n readonly observedPrincipalHeads: readonly ReferencedPrincipalHead[];\n}\n\n/** All artifacts must already be authenticated before currency is considered. */\nasync function currentContainerHeads(input: PurgeCheckpointInput) {\n const current: VerifiedAccessManifestCheckpointEvidence[] = [];\n let superseded = false;\n for (const head of input.context.verifiedHeads) {\n const checkpoint = head.checkpoint;\n const local =\n checkpoint.objectKind === \"container\"\n ? await loadAccessManifestCheckpoint(\n input.execSql,\n \"container\",\n checkpoint.organizationId,\n checkpoint.objectId,\n )\n : null;\n if (!local || checkpoint.epoch >= local.epoch) {\n current.push(head);\n continue;\n }\n // A newer head does not order this separately signed purge event. Still\n // reject signed forks visible in the supplied evidence before deferring.\n const key = accessManifestObjectKey(checkpoint);\n validateAccessManifestCheckpointEvidence({\n head,\n localCheckpoint: local,\n predecessors: input.context.verifiedManifests.filter(\n (evidence) =>\n accessManifestObjectKey(evidence.checkpoint) === key &&\n evidence.manifestHash !== head.manifestHash,\n ),\n });\n superseded = true;\n }\n return { current, superseded };\n}\n\nasync function checkPurgeCheckpointCurrency(\n input: PurgeCheckpointInput,\n documentPurgeCheckpoint?: DocumentPurgeCheckpoint,\n): Promise<void> {\n // Keep comparison and optional advancement in the same immediate transaction.\n // Pass the locked executor through nested readers and checkpoint commits.\n await runSerializedSqlMutation(input.execSql, async (execSql) => {\n await getClientSQLitePersistenceRuntime(execSql).transaction(\n async (transaction) => {\n const stillCurrent = projectionLifetimeGuard(input.context);\n registerClientSQLiteCommitGuard(execSql, () =>\n assertProjectionVerificationCurrent(stillCurrent),\n );\n const { current, superseded } = await currentContainerHeads({\n ...input,\n execSql,\n });\n // An older container must not conceal a document fork, a policy fork, or\n // conflicting current evidence for another container in the same proof.\n await validateAccessManifestCheckpoints({\n execSql,\n policies: [],\n verifiedHeads: current,\n verifiedManifests: input.context.verifiedManifests,\n });\n if (input.currencyPolicies.length) {\n await ensurePrincipalPolicyTables(execSql);\n await validatePrincipalAuthorizationCheckpoints(\n transaction,\n input.currencyPolicies,\n );\n }\n if (superseded) {\n throw new ProjectionDependencyUnavailableError(\n \"Document purge cannot be ordered against a newer container checkpoint\",\n );\n }\n if (documentPurgeCheckpoint) {\n // Only the complete authenticated terminal proof admits these public\n // observations. Page recovery and baseline verification never pin.\n await admitDocumentPurgePolicyCheckpoints({\n transaction,\n organizationId: input.context.organizationId,\n policies: input.principalPolicies,\n heads: input.observedPrincipalHeads,\n });\n assertProjectionVerificationCurrent(stillCurrent);\n await commitProjectionCheckpoints(\n {\n ...input.context,\n policies: [],\n // Currency was rechecked above in this same transaction. Private\n // ancestry bridges must never become newly admitted purge heads.\n authorizationPolicies: [],\n },\n {\n documentPurgeCheckpoint,\n execSql,\n },\n );\n }\n },\n { behavior: \"immediate\" },\n );\n }).catch((error: unknown) => {\n if (error instanceof PrincipalAuthorizationCheckpointUnavailableError)\n throw new ProjectionDependencyUnavailableError(error.message);\n throw error;\n });\n}\n\nexport function validateDocumentPurgeCheckpoints(\n input: PurgeCheckpointInput,\n): Promise<void> {\n return checkPurgeCheckpointCurrency(input);\n}\n\nexport function commitDocumentPurgeCheckpoints(\n input: PurgeCheckpointInput & {\n readonly documentPurgeCheckpoint: DocumentPurgeCheckpoint;\n },\n): Promise<void> {\n return checkPurgeCheckpointCurrency(input, input.documentPurgeCheckpoint);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"documentPurgeDocumentChainVerification.js","sourceRoot":"","sources":["documentPurgeDocumentChainVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n type VerifiedAccessManifestSnapshot,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n verifyDocumentLinkSetSnapshot,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentPurgeProofResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalJson } from \"../keyingCanonicalJson\";\nimport {\n addBundleByHash,\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport {\n observeAccessManifestCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { verifyDocumentManifestBundle } from \"./documentManifestVerification\";\nimport { loadManifestCheckpointVerification } from \"./manifestCheckpointVerification\";\nimport { readAccessManifest, readDocumentAccessEventBody } from \"./readers\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\nasync function verifyPinnedChainEndpoint(input: {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly checkpointContext: ProjectionCheckpointContext;\n}): Promise<VerifiedDocumentLinkSetSnapshot> {\n const manifest = readAccessManifest(\n input.bundle.manifest,\n \"Document purge predecessor endpoint manifest\",\n );\n const checkpointVerification = await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: new Map(),\n });\n const localCheckpoint = checkpointVerification.localCheckpoint;\n if (!localCheckpoint) {\n throw new ProjectionDependencyUnavailableError(\n \"Document purge history needs a local checkpoint or signed genesis\",\n );\n }\n if (\n localCheckpoint.epoch !== manifest.epoch ||\n localCheckpoint.manifestHash !== input.bundle.manifestHash\n ) {\n throw new KeyingVerificationError(\n localCheckpoint.epoch > manifest.epoch ? \"rollback\" : \"stale_predecessor\",\n \"Document purge predecessor chain does not start at the local checkpoint\",\n );\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...checkpointVerification,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n state: input.bundle.state,\n });\n if (!verified.ok) throw verified.error;\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(\n verified.value.state,\n \"Document purge predecessor endpoint state\",\n ),\n label: \"Document purge predecessor endpoint state\",\n });\n return verified.value;\n}\n\nasync function recordSnapshotContainerEvidence(input: {\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly manifest: VerifiedDocumentLinkSetSnapshot;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<void> {\n if (!input.usedContainerManifests) return;\n const event = await verifyAccessEventBundle({\n bundle: input.proof.documentManifest,\n label: \"Document purge manifest snapshot\",\n resolveUserKey: input.resolveUserKey,\n });\n if (event.eventHash !== input.manifest.manifest.eventHash) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"Document purge manifest snapshot event is not bound to its manifest\",\n );\n }\n const body = readDocumentAccessEventBody(\n event.body,\n \"Document purge manifest snapshot event body\",\n );\n const manifestHashes = [\n ...event.event.dependencyManifestHashes,\n body.containerManifestHash,\n ];\n for (const manifestHash of manifestHashes) {\n for (const containerManifest of input.containerPathByManifestHash.get(\n manifestHash,\n ) ?? []) {\n input.usedContainerManifests.set(\n containerManifest.manifestHash,\n containerManifest,\n );\n }\n }\n}\n\nasync function verifyPurgeChainEndpoint(\n input: Parameters<typeof verifySignedPurgeDocumentManifestChain>[0] & {\n readonly endpoint: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<\n string,\n AccessManifestBundleWireResponse\n >;\n readonly verifiedByHash: Map<string, VerifiedDocumentLinkSetManifest>;\n },\n): Promise<VerifiedDocumentLinkSetSnapshot | null> {\n const endpointManifest = readAccessManifest(\n input.endpoint.manifest,\n \"Document purge chain endpoint\",\n );\n if (endpointManifest.previousManifestHash === null) {\n await verifyDocumentManifestBundle({\n ...input,\n authorizationMembership: \"referenced\",\n bundle: input.endpoint,\n enforceLocalCheckpoint: false,\n label: \"Document purge genesis\",\n requireAuthorizationEvidence: true,\n });\n return null;\n }\n if (!input.enforceLocalCheckpoints) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Initial document purge history does not reach signed genesis\",\n );\n }\n return verifyPinnedChainEndpoint({\n bundle: input.endpoint,\n checkpointContext: input.checkpointContext,\n });\n}\n\nasync function verifySignedPurgeDocumentManifestChain(input: {\n readonly authorizationEvidence: readonly AnyVerifiedPrincipalPolicy[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n addBundleByHash(\n bundlesByHash,\n input.proof.documentManifest,\n \"Document purge manifest\",\n );\n for (const [\n index,\n bundle,\n ] of input.proof.documentManifestPredecessors.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge predecessor[${index}]`,\n );\n }\n\n const endpoint =\n input.proof.documentManifestPredecessors.at(-1) ??\n input.proof.documentManifest;\n const verifiedByHash = new Map<string, VerifiedDocumentLinkSetManifest>();\n const trustedPredecessorByHash = new Map<\n string,\n VerifiedDocumentLinkSetSnapshot\n >();\n const verifiedEndpoint = await verifyPurgeChainEndpoint({\n ...input,\n endpoint,\n bundlesByHash,\n verifiedByHash,\n });\n if (verifiedEndpoint) {\n trustedPredecessorByHash.set(\n verifiedEndpoint.manifestHash,\n verifiedEndpoint,\n );\n }\n\n const verificationInput = {\n ...input,\n authorizationMembership: \"referenced\" as const,\n bundlesByHash,\n requireAuthorizationEvidence: true,\n trustedPredecessorByHash,\n verifiedByHash,\n };\n for (\n let index = input.proof.documentManifestPredecessors.length - 2;\n index >= 0;\n index -= 1\n ) {\n const bundle = input.proof.documentManifestPredecessors[index];\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `Document purge predecessor[${index}] is missing`,\n );\n }\n await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle,\n enforceLocalCheckpoint: false,\n label: `Document purge predecessor[${index}]`,\n });\n }\n const head = await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle: input.proof.documentManifest,\n enforceLocalCheckpoint: input.enforceLocalCheckpoints,\n label: \"Document purge manifest\",\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [head],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return head;\n}\n\nexport async function verifyPurgeDocumentManifest(input: {\n readonly authorizationEvidence: readonly AnyVerifiedPrincipalPolicy[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest | VerifiedDocumentLinkSetSnapshot> {\n const verifiedByHash = new Map<string, VerifiedAccessManifestSnapshot>();\n const manifest = readAccessManifest(\n input.proof.documentManifest.manifest,\n \"Document purge manifest snapshot\",\n );\n const checkpointVerification = input.enforceLocalCheckpoints\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: verifiedByHash,\n })\n : undefined;\n const localCheckpoint = checkpointVerification?.localCheckpoint;\n const isPinnedHead =\n localCheckpoint?.epoch === manifest.epoch &&\n localCheckpoint.manifestHash === input.proof.documentManifest.manifestHash;\n // Baseline inspection may read a hash-only snapshot. Committing a purge\n // requires an exact existing pin or verified signed transitions from\n // that pin (or signed genesis for a fresh device).\n if (\n input.proof.documentManifestPredecessors.length > 0 ||\n (input.enforceLocalCheckpoints && !isPinnedHead)\n ) {\n return verifySignedPurgeDocumentManifestChain(input);\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...(checkpointVerification ?? {}),\n expectedManifestHash: input.proof.documentManifest.manifestHash,\n manifest,\n state: input.proof.documentManifest.state,\n });\n if (!verified.ok) throw verified.error;\n const documentManifest = verified.value;\n await recordSnapshotContainerEvidence({\n containerPathByManifestHash: input.containerPathByManifestHash,\n manifest: documentManifest,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n usedContainerManifests: input.usedContainerManifests,\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [documentManifest],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return documentManifest;\n}\n"]}
1
+ {"version":3,"file":"documentPurgeDocumentChainVerification.js","sourceRoot":"","sources":["documentPurgeDocumentChainVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyAuthorization,\n type VerifiedAccessManifestSnapshot,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n verifyDocumentLinkSetSnapshot,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentPurgeProofResponse,\n} from \"@tearleads/validators/response\";\nimport { readCanonicalJson } from \"../keyingCanonicalJson\";\nimport {\n addBundleByHash,\n assertCanonicalEqual,\n verifyAccessEventBundle,\n} from \"./bundleVerification\";\nimport {\n observeAccessManifestCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { verifyDocumentManifestBundle } from \"./documentManifestVerification\";\nimport { loadManifestCheckpointVerification } from \"./manifestCheckpointVerification\";\nimport { readAccessManifest, readDocumentAccessEventBody } from \"./readers\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\nasync function verifyPinnedChainEndpoint(input: {\n readonly bundle: AccessManifestBundleWireResponse;\n readonly checkpointContext: ProjectionCheckpointContext;\n}): Promise<VerifiedDocumentLinkSetSnapshot> {\n const manifest = readAccessManifest(\n input.bundle.manifest,\n \"Document purge predecessor endpoint manifest\",\n );\n const checkpointVerification = await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: new Map(),\n });\n const localCheckpoint = checkpointVerification.localCheckpoint;\n if (!localCheckpoint) {\n throw new ProjectionDependencyUnavailableError(\n \"Document purge history needs a local checkpoint or signed genesis\",\n );\n }\n if (\n localCheckpoint.epoch !== manifest.epoch ||\n localCheckpoint.manifestHash !== input.bundle.manifestHash\n ) {\n throw new KeyingVerificationError(\n localCheckpoint.epoch > manifest.epoch ? \"rollback\" : \"stale_predecessor\",\n \"Document purge predecessor chain does not start at the local checkpoint\",\n );\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...checkpointVerification,\n expectedManifestHash: input.bundle.manifestHash,\n manifest,\n state: input.bundle.state,\n });\n if (!verified.ok) throw verified.error;\n assertCanonicalEqual({\n actual: input.bundle.state,\n expected: readCanonicalJson(\n verified.value.state,\n \"Document purge predecessor endpoint state\",\n ),\n label: \"Document purge predecessor endpoint state\",\n });\n return verified.value;\n}\n\nasync function recordSnapshotContainerEvidence(input: {\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly manifest: VerifiedDocumentLinkSetSnapshot;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<void> {\n if (!input.usedContainerManifests) return;\n const event = await verifyAccessEventBundle({\n bundle: input.proof.documentManifest,\n label: \"Document purge manifest snapshot\",\n resolveUserKey: input.resolveUserKey,\n });\n if (event.eventHash !== input.manifest.manifest.eventHash) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"Document purge manifest snapshot event is not bound to its manifest\",\n );\n }\n const body = readDocumentAccessEventBody(\n event.body,\n \"Document purge manifest snapshot event body\",\n );\n const manifestHashes = [\n ...event.event.dependencyManifestHashes,\n body.containerManifestHash,\n ];\n for (const manifestHash of manifestHashes) {\n for (const containerManifest of input.containerPathByManifestHash.get(\n manifestHash,\n ) ?? []) {\n input.usedContainerManifests.set(\n containerManifest.manifestHash,\n containerManifest,\n );\n }\n }\n}\n\nasync function verifyPurgeChainEndpoint(\n input: Parameters<typeof verifySignedPurgeDocumentManifestChain>[0] & {\n readonly endpoint: AccessManifestBundleWireResponse;\n readonly bundlesByHash: ReadonlyMap<\n string,\n AccessManifestBundleWireResponse\n >;\n readonly verifiedByHash: Map<string, VerifiedDocumentLinkSetManifest>;\n },\n): Promise<VerifiedDocumentLinkSetSnapshot | null> {\n const endpointManifest = readAccessManifest(\n input.endpoint.manifest,\n \"Document purge chain endpoint\",\n );\n if (endpointManifest.previousManifestHash === null) {\n await verifyDocumentManifestBundle({\n ...input,\n authorizationMembership: \"referenced\",\n bundle: input.endpoint,\n enforceLocalCheckpoint: false,\n label: \"Document purge genesis\",\n requireAuthorizationEvidence: true,\n });\n return null;\n }\n if (!input.enforceLocalCheckpoints) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Initial document purge history does not reach signed genesis\",\n );\n }\n return verifyPinnedChainEndpoint({\n bundle: input.endpoint,\n checkpointContext: input.checkpointContext,\n });\n}\n\nasync function verifySignedPurgeDocumentManifestChain(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n addBundleByHash(\n bundlesByHash,\n input.proof.documentManifest,\n \"Document purge manifest\",\n );\n for (const [\n index,\n bundle,\n ] of input.proof.documentManifestPredecessors.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge predecessor[${index}]`,\n );\n }\n\n const endpoint =\n input.proof.documentManifestPredecessors.at(-1) ??\n input.proof.documentManifest;\n const verifiedByHash = new Map<string, VerifiedDocumentLinkSetManifest>();\n const trustedPredecessorByHash = new Map<\n string,\n VerifiedDocumentLinkSetSnapshot\n >();\n const verifiedEndpoint = await verifyPurgeChainEndpoint({\n ...input,\n endpoint,\n bundlesByHash,\n verifiedByHash,\n });\n if (verifiedEndpoint) {\n trustedPredecessorByHash.set(\n verifiedEndpoint.manifestHash,\n verifiedEndpoint,\n );\n }\n\n const verificationInput = {\n ...input,\n authorizationMembership: \"referenced\" as const,\n bundlesByHash,\n requireAuthorizationEvidence: true,\n trustedPredecessorByHash,\n verifiedByHash,\n };\n for (\n let index = input.proof.documentManifestPredecessors.length - 2;\n index >= 0;\n index -= 1\n ) {\n const bundle = input.proof.documentManifestPredecessors[index];\n if (!bundle) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `Document purge predecessor[${index}] is missing`,\n );\n }\n await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle,\n enforceLocalCheckpoint: false,\n label: `Document purge predecessor[${index}]`,\n });\n }\n const head = await verifyDocumentManifestBundle({\n ...verificationInput,\n bundle: input.proof.documentManifest,\n enforceLocalCheckpoint: input.enforceLocalCheckpoints,\n label: \"Document purge manifest\",\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [head],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return head;\n}\n\nexport async function verifyPurgeDocumentManifest(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly usedContainerManifests?:\n | Map<string, VerifiedContainerAccessManifest>\n | undefined;\n}): Promise<VerifiedDocumentLinkSetManifest | VerifiedDocumentLinkSetSnapshot> {\n const verifiedByHash = new Map<string, VerifiedAccessManifestSnapshot>();\n const manifest = readAccessManifest(\n input.proof.documentManifest.manifest,\n \"Document purge manifest snapshot\",\n );\n const checkpointVerification = input.enforceLocalCheckpoints\n ? await loadManifestCheckpointVerification({\n current: manifest,\n execSql: input.checkpointContext.execSql,\n localCheckpoints: input.checkpointContext.localCheckpoints,\n verifiedManifests: verifiedByHash,\n })\n : undefined;\n const localCheckpoint = checkpointVerification?.localCheckpoint;\n const isPinnedHead =\n localCheckpoint?.epoch === manifest.epoch &&\n localCheckpoint.manifestHash === input.proof.documentManifest.manifestHash;\n // Baseline inspection may read a hash-only snapshot. Committing a purge\n // requires an exact existing pin or verified signed transitions from\n // that pin (or signed genesis for a fresh device).\n if (\n input.proof.documentManifestPredecessors.length > 0 ||\n (input.enforceLocalCheckpoints && !isPinnedHead)\n ) {\n return verifySignedPurgeDocumentManifestChain(input);\n }\n const verified = await verifyDocumentLinkSetSnapshot({\n ...(checkpointVerification ?? {}),\n expectedManifestHash: input.proof.documentManifest.manifestHash,\n manifest,\n state: input.proof.documentManifest.state,\n });\n if (!verified.ok) throw verified.error;\n const documentManifest = verified.value;\n await recordSnapshotContainerEvidence({\n containerPathByManifestHash: input.containerPathByManifestHash,\n manifest: documentManifest,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n usedContainerManifests: input.usedContainerManifests,\n });\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [documentManifest],\n verifiedManifests: [...verifiedByHash.values()],\n });\n return documentManifest;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { KeyingVerificationError, principalPolicyMatchesReference, } from "../../internal/crypto/index.js";
2
+ import { loadStoredPrincipalPolicyCheckpoint, upsertPrincipalPolicyCheckpointInTransaction, } from "../persistence/keyingCheckpointPersistence.js";
3
+ /** After complete terminal-proof currency validation, admit only its bound sources. */
4
+ export async function admitDocumentPurgePolicyCheckpoints(input) {
5
+ const updatedAt = new Date().toISOString();
6
+ for (const reference of input.heads) {
7
+ if (!input.policies.some((policy) => principalPolicyMatchesReference({ policy, reference })))
8
+ throw new KeyingVerificationError("missing_dependency", "Purge source lacks verified inclusion");
9
+ const checkpoint = await loadStoredPrincipalPolicyCheckpoint(input.transaction, reference);
10
+ // A newer privately authenticated prefix can prove ancestry, but is not an
11
+ // observation admitted by this terminal proof. Preserve any newer pin.
12
+ if (checkpoint && checkpoint.version >= reference.version)
13
+ continue;
14
+ await upsertPrincipalPolicyCheckpointInTransaction(input.transaction, reference, updatedAt, input.organizationId);
15
+ }
16
+ }
17
+ //# sourceMappingURL=documentPurgePolicyCheckpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentPurgePolicyCheckpoints.js","sourceRoot":"","sources":["documentPurgePolicyCheckpoints.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,+BAA+B,GAGhC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mCAAmC,EACnC,4CAA4C,GAC7C,MAAM,4CAA4C,CAAC;AAGpD,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,mCAAmC,CAAC,KAKzD;IACC,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACpC,IACE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9B,+BAA+B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CACvD;YAED,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,uCAAuC,CACxC,CAAC;QACJ,MAAM,UAAU,GAAG,MAAM,mCAAmC,CAC1D,KAAK,CAAC,WAAW,EACjB,SAAS,CACV,CAAC;QACF,2EAA2E;QAC3E,uEAAuE;QACvE,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO,IAAI,SAAS,CAAC,OAAO;YAAE,SAAS;QACpE,MAAM,4CAA4C,CAChD,KAAK,CAAC,WAAW,EACjB,SAAS,EACT,SAAS,EACT,KAAK,CAAC,cAAc,CACrB,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n principalPolicyMatchesReference,\n type ReferencedPrincipalHead,\n type VerifiedPrincipalPolicySelection,\n} from \"@tearleads/crypto\";\nimport {\n loadStoredPrincipalPolicyCheckpoint,\n upsertPrincipalPolicyCheckpointInTransaction,\n} from \"../persistence/keyingCheckpointPersistence\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\n\n/** After complete terminal-proof currency validation, admit only its bound sources. */\nexport async function admitDocumentPurgePolicyCheckpoints(input: {\n readonly transaction: ClientSQLiteTransactionScope;\n readonly organizationId: string | undefined;\n readonly policies: readonly VerifiedPrincipalPolicySelection[];\n readonly heads: readonly ReferencedPrincipalHead[];\n}): Promise<void> {\n const updatedAt = new Date().toISOString();\n for (const reference of input.heads) {\n if (\n !input.policies.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n )\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Purge source lacks verified inclusion\",\n );\n const checkpoint = await loadStoredPrincipalPolicyCheckpoint(\n input.transaction,\n reference,\n );\n // A newer privately authenticated prefix can prove ancestry, but is not an\n // observation admitted by this terminal proof. Preserve any newer pin.\n if (checkpoint && checkpoint.version >= reference.version) continue;\n await upsertPrincipalPolicyCheckpointInTransaction(\n input.transaction,\n reference,\n updatedAt,\n input.organizationId,\n );\n }\n}\n"]}
@@ -0,0 +1,55 @@
1
+ import { KeyingVerificationError, principalPolicyMatchesReference, } from "../../internal/crypto/index.js";
2
+ import { loadPrincipalPolicyCheckpoint } from "../persistence/keyingCheckpointPersistence.js";
3
+ import { observeProjectionLifetime, projectionLifetimeGuard, } from "./projectionLifetimes.js";
4
+ import { assertProjectionVerificationCurrent, } from "./types.js";
5
+ /** Authenticate connections to newer device pins without extending terminal grants or admitting heads. */
6
+ export async function recoverDocumentPurgePolicyCurrency(input) {
7
+ const resolve = input.warmer?.resolveReference;
8
+ if (!resolve)
9
+ return [...input.policies];
10
+ const recoveryBatch = {};
11
+ const recovered = new Map();
12
+ const policies = [];
13
+ for (const policy of input.policies) {
14
+ // Returned leases may include their caller predicate. Pass the original
15
+ // lifetime, not the growing context guard, to avoid a recursive guard graph.
16
+ const stillCurrent = input.stillCurrent;
17
+ assertProjectionVerificationCurrent(projectionLifetimeGuard(input.context));
18
+ const checkpoint = await loadPrincipalPolicyCheckpoint(input.context.execSql, policy.principalType, policy.principalId);
19
+ if (!checkpoint || checkpoint.version <= policy.version) {
20
+ policies.push(policy);
21
+ continue;
22
+ }
23
+ const key = `${policy.principalType}:${policy.principalId}:${policy.stateHash}`;
24
+ let bridge = recovered.get(key);
25
+ if (!bridge) {
26
+ const reference = {
27
+ principalType: policy.principalType,
28
+ principalId: policy.principalId,
29
+ version: policy.version,
30
+ stateHash: policy.stateHash,
31
+ keyEpoch: policy.keyEpoch,
32
+ keyFingerprint: policy.state.keyFingerprint,
33
+ };
34
+ const result = await resolve({
35
+ organizationId: input.organizationId,
36
+ reference,
37
+ recoveryBatch,
38
+ preferLocalHistory: true,
39
+ stillCurrent,
40
+ });
41
+ assertProjectionVerificationCurrent(projectionLifetimeGuard(input.context));
42
+ assertProjectionVerificationCurrent(result.stillCurrent);
43
+ if (result.organizationId !== input.organizationId ||
44
+ !principalPolicyMatchesReference({ policy: result.policy, reference }))
45
+ throw new KeyingVerificationError("object_mismatch", "Purge currency recovery does not bind its historical policy");
46
+ observeProjectionLifetime(input.context, result.stillCurrent);
47
+ bridge = result.policy;
48
+ recovered.set(key, bridge);
49
+ }
50
+ policies.push(bridge);
51
+ }
52
+ assertProjectionVerificationCurrent(projectionLifetimeGuard(input.context));
53
+ return policies;
54
+ }
55
+ //# sourceMappingURL=documentPurgePolicyCurrency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentPurgePolicyCurrency.js","sourceRoot":"","sources":["documentPurgePolicyCurrency.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n principalPolicyMatchesReference,\n type VerifiedPrincipalPolicyCurrent,\n type VerifiedPrincipalPolicySelection,\n} from \"@tearleads/crypto\";\nimport { loadPrincipalPolicyCheckpoint } from \"../persistence/keyingCheckpointPersistence\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport {\n observeProjectionLifetime,\n projectionLifetimeGuard,\n} from \"./projectionLifetimes\";\nimport {\n assertProjectionVerificationCurrent,\n type ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\n\nexport type PurgePolicyCurrencyEvidence =\n | VerifiedPrincipalPolicySelection\n | VerifiedPrincipalPolicyCurrent;\n\n/** Authenticate connections to newer device pins without extending terminal grants or admitting heads. */\nexport async function recoverDocumentPurgePolicyCurrency(input: {\n readonly context: ProjectionCheckpointContext;\n readonly organizationId: string;\n readonly policies: readonly VerifiedPrincipalPolicySelection[];\n readonly warmer: ReferencedPrincipalPolicyWarmer | undefined;\n readonly stillCurrent: () => boolean;\n}): Promise<PurgePolicyCurrencyEvidence[]> {\n const resolve = input.warmer?.resolveReference;\n if (!resolve) return [...input.policies];\n const recoveryBatch = {};\n const recovered = new Map<string, VerifiedPrincipalPolicyCurrent>();\n const policies: PurgePolicyCurrencyEvidence[] = [];\n for (const policy of input.policies) {\n // Returned leases may include their caller predicate. Pass the original\n // lifetime, not the growing context guard, to avoid a recursive guard graph.\n const stillCurrent = input.stillCurrent;\n assertProjectionVerificationCurrent(projectionLifetimeGuard(input.context));\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n input.context.execSql,\n policy.principalType,\n policy.principalId,\n );\n if (!checkpoint || checkpoint.version <= policy.version) {\n policies.push(policy);\n continue;\n }\n const key = `${policy.principalType}:${policy.principalId}:${policy.stateHash}`;\n let bridge = recovered.get(key);\n if (!bridge) {\n const reference = {\n principalType: policy.principalType,\n principalId: policy.principalId,\n version: policy.version,\n stateHash: policy.stateHash,\n keyEpoch: policy.keyEpoch,\n keyFingerprint: policy.state.keyFingerprint,\n };\n const result = await resolve({\n organizationId: input.organizationId,\n reference,\n recoveryBatch,\n preferLocalHistory: true,\n stillCurrent,\n });\n assertProjectionVerificationCurrent(\n projectionLifetimeGuard(input.context),\n );\n assertProjectionVerificationCurrent(result.stillCurrent);\n if (\n result.organizationId !== input.organizationId ||\n !principalPolicyMatchesReference({ policy: result.policy, reference })\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Purge currency recovery does not bind its historical policy\",\n );\n observeProjectionLifetime(input.context, result.stillCurrent);\n bridge = result.policy;\n recovered.set(key, bridge);\n }\n policies.push(bridge);\n }\n assertProjectionVerificationCurrent(projectionLifetimeGuard(input.context));\n return policies;\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { KeyingVerificationError, principalPolicyMatchesReference, verifyDocumentPurgeEvent, } from "../../internal/crypto/index.js";
2
+ import { parseOrganizationAuthorityDescriptor } from "../principals/organizationAuthorityDescriptor.js";
2
3
  import { verifyStandaloneAccessEventBundle } from "./bundleVerification.js";
3
4
  import { verifyPurgeDocumentManifest } from "./documentPurgeDocumentChainVerification.js";
4
5
  function principalIdentity(input) {
@@ -26,25 +27,31 @@ function collectEvidenceContainerManifests(input) {
26
27
  return [...selected.values()];
27
28
  }
28
29
  function requireExactPurgePrincipalEvidence(input) {
29
- const pendingReferences = input.verifiedContainerManifests.flatMap((manifest) => manifest.state.referencedPrincipalHeads);
30
- const requiredByPrincipal = new Map();
31
- while (pendingReferences.length > 0) {
32
- const reference = pendingReferences.shift();
33
- if (!reference)
34
- break;
30
+ const references = input.verifiedContainerManifests.flatMap((manifest) => manifest.state.referencedPrincipalHeads);
31
+ const requiredByPrincipal = new Set();
32
+ for (const reference of references) {
35
33
  const policy = input.authorizationEvidence.find((candidate) => principalPolicyMatchesReference({ policy: candidate, reference }));
36
34
  if (!policy) {
37
35
  throw new KeyingVerificationError("missing_dependency", "Document purge proof omits referenced principal policy evidence");
38
36
  }
39
37
  const identity = principalIdentity(policy);
40
- if (requiredByPrincipal.has(identity))
41
- continue;
42
- requiredByPrincipal.set(identity, policy);
43
- pendingReferences.push(...(policy.history ?? []).flatMap((entry) => entry.state.externalAuthority ? [entry.state.externalAuthority] : []));
38
+ requiredByPrincipal.add(identity);
39
+ // External authority is verified incrementally by paged recovery. Its
40
+ // historical entries need not be copied into this returned selection.
44
41
  }
45
- if (requiredByPrincipal.size !== input.authorizationEvidence.length) {
46
- throw new KeyingVerificationError("invalid_shape", "Document purge proof includes unrelated principal policy evidence");
42
+ const allowed = new Set(requiredByPrincipal);
43
+ // Paged recovery has authenticated these payloads against their signed
44
+ // organization states and verified their exact group-head bindings. This
45
+ // identity allow-list cannot authenticate an unverified directory payload.
46
+ for (const { payload } of input.policyEvidence.organizationPayloads) {
47
+ const directory = parseOrganizationAuthorityDescriptor(payload.ciphertext);
48
+ if (directory.groupHeads.some((head) => allowed.has(principalIdentity(head)))) {
49
+ allowed.add(`group:${directory.adminGroupId}`);
50
+ allowed.add(`organization:${directory.organizationId}`);
51
+ }
47
52
  }
53
+ if (input.authorizationEvidence.some((policy) => !allowed.has(principalIdentity(policy))))
54
+ throw new KeyingVerificationError("invalid_shape", "Document purge proof includes unrelated principal policy evidence");
48
55
  return input.authorizationEvidence.filter((policy) => requiredByPrincipal.has(principalIdentity(policy)));
49
56
  }
50
57
  async function authenticateDocumentPurgeEvent(input) {
@@ -60,6 +67,7 @@ async function authenticateDocumentPurgeEvent(input) {
60
67
  const principalPolicies = requireExactPurgePrincipalEvidence({
61
68
  authorizationEvidence: input.authorizationEvidence,
62
69
  verifiedContainerManifests: evidenceContainerManifests,
70
+ policyEvidence: input.policyEvidence,
63
71
  });
64
72
  const verified = await verifyDocumentPurgeEvent({
65
73
  authorizingContainerPath: input.authorizingContainerPath,
@@ -70,7 +78,10 @@ async function authenticateDocumentPurgeEvent(input) {
70
78
  });
71
79
  if (!verified.ok)
72
80
  throw verified.error;
73
- return { principalPolicies, purgeEventHash: verified.value.eventHash };
81
+ return {
82
+ principalPolicies: [...input.authorizationEvidence],
83
+ purgeEventHash: verified.value.eventHash,
84
+ };
74
85
  }
75
86
  export async function authenticateDocumentPurgeArtifacts(input) {
76
87
  const usedContainerManifests = new Map();
@@ -92,6 +103,7 @@ export async function authenticateDocumentPurgeArtifacts(input) {
92
103
  documentManifest,
93
104
  expectedDocumentId: input.expectedDocumentId,
94
105
  purgeEvent: input.proof.purgeEvent,
106
+ policyEvidence: input.proof.policyEvidence,
95
107
  resolveUserKey: input.resolveUserKey,
96
108
  rootContainerManifests: [
97
109
  ...input.authorizingContainerPath,
@@ -1 +1 @@
1
- {"version":3,"file":"documentPurgePrincipalEvidence.js","sourceRoot":"","sources":["documentPurgePrincipalEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n principalPolicyMatchesReference,\n type ReferencedPrincipalHead,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n type VerifiedPrincipalPolicySnapshot,\n verifyDocumentPurgeEvent,\n} from \"@tearleads/crypto\";\nimport type { DocumentPurgeProofResponse } from \"@tearleads/validators/response\";\nimport { verifyStandaloneAccessEventBundle } from \"./bundleVerification\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport { verifyPurgeDocumentManifest } from \"./documentPurgeDocumentChainVerification\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\nfunction principalIdentity(input: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${input.principalType}:${input.principalId}`;\n}\n\nfunction collectEvidenceContainerManifests(input: {\n readonly roots: readonly VerifiedContainerAccessManifest[];\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): VerifiedContainerAccessManifest[] {\n const selected = new Map<string, VerifiedContainerAccessManifest>();\n const pending = [...input.roots];\n while (pending.length > 0) {\n const manifest = pending.shift();\n if (!manifest || selected.has(manifest.manifestHash)) continue;\n selected.set(manifest.manifestHash, manifest);\n for (const dependencyHash of [\n manifest.manifest.previousManifestHash,\n manifest.state.parentManifestHash,\n ]) {\n if (!dependencyHash) continue;\n const dependency = input.verifiedByHash.get(dependencyHash);\n if (dependency) pending.push(dependency);\n }\n }\n return [...selected.values()];\n}\n\nfunction requireExactPurgePrincipalEvidence<\n TPolicy extends AnyVerifiedPrincipalPolicy,\n>(input: {\n readonly authorizationEvidence: readonly TPolicy[];\n readonly verifiedContainerManifests: readonly VerifiedContainerAccessManifest[];\n}): TPolicy[] {\n const pendingReferences: ReferencedPrincipalHead[] =\n input.verifiedContainerManifests.flatMap(\n (manifest) => manifest.state.referencedPrincipalHeads,\n );\n const requiredByPrincipal = new Map<string, TPolicy>();\n\n while (pendingReferences.length > 0) {\n const reference = pendingReferences.shift();\n if (!reference) break;\n const policy = input.authorizationEvidence.find((candidate) =>\n principalPolicyMatchesReference({ policy: candidate, reference }),\n );\n if (!policy) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Document purge proof omits referenced principal policy evidence\",\n );\n }\n const identity = principalIdentity(policy);\n if (requiredByPrincipal.has(identity)) continue;\n requiredByPrincipal.set(identity, policy);\n pendingReferences.push(\n ...(policy.history ?? []).flatMap((entry) =>\n entry.state.externalAuthority ? [entry.state.externalAuthority] : [],\n ),\n );\n }\n\n if (requiredByPrincipal.size !== input.authorizationEvidence.length) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Document purge proof includes unrelated principal policy evidence\",\n );\n }\n return input.authorizationEvidence.filter((policy) =>\n requiredByPrincipal.has(principalIdentity(policy)),\n );\n}\n\nasync function authenticateDocumentPurgeEvent(input: {\n readonly authorizationEvidence: readonly VerifiedPrincipalPolicySnapshot[];\n readonly authorizingContainerPath: readonly VerifiedContainerAccessManifest[];\n readonly documentManifest:\n | VerifiedDocumentLinkSetManifest\n | VerifiedDocumentLinkSetSnapshot;\n readonly expectedDocumentId: string;\n readonly purgeEvent: DocumentPurgeProofResponse[\"purgeEvent\"];\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly rootContainerManifests: readonly VerifiedContainerAccessManifest[];\n readonly verifiedContainerManifests: ReadonlyMap<\n string,\n VerifiedContainerAccessManifest\n >;\n}): Promise<{\n readonly principalPolicies: VerifiedPrincipalPolicySnapshot[];\n readonly purgeEventHash: string;\n}> {\n const event = await verifyStandaloneAccessEventBundle({\n bundle: input.purgeEvent,\n label: \"Document purge event\",\n resolveUserKey: input.resolveUserKey,\n });\n const evidenceContainerManifests = collectEvidenceContainerManifests({\n roots: input.rootContainerManifests,\n verifiedByHash: input.verifiedContainerManifests,\n });\n const principalPolicies = requireExactPurgePrincipalEvidence({\n authorizationEvidence: input.authorizationEvidence,\n verifiedContainerManifests: evidenceContainerManifests,\n });\n const verified = await verifyDocumentPurgeEvent({\n authorizingContainerPath: input.authorizingContainerPath,\n documentManifest: input.documentManifest,\n event,\n expectedDocumentId: input.expectedDocumentId,\n principalPolicies,\n });\n if (!verified.ok) throw verified.error;\n return { principalPolicies, purgeEventHash: verified.value.eventHash };\n}\n\nexport async function authenticateDocumentPurgeArtifacts(input: {\n readonly authorizationEvidence: readonly VerifiedPrincipalPolicySnapshot[];\n readonly authorizingContainerPath: readonly VerifiedContainerAccessManifest[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly expectedDocumentId: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly verifiedContainerManifests: ReadonlyMap<\n string,\n VerifiedContainerAccessManifest\n >;\n}) {\n const usedContainerManifests = new Map<\n string,\n VerifiedContainerAccessManifest\n >();\n const documentManifest = await verifyPurgeDocumentManifest({\n authorizationEvidence: input.authorizationEvidence,\n checkpointContext: input.checkpointContext,\n containerPathByManifestHash: input.containerPathByManifestHash,\n enforceLocalCheckpoints: input.enforceLocalCheckpoints,\n principalPolicyCache: input.principalPolicyCache,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n usedContainerManifests,\n });\n return {\n documentManifest,\n ...(await authenticateDocumentPurgeEvent({\n authorizationEvidence: input.authorizationEvidence,\n authorizingContainerPath: input.authorizingContainerPath,\n documentManifest,\n expectedDocumentId: input.expectedDocumentId,\n purgeEvent: input.proof.purgeEvent,\n resolveUserKey: input.resolveUserKey,\n rootContainerManifests: [\n ...input.authorizingContainerPath,\n ...usedContainerManifests.values(),\n ],\n verifiedContainerManifests: input.verifiedContainerManifests,\n })),\n };\n}\n"]}
1
+ {"version":3,"file":"documentPurgePrincipalEvidence.js","sourceRoot":"","sources":["documentPurgePrincipalEvidence.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EAEvB,+BAA+B,EAM/B,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,oCAAoC,EAAE,MAAM,+CAA+C,CAAC;AACrG,OAAO,EAAE,iCAAiC,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AAGvF,SAAS,iBAAiB,CAAC,KAG1B;IACC,OAAO,GAAG,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;AACvD,CAAC;AAED,SAAS,iCAAiC,CAAC,KAG1C;IACC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2C,CAAC;IACpE,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,SAAS;QAC/D,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC9C,KAAK,MAAM,cAAc,IAAI;YAC3B,QAAQ,CAAC,QAAQ,CAAC,oBAAoB;YACtC,QAAQ,CAAC,KAAK,CAAC,kBAAkB;SAClC,EAAE,CAAC;YACF,IAAI,CAAC,cAAc;gBAAE,SAAS;YAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC5D,IAAI,UAAU;gBAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,kCAAkC,CAEzC,KAID;IACC,MAAM,UAAU,GACd,KAAK,CAAC,0BAA0B,CAAC,OAAO,CACtC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,wBAAwB,CACtD,CAAC;IACJ,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE9C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAC5D,+BAA+B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAClE,CAAC;QACF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,iEAAiE,CAClE,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC3C,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,sEAAsE;QACtE,sEAAsE;IACxE,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC7C,uEAAuE;IACvE,yEAAyE;IACzE,2EAA2E;IAC3E,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,KAAK,CAAC,cAAc,CAAC,oBAAoB,EAAE,CAAC;QACpE,MAAM,SAAS,GAAG,oCAAoC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3E,IACE,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EACzE,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,SAAS,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,gBAAgB,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,IACE,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAC9B,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CACpD;QAED,MAAM,IAAI,uBAAuB,CAC/B,eAAe,EACf,mEAAmE,CACpE,CAAC;IACJ,OAAO,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACnD,mBAAmB,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CACnD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,KAe7C;IAIC,MAAM,KAAK,GAAG,MAAM,iCAAiC,CAAC;QACpD,MAAM,EAAE,KAAK,CAAC,UAAU;QACxB,KAAK,EAAE,sBAAsB;QAC7B,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC,CAAC;IACH,MAAM,0BAA0B,GAAG,iCAAiC,CAAC;QACnE,KAAK,EAAE,KAAK,CAAC,sBAAsB;QACnC,cAAc,EAAE,KAAK,CAAC,0BAA0B;KACjD,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;QAC3D,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;QAClD,0BAA0B,EAAE,0BAA0B;QACtD,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC;QAC9C,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;QACxD,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,KAAK;QACL,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,iBAAiB;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,QAAQ,CAAC,KAAK,CAAC;IACvC,OAAO;QACL,iBAAiB,EAAE,CAAC,GAAG,KAAK,CAAC,qBAAqB,CAAC;QACnD,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CAAC,KAiBxD;IACC,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAGnC,CAAC;IACJ,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,CAAC;QACzD,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;QAClD,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,2BAA2B,EAAE,KAAK,CAAC,2BAA2B;QAC9D,uBAAuB,EAAE,KAAK,CAAC,uBAAuB;QACtD,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,sBAAsB;KACvB,CAAC,CAAC;IACH,OAAO;QACL,gBAAgB;QAChB,GAAG,CAAC,MAAM,8BAA8B,CAAC;YACvC,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;YAClD,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;YACxD,gBAAgB;YAChB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;YAC5C,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU;YAClC,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc;YAC1C,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,sBAAsB,EAAE;gBACtB,GAAG,KAAK,CAAC,wBAAwB;gBACjC,GAAG,sBAAsB,CAAC,MAAM,EAAE;aACnC;YACD,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;SAC7D,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyAuthorization,\n principalPolicyMatchesReference,\n type ReferencedPrincipalHead,\n type VerifiedContainerAccessManifest,\n type VerifiedDocumentLinkSetManifest,\n type VerifiedDocumentLinkSetSnapshot,\n type VerifiedPrincipalPolicySelection,\n verifyDocumentPurgeEvent,\n} from \"@tearleads/crypto\";\nimport type { DocumentPurgeProofResponse } from \"@tearleads/validators/response\";\nimport { parseOrganizationAuthorityDescriptor } from \"../principals/organizationAuthorityDescriptor\";\nimport { verifyStandaloneAccessEventBundle } from \"./bundleVerification\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport { verifyPurgeDocumentManifest } from \"./documentPurgeDocumentChainVerification\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\nfunction principalIdentity(input: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${input.principalType}:${input.principalId}`;\n}\n\nfunction collectEvidenceContainerManifests(input: {\n readonly roots: readonly VerifiedContainerAccessManifest[];\n readonly verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): VerifiedContainerAccessManifest[] {\n const selected = new Map<string, VerifiedContainerAccessManifest>();\n const pending = [...input.roots];\n while (pending.length > 0) {\n const manifest = pending.shift();\n if (!manifest || selected.has(manifest.manifestHash)) continue;\n selected.set(manifest.manifestHash, manifest);\n for (const dependencyHash of [\n manifest.manifest.previousManifestHash,\n manifest.state.parentManifestHash,\n ]) {\n if (!dependencyHash) continue;\n const dependency = input.verifiedByHash.get(dependencyHash);\n if (dependency) pending.push(dependency);\n }\n }\n return [...selected.values()];\n}\n\nfunction requireExactPurgePrincipalEvidence<\n TPolicy extends PrincipalPolicyAuthorization,\n>(input: {\n readonly authorizationEvidence: readonly TPolicy[];\n readonly verifiedContainerManifests: readonly VerifiedContainerAccessManifest[];\n readonly policyEvidence: DocumentPurgeProofResponse[\"policyEvidence\"];\n}): TPolicy[] {\n const references: ReferencedPrincipalHead[] =\n input.verifiedContainerManifests.flatMap(\n (manifest) => manifest.state.referencedPrincipalHeads,\n );\n const requiredByPrincipal = new Set<string>();\n\n for (const reference of references) {\n const policy = input.authorizationEvidence.find((candidate) =>\n principalPolicyMatchesReference({ policy: candidate, reference }),\n );\n if (!policy) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Document purge proof omits referenced principal policy evidence\",\n );\n }\n const identity = principalIdentity(policy);\n requiredByPrincipal.add(identity);\n // External authority is verified incrementally by paged recovery. Its\n // historical entries need not be copied into this returned selection.\n }\n\n const allowed = new Set(requiredByPrincipal);\n // Paged recovery has authenticated these payloads against their signed\n // organization states and verified their exact group-head bindings. This\n // identity allow-list cannot authenticate an unverified directory payload.\n for (const { payload } of input.policyEvidence.organizationPayloads) {\n const directory = parseOrganizationAuthorityDescriptor(payload.ciphertext);\n if (\n directory.groupHeads.some((head) => allowed.has(principalIdentity(head)))\n ) {\n allowed.add(`group:${directory.adminGroupId}`);\n allowed.add(`organization:${directory.organizationId}`);\n }\n }\n if (\n input.authorizationEvidence.some(\n (policy) => !allowed.has(principalIdentity(policy)),\n )\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Document purge proof includes unrelated principal policy evidence\",\n );\n return input.authorizationEvidence.filter((policy) =>\n requiredByPrincipal.has(principalIdentity(policy)),\n );\n}\n\nasync function authenticateDocumentPurgeEvent(input: {\n readonly authorizationEvidence: readonly VerifiedPrincipalPolicySelection[];\n readonly authorizingContainerPath: readonly VerifiedContainerAccessManifest[];\n readonly documentManifest:\n | VerifiedDocumentLinkSetManifest\n | VerifiedDocumentLinkSetSnapshot;\n readonly expectedDocumentId: string;\n readonly purgeEvent: DocumentPurgeProofResponse[\"purgeEvent\"];\n readonly policyEvidence: DocumentPurgeProofResponse[\"policyEvidence\"];\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly rootContainerManifests: readonly VerifiedContainerAccessManifest[];\n readonly verifiedContainerManifests: ReadonlyMap<\n string,\n VerifiedContainerAccessManifest\n >;\n}): Promise<{\n readonly principalPolicies: VerifiedPrincipalPolicySelection[];\n readonly purgeEventHash: string;\n}> {\n const event = await verifyStandaloneAccessEventBundle({\n bundle: input.purgeEvent,\n label: \"Document purge event\",\n resolveUserKey: input.resolveUserKey,\n });\n const evidenceContainerManifests = collectEvidenceContainerManifests({\n roots: input.rootContainerManifests,\n verifiedByHash: input.verifiedContainerManifests,\n });\n const principalPolicies = requireExactPurgePrincipalEvidence({\n authorizationEvidence: input.authorizationEvidence,\n verifiedContainerManifests: evidenceContainerManifests,\n policyEvidence: input.policyEvidence,\n });\n const verified = await verifyDocumentPurgeEvent({\n authorizingContainerPath: input.authorizingContainerPath,\n documentManifest: input.documentManifest,\n event,\n expectedDocumentId: input.expectedDocumentId,\n principalPolicies,\n });\n if (!verified.ok) throw verified.error;\n return {\n principalPolicies: [...input.authorizationEvidence],\n purgeEventHash: verified.value.eventHash,\n };\n}\n\nexport async function authenticateDocumentPurgeArtifacts(input: {\n readonly authorizationEvidence: readonly VerifiedPrincipalPolicySelection[];\n readonly authorizingContainerPath: readonly VerifiedContainerAccessManifest[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly enforceLocalCheckpoints: boolean;\n readonly expectedDocumentId: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly verifiedContainerManifests: ReadonlyMap<\n string,\n VerifiedContainerAccessManifest\n >;\n}) {\n const usedContainerManifests = new Map<\n string,\n VerifiedContainerAccessManifest\n >();\n const documentManifest = await verifyPurgeDocumentManifest({\n authorizationEvidence: input.authorizationEvidence,\n checkpointContext: input.checkpointContext,\n containerPathByManifestHash: input.containerPathByManifestHash,\n enforceLocalCheckpoints: input.enforceLocalCheckpoints,\n principalPolicyCache: input.principalPolicyCache,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n usedContainerManifests,\n });\n return {\n documentManifest,\n ...(await authenticateDocumentPurgeEvent({\n authorizationEvidence: input.authorizationEvidence,\n authorizingContainerPath: input.authorizingContainerPath,\n documentManifest,\n expectedDocumentId: input.expectedDocumentId,\n purgeEvent: input.proof.purgeEvent,\n policyEvidence: input.proof.policyEvidence,\n resolveUserKey: input.resolveUserKey,\n rootContainerManifests: [\n ...input.authorizingContainerPath,\n ...usedContainerManifests.values(),\n ],\n verifiedContainerManifests: input.verifiedContainerManifests,\n })),\n };\n}\n"]}
@@ -1,9 +1,11 @@
1
- import { type AccessManifestCheckpoint, type AnyVerifiedPrincipalPolicy, type VerifiedContainerAccessManifest } from "../../internal/crypto/index.js";
1
+ import { type AccessManifestCheckpoint, type PrincipalPolicyAuthorization, type VerifiedContainerAccessManifest } from "../../internal/crypto/index.js";
2
2
  import type { DocumentPurgeProofResponse } from "../../internal/validators/response/index.js";
3
3
  import type { ExecSql } from "../sqlite/sqlSchema.js";
4
4
  import { createProjectionCheckpointContext } from "./checkpointContext.js";
5
- import type { PrincipalPolicyCache, ProjectionUserKeyResolver } from "./types.js";
5
+ import { type PrincipalPolicyCache, type ProjectionUserKeyResolver, type ReferencedPrincipalPolicyWarmer } from "./types.js";
6
6
  interface VerifyDocumentPurgeProofInput {
7
+ readonly stillCurrent?: (() => boolean) | undefined;
8
+ readonly warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;
7
9
  readonly execSql: ExecSql;
8
10
  readonly expectedDocumentId: string;
9
11
  readonly expectedOrganizationId: string;
@@ -17,7 +19,7 @@ interface VerifiedDocumentPurgeProofCommit {
17
19
  }
18
20
  type PurgeContainerEvidence = Pick<DocumentPurgeProofResponse, "authorizingContainerPath" | "documentContainerManifestHistory" | "documentManifestContainerPaths">;
19
21
  export declare function verifyPurgeContainerPaths(input: {
20
- readonly authorizationEvidence: readonly AnyVerifiedPrincipalPolicy[];
22
+ readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];
21
23
  readonly checkpointContext: ReturnType<typeof createProjectionCheckpointContext>;
22
24
  readonly principalPolicyCache: PrincipalPolicyCache;
23
25
  readonly proof: PurgeContainerEvidence;
@@ -5,8 +5,12 @@ import { createProjectionCheckpointContext, observeAccessManifestCheckpoints, }
5
5
  import { verifyContainerManifestPath } from "./containerPathVerification.js";
6
6
  import { verifiedContainerManifestsForBundles } from "./containerProjectionVerification.js";
7
7
  import { commitDocumentPurgeCheckpoints, validateDocumentPurgeCheckpoints, } from "./documentPurgeCheckpointCurrency.js";
8
+ import { recoverDocumentPurgePolicyCurrency } from "./documentPurgePolicyCurrency.js";
8
9
  import { authenticateDocumentPurgeArtifacts } from "./documentPurgePrincipalEvidence.js";
9
- import { verifyPrincipalPolicySnapshots } from "./principalPolicySnapshotVerification.js";
10
+ import { observeProjectionLifetime } from "./projectionLifetimes.js";
11
+ import { verifyProjectionPolicyEvidence } from "./projectionPolicyEvidence.js";
12
+ import { readAccessManifest } from "./readers.js";
13
+ import { assertProjectionVerificationCurrent, } from "./types.js";
10
14
  function collectContainerBundles(proof) {
11
15
  const bundlesByHash = new Map();
12
16
  for (const [index, bundle] of proof.authorizingContainerPath.entries()) {
@@ -91,8 +95,36 @@ function requirePurgeProofShape(proof) {
91
95
  throw new KeyingVerificationError("invalid_shape", "Document purge proof has an invalid shape");
92
96
  }
93
97
  }
98
+ function requirePurgeOrganization(actual, expected) {
99
+ if (actual !== expected)
100
+ throw new KeyingVerificationError("object_mismatch", "Document purge proof belongs to another organization");
101
+ }
102
+ async function recoverPurgePolicyEvidence(input) {
103
+ const references = [...collectContainerBundles(input.proof).values()].flatMap((bundle) => readAccessManifest(bundle.manifest, "Purge container manifest")
104
+ .referencedPrincipalHeads);
105
+ if (!references.length &&
106
+ (input.proof.policyEvidence.organization ||
107
+ input.proof.policyEvidence.groups.length ||
108
+ input.proof.policyEvidence.organizationPayloads.length))
109
+ throw new KeyingVerificationError("invalid_shape", "Document purge proof includes unrelated principal policy evidence");
110
+ return verifyProjectionPolicyEvidence({
111
+ evidence: input.proof.policyEvidence,
112
+ organizationId: input.expectedOrganizationId,
113
+ references,
114
+ historicalProof: true,
115
+ stillCurrent: input.stillCurrent,
116
+ warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,
117
+ });
118
+ }
119
+ function purgePrincipalSourceHeads(proof) {
120
+ return [
121
+ proof.policyEvidence.organization,
122
+ ...proof.policyEvidence.groups,
123
+ ].flatMap((source) => (source ? [source.head] : []));
124
+ }
94
125
  async function verifyDocumentPurgeProofWithMode(input, enforceLocalCheckpoints) {
95
126
  requirePurgeProofShape(input.proof);
127
+ input = { ...input, proof: structuredClone(input.proof) };
96
128
  if (input.proof.documentId !== input.expectedDocumentId ||
97
129
  input.proof.documentManifest.manifestHash.length === 0) {
98
130
  throw new KeyingVerificationError("object_mismatch", "Document purge proof targets the wrong document");
@@ -102,10 +134,9 @@ async function verifyDocumentPurgeProofWithMode(input, enforceLocalCheckpoints)
102
134
  organizationId: input.expectedOrganizationId,
103
135
  });
104
136
  const principalPolicyCache = input.principalPolicyCache ?? new Map();
105
- const authorizationEvidence = await verifyPrincipalPolicySnapshots({
106
- resolveUserKey: input.resolveUserKey,
107
- snapshots: input.proof.principalPolicySnapshots,
108
- });
137
+ const recovered = await recoverPurgePolicyEvidence(input);
138
+ observeProjectionLifetime(checkpointContext, recovered.stillCurrent);
139
+ const authorizationEvidence = recovered.policies;
109
140
  const { authorizingContainerPath, containerPathByManifestHash, verifiedContainerManifests, } = await verifyPurgeContainerPaths({
110
141
  authorizationEvidence,
111
142
  checkpointContext,
@@ -125,14 +156,25 @@ async function verifyDocumentPurgeProofWithMode(input, enforceLocalCheckpoints)
125
156
  resolveUserKey: input.resolveUserKey,
126
157
  verifiedContainerManifests,
127
158
  });
128
- if (documentManifest.state.organizationId !== input.expectedOrganizationId) {
129
- throw new KeyingVerificationError("object_mismatch", "Document purge proof belongs to another organization");
130
- }
159
+ requirePurgeOrganization(documentManifest.state.organizationId, input.expectedOrganizationId);
160
+ const observedPrincipalHeads = purgePrincipalSourceHeads(input.proof);
161
+ assertProjectionVerificationCurrent(recovered.stillCurrent);
162
+ const currencyPolicies = enforceLocalCheckpoints
163
+ ? await recoverDocumentPurgePolicyCurrency({
164
+ context: checkpointContext,
165
+ organizationId: input.expectedOrganizationId,
166
+ policies: principalPolicies,
167
+ warmer: input.warmReferencedPrincipalPolicies,
168
+ stillCurrent: recovered.stillCurrent,
169
+ })
170
+ : principalPolicies;
131
171
  if (enforceLocalCheckpoints) {
132
172
  await validateDocumentPurgeCheckpoints({
133
173
  context: checkpointContext,
134
174
  execSql: input.execSql,
135
175
  principalPolicies,
176
+ currencyPolicies,
177
+ observedPrincipalHeads,
136
178
  });
137
179
  }
138
180
  const documentPurgeCheckpoint = {
@@ -147,6 +189,8 @@ async function verifyDocumentPurgeProofWithMode(input, enforceLocalCheckpoints)
147
189
  documentPurgeCheckpoint,
148
190
  execSql,
149
191
  principalPolicies,
192
+ currencyPolicies,
193
+ observedPrincipalHeads,
150
194
  }),
151
195
  documentCheckpoint: documentManifest.checkpoint,
152
196
  };
@@ -1 +1 @@
1
- {"version":3,"file":"documentPurgeProofVerification.js","sourceRoot":"","sources":["documentPurgeProofVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n type VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentPurgeProofResponse,\n} from \"@tearleads/validators/response\";\nimport { isDocumentPurgeProofResponse } from \"@tearleads/validators/response\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { addBundleByHash } from \"./bundleVerification\";\nimport {\n createProjectionCheckpointContext,\n observeAccessManifestCheckpoints,\n} from \"./checkpointContext\";\nimport { verifyContainerManifestPath } from \"./containerPathVerification\";\nimport { verifiedContainerManifestsForBundles } from \"./containerProjectionVerification\";\nimport {\n commitDocumentPurgeCheckpoints,\n validateDocumentPurgeCheckpoints,\n} from \"./documentPurgeCheckpointCurrency\";\nimport { authenticateDocumentPurgeArtifacts } from \"./documentPurgePrincipalEvidence\";\nimport { verifyPrincipalPolicySnapshots } from \"./principalPolicySnapshotVerification\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\ninterface VerifyDocumentPurgeProofInput {\n readonly execSql: ExecSql;\n readonly expectedDocumentId: string;\n readonly expectedOrganizationId: string;\n readonly principalPolicyCache?: PrincipalPolicyCache | undefined;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}\n\ninterface VerifiedDocumentPurgeProofCommit {\n readonly commitCheckpoints: (execSql?: ExecSql) => Promise<void>;\n readonly documentCheckpoint: AccessManifestCheckpoint;\n}\n\ntype PurgeContainerEvidence = Pick<\n DocumentPurgeProofResponse,\n | \"authorizingContainerPath\"\n | \"documentContainerManifestHistory\"\n | \"documentManifestContainerPaths\"\n>;\n\nfunction collectContainerBundles(\n proof: PurgeContainerEvidence,\n): Map<string, AccessManifestBundleWireResponse> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n for (const [index, bundle] of proof.authorizingContainerPath.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge authorizing container path[${index}]`,\n );\n }\n for (const [\n index,\n bundle,\n ] of proof.documentContainerManifestHistory.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge container history[${index}]`,\n );\n }\n for (const [\n pathIndex,\n path,\n ] of proof.documentManifestContainerPaths.entries()) {\n for (const [bundleIndex, bundle] of path.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge dependency path[${pathIndex}][${bundleIndex}]`,\n );\n }\n }\n return bundlesByHash;\n}\n\nexport async function verifyPurgeContainerPaths(input: {\n readonly authorizationEvidence: readonly AnyVerifiedPrincipalPolicy[];\n readonly checkpointContext: ReturnType<\n typeof createProjectionCheckpointContext\n >;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: PurgeContainerEvidence;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}) {\n const bundlesByHash = collectContainerBundles(input.proof);\n const verifiedByHash = new Map<string, VerifiedContainerAccessManifest>();\n const authorizingContainerPath = await verifyContainerManifestPath({\n servedAsCurrent: false,\n authorizationMembership: \"referenced\",\n authorizationEvidence: input.authorizationEvidence,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n // Authenticate the signed path here; the complete purge's local currency\n // is checked after its event and document evidence have authenticated.\n enforceLocalCheckpoints: false,\n label: \"Document purge authorizing container path\",\n path: input.proof.authorizingContainerPath,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: true,\n verifiedByHash,\n });\n const authorizingLeaf = authorizingContainerPath.at(-1);\n if (!authorizingLeaf) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Document purge authorizing container path is empty\",\n );\n }\n const containerPathByManifestHash = new Map<\n string,\n readonly VerifiedContainerAccessManifest[]\n >();\n containerPathByManifestHash.set(authorizingLeaf.manifestHash, [\n ...authorizingContainerPath,\n ]);\n for (const [\n index,\n path,\n ] of input.proof.documentManifestContainerPaths.entries()) {\n const verifiedPath = await verifyContainerManifestPath({\n servedAsCurrent: false,\n authorizationMembership: \"referenced\",\n authorizationEvidence: input.authorizationEvidence,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n enforceLocalCheckpoints: false,\n label: `Document purge dependency path[${index}]`,\n path,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: true,\n verifiedByHash,\n });\n const leaf = verifiedPath.at(-1);\n if (leaf && !containerPathByManifestHash.has(leaf.manifestHash)) {\n containerPathByManifestHash.set(leaf.manifestHash, verifiedPath);\n }\n }\n // Purge verification consumes event citations only, never content-write\n // headers, so historical evidence needs no pinned target-path grouping.\n for (const [hash, manifest] of verifiedByHash) {\n if (!containerPathByManifestHash.has(hash)) {\n containerPathByManifestHash.set(hash, [manifest]);\n }\n }\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: authorizingContainerPath,\n verifiedManifests: verifiedContainerManifestsForBundles(\n bundlesByHash,\n verifiedByHash,\n ),\n });\n return {\n authorizingContainerPath,\n containerPathByManifestHash,\n verifiedContainerManifests: new Map(verifiedByHash),\n };\n}\n\nfunction requirePurgeProofShape(\n proof: unknown,\n): asserts proof is DocumentPurgeProofResponse {\n if (!isDocumentPurgeProofResponse(proof)) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Document purge proof has an invalid shape\",\n );\n }\n}\n\nasync function verifyDocumentPurgeProofWithMode(\n input: VerifyDocumentPurgeProofInput,\n enforceLocalCheckpoints: boolean,\n): Promise<VerifiedDocumentPurgeProofCommit> {\n requirePurgeProofShape(input.proof);\n if (\n input.proof.documentId !== input.expectedDocumentId ||\n input.proof.documentManifest.manifestHash.length === 0\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document purge proof targets the wrong document\",\n );\n }\n const checkpointContext = createProjectionCheckpointContext({\n execSql: input.execSql,\n organizationId: input.expectedOrganizationId,\n });\n const principalPolicyCache =\n input.principalPolicyCache ?? new Map<string, VerifiedPrincipalPolicy>();\n const authorizationEvidence = await verifyPrincipalPolicySnapshots({\n resolveUserKey: input.resolveUserKey,\n snapshots: input.proof.principalPolicySnapshots,\n });\n const {\n authorizingContainerPath,\n containerPathByManifestHash,\n verifiedContainerManifests,\n } = await verifyPurgeContainerPaths({\n authorizationEvidence,\n checkpointContext,\n principalPolicyCache,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n });\n const { documentManifest, principalPolicies, purgeEventHash } =\n await authenticateDocumentPurgeArtifacts({\n authorizationEvidence,\n authorizingContainerPath,\n checkpointContext,\n containerPathByManifestHash,\n enforceLocalCheckpoints,\n expectedDocumentId: input.expectedDocumentId,\n principalPolicyCache,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n verifiedContainerManifests,\n });\n if (documentManifest.state.organizationId !== input.expectedOrganizationId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document purge proof belongs to another organization\",\n );\n }\n if (enforceLocalCheckpoints) {\n await validateDocumentPurgeCheckpoints({\n context: checkpointContext,\n execSql: input.execSql,\n principalPolicies,\n });\n }\n const documentPurgeCheckpoint = {\n documentId: input.expectedDocumentId,\n documentManifestHash: documentManifest.manifestHash,\n organizationId: documentManifest.state.organizationId,\n purgeEventHash,\n };\n return {\n commitCheckpoints: (execSql = input.execSql) =>\n commitDocumentPurgeCheckpoints({\n context: checkpointContext,\n documentPurgeCheckpoint,\n execSql,\n principalPolicies,\n }),\n documentCheckpoint: documentManifest.checkpoint,\n };\n}\n\nexport async function verifyDocumentPurgeProofBaseline(\n input: VerifyDocumentPurgeProofInput,\n): Promise<Pick<VerifiedDocumentPurgeProofCommit, \"documentCheckpoint\">> {\n requirePurgeProofShape(input.proof);\n const verified = await verifyDocumentPurgeProofWithMode(input, false);\n return {\n documentCheckpoint: verified.documentCheckpoint,\n };\n}\n\nexport function verifyDocumentPurgeProof(\n input: VerifyDocumentPurgeProofInput,\n): Promise<VerifiedDocumentPurgeProofCommit> {\n return verifyDocumentPurgeProofWithMode(input, true);\n}\n"]}
1
+ {"version":3,"file":"documentPurgeProofVerification.js","sourceRoot":"","sources":["documentPurgeProofVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type PrincipalPolicyAuthorization,\n type VerifiedContainerAccessManifest,\n type VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentPurgeProofResponse,\n} from \"@tearleads/validators/response\";\nimport { isDocumentPurgeProofResponse } from \"@tearleads/validators/response\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { addBundleByHash } from \"./bundleVerification\";\nimport {\n createProjectionCheckpointContext,\n observeAccessManifestCheckpoints,\n} from \"./checkpointContext\";\nimport { verifyContainerManifestPath } from \"./containerPathVerification\";\nimport { verifiedContainerManifestsForBundles } from \"./containerProjectionVerification\";\nimport {\n commitDocumentPurgeCheckpoints,\n validateDocumentPurgeCheckpoints,\n} from \"./documentPurgeCheckpointCurrency\";\nimport { recoverDocumentPurgePolicyCurrency } from \"./documentPurgePolicyCurrency\";\nimport { authenticateDocumentPurgeArtifacts } from \"./documentPurgePrincipalEvidence\";\nimport { observeProjectionLifetime } from \"./projectionLifetimes\";\nimport { verifyProjectionPolicyEvidence } from \"./projectionPolicyEvidence\";\nimport { readAccessManifest } from \"./readers\";\nimport {\n assertProjectionVerificationCurrent,\n type PrincipalPolicyCache,\n type ProjectionUserKeyResolver,\n type ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\n\ninterface VerifyDocumentPurgeProofInput {\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n readonly execSql: ExecSql;\n readonly expectedDocumentId: string;\n readonly expectedOrganizationId: string;\n readonly principalPolicyCache?: PrincipalPolicyCache | undefined;\n readonly proof: DocumentPurgeProofResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}\n\ninterface VerifiedDocumentPurgeProofCommit {\n readonly commitCheckpoints: (execSql?: ExecSql) => Promise<void>;\n readonly documentCheckpoint: AccessManifestCheckpoint;\n}\n\ntype PurgeContainerEvidence = Pick<\n DocumentPurgeProofResponse,\n | \"authorizingContainerPath\"\n | \"documentContainerManifestHistory\"\n | \"documentManifestContainerPaths\"\n>;\n\nfunction collectContainerBundles(\n proof: PurgeContainerEvidence,\n): Map<string, AccessManifestBundleWireResponse> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n for (const [index, bundle] of proof.authorizingContainerPath.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge authorizing container path[${index}]`,\n );\n }\n for (const [\n index,\n bundle,\n ] of proof.documentContainerManifestHistory.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge container history[${index}]`,\n );\n }\n for (const [\n pathIndex,\n path,\n ] of proof.documentManifestContainerPaths.entries()) {\n for (const [bundleIndex, bundle] of path.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document purge dependency path[${pathIndex}][${bundleIndex}]`,\n );\n }\n }\n return bundlesByHash;\n}\n\nexport async function verifyPurgeContainerPaths(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ReturnType<\n typeof createProjectionCheckpointContext\n >;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly proof: PurgeContainerEvidence;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}) {\n const bundlesByHash = collectContainerBundles(input.proof);\n const verifiedByHash = new Map<string, VerifiedContainerAccessManifest>();\n const authorizingContainerPath = await verifyContainerManifestPath({\n servedAsCurrent: false,\n authorizationMembership: \"referenced\",\n authorizationEvidence: input.authorizationEvidence,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n // Authenticate the signed path here; the complete purge's local currency\n // is checked after its event and document evidence have authenticated.\n enforceLocalCheckpoints: false,\n label: \"Document purge authorizing container path\",\n path: input.proof.authorizingContainerPath,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: true,\n verifiedByHash,\n });\n const authorizingLeaf = authorizingContainerPath.at(-1);\n if (!authorizingLeaf) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Document purge authorizing container path is empty\",\n );\n }\n const containerPathByManifestHash = new Map<\n string,\n readonly VerifiedContainerAccessManifest[]\n >();\n containerPathByManifestHash.set(authorizingLeaf.manifestHash, [\n ...authorizingContainerPath,\n ]);\n for (const [\n index,\n path,\n ] of input.proof.documentManifestContainerPaths.entries()) {\n const verifiedPath = await verifyContainerManifestPath({\n servedAsCurrent: false,\n authorizationMembership: \"referenced\",\n authorizationEvidence: input.authorizationEvidence,\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n enforceLocalCheckpoints: false,\n label: `Document purge dependency path[${index}]`,\n path,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n requireAuthorizationEvidence: true,\n verifiedByHash,\n });\n const leaf = verifiedPath.at(-1);\n if (leaf && !containerPathByManifestHash.has(leaf.manifestHash)) {\n containerPathByManifestHash.set(leaf.manifestHash, verifiedPath);\n }\n }\n // Purge verification consumes event citations only, never content-write\n // headers, so historical evidence needs no pinned target-path grouping.\n for (const [hash, manifest] of verifiedByHash) {\n if (!containerPathByManifestHash.has(hash)) {\n containerPathByManifestHash.set(hash, [manifest]);\n }\n }\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: authorizingContainerPath,\n verifiedManifests: verifiedContainerManifestsForBundles(\n bundlesByHash,\n verifiedByHash,\n ),\n });\n return {\n authorizingContainerPath,\n containerPathByManifestHash,\n verifiedContainerManifests: new Map(verifiedByHash),\n };\n}\n\nfunction requirePurgeProofShape(\n proof: unknown,\n): asserts proof is DocumentPurgeProofResponse {\n if (!isDocumentPurgeProofResponse(proof)) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Document purge proof has an invalid shape\",\n );\n }\n}\n\nfunction requirePurgeOrganization(actual: string, expected: string): void {\n if (actual !== expected)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document purge proof belongs to another organization\",\n );\n}\n\nasync function recoverPurgePolicyEvidence(\n input: VerifyDocumentPurgeProofInput,\n) {\n const references = [...collectContainerBundles(input.proof).values()].flatMap(\n (bundle) =>\n readAccessManifest(bundle.manifest, \"Purge container manifest\")\n .referencedPrincipalHeads,\n );\n if (\n !references.length &&\n (input.proof.policyEvidence.organization ||\n input.proof.policyEvidence.groups.length ||\n input.proof.policyEvidence.organizationPayloads.length)\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Document purge proof includes unrelated principal policy evidence\",\n );\n return verifyProjectionPolicyEvidence({\n evidence: input.proof.policyEvidence,\n organizationId: input.expectedOrganizationId,\n references,\n historicalProof: true,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n}\n\nfunction purgePrincipalSourceHeads(proof: DocumentPurgeProofResponse) {\n return [\n proof.policyEvidence.organization,\n ...proof.policyEvidence.groups,\n ].flatMap((source) => (source ? [source.head] : []));\n}\n\nasync function verifyDocumentPurgeProofWithMode(\n input: VerifyDocumentPurgeProofInput,\n enforceLocalCheckpoints: boolean,\n): Promise<VerifiedDocumentPurgeProofCommit> {\n requirePurgeProofShape(input.proof);\n input = { ...input, proof: structuredClone(input.proof) };\n if (\n input.proof.documentId !== input.expectedDocumentId ||\n input.proof.documentManifest.manifestHash.length === 0\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Document purge proof targets the wrong document\",\n );\n }\n const checkpointContext = createProjectionCheckpointContext({\n execSql: input.execSql,\n organizationId: input.expectedOrganizationId,\n });\n const principalPolicyCache =\n input.principalPolicyCache ?? new Map<string, VerifiedPrincipalPolicy>();\n const recovered = await recoverPurgePolicyEvidence(input);\n observeProjectionLifetime(checkpointContext, recovered.stillCurrent);\n const authorizationEvidence = recovered.policies;\n const {\n authorizingContainerPath,\n containerPathByManifestHash,\n verifiedContainerManifests,\n } = await verifyPurgeContainerPaths({\n authorizationEvidence,\n checkpointContext,\n principalPolicyCache,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n });\n const { documentManifest, principalPolicies, purgeEventHash } =\n await authenticateDocumentPurgeArtifacts({\n authorizationEvidence,\n authorizingContainerPath,\n checkpointContext,\n containerPathByManifestHash,\n enforceLocalCheckpoints,\n expectedDocumentId: input.expectedDocumentId,\n principalPolicyCache,\n proof: input.proof,\n resolveUserKey: input.resolveUserKey,\n verifiedContainerManifests,\n });\n requirePurgeOrganization(\n documentManifest.state.organizationId,\n input.expectedOrganizationId,\n );\n const observedPrincipalHeads = purgePrincipalSourceHeads(input.proof);\n assertProjectionVerificationCurrent(recovered.stillCurrent);\n const currencyPolicies = enforceLocalCheckpoints\n ? await recoverDocumentPurgePolicyCurrency({\n context: checkpointContext,\n organizationId: input.expectedOrganizationId,\n policies: principalPolicies,\n warmer: input.warmReferencedPrincipalPolicies,\n stillCurrent: recovered.stillCurrent,\n })\n : principalPolicies;\n if (enforceLocalCheckpoints) {\n await validateDocumentPurgeCheckpoints({\n context: checkpointContext,\n execSql: input.execSql,\n principalPolicies,\n currencyPolicies,\n observedPrincipalHeads,\n });\n }\n const documentPurgeCheckpoint = {\n documentId: input.expectedDocumentId,\n documentManifestHash: documentManifest.manifestHash,\n organizationId: documentManifest.state.organizationId,\n purgeEventHash,\n };\n return {\n commitCheckpoints: (execSql = input.execSql) =>\n commitDocumentPurgeCheckpoints({\n context: checkpointContext,\n documentPurgeCheckpoint,\n execSql,\n principalPolicies,\n currencyPolicies,\n observedPrincipalHeads,\n }),\n documentCheckpoint: documentManifest.checkpoint,\n };\n}\n\nexport async function verifyDocumentPurgeProofBaseline(\n input: VerifyDocumentPurgeProofInput,\n): Promise<Pick<VerifiedDocumentPurgeProofCommit, \"documentCheckpoint\">> {\n requirePurgeProofShape(input.proof);\n const verified = await verifyDocumentPurgeProofWithMode(input, false);\n return {\n documentCheckpoint: verified.documentCheckpoint,\n };\n}\n\nexport function verifyDocumentPurgeProof(\n input: VerifyDocumentPurgeProofInput,\n): Promise<VerifiedDocumentPurgeProofCommit> {\n return verifyDocumentPurgeProofWithMode(input, true);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"projectionPolicyEvidence.js","sourceRoot":"","sources":["projectionPolicyEvidence.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,oCAAoC,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EACL,mCAAmC,GAGpC,MAAM,SAAS,CAAC;AAEjB,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,KAQpD;IACC,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,CAAC;IAC5D,mCAAmC,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QACjC,IACE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM;YAC5B,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,MAAM;YAC1C,KAAK,CAAC,UAAU,CAAC,MAAM;YAEvB,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,gDAAgD,CACjD,CAAC;QACJ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC;IACxC,CAAC;IACD,MAAM,OAAO,GACX,KAAK,CAAC,+BAA+B,EAAE,wBAAwB,CAAC;IAClE,IAAI,CAAC,OAAO;QACV,MAAM,IAAI,oCAAoC,CAC5C,oDAAoD,CACrD,CAAC;IACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IACzD,mCAAmC,CAAC,YAAY,CAAC,CAAC;IAClD,mCAAmC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n type ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { ProjectionPolicyEvidenceResponse } from \"@tearleads/validators/response\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport {\n assertProjectionVerificationCurrent,\n type ReferencedPrincipalPolicyWarmer,\n type ResolvedProjectionPolicyHistory,\n} from \"./types\";\n\n/** Recover public authorization without admitting historical heads as current policy. */\nexport async function verifyProjectionPolicyEvidence(input: {\n readonly evidence: ProjectionPolicyEvidenceResponse;\n readonly organizationId: string;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<ResolvedProjectionPolicyHistory> {\n const stillCurrent = () => input.stillCurrent?.() !== false;\n assertProjectionVerificationCurrent(stillCurrent);\n if (!input.evidence.organization) {\n if (\n input.evidence.groups.length ||\n input.evidence.organizationPayloads.length ||\n input.references.length\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Projection omits required organization history\",\n );\n return { policies: [], stillCurrent };\n }\n const resolve =\n input.warmReferencedPrincipalPolicies?.resolveProjectionHistory;\n if (!resolve)\n throw new ProjectionDependencyUnavailableError(\n \"Private projection history recovery is unavailable\",\n );\n const result = await resolve({ ...input, stillCurrent });\n assertProjectionVerificationCurrent(stillCurrent);\n assertProjectionVerificationCurrent(result.stillCurrent);\n return result;\n}\n"]}
1
+ {"version":3,"file":"projectionPolicyEvidence.js","sourceRoot":"","sources":["projectionPolicyEvidence.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,oCAAoC,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EACL,mCAAmC,GAGpC,MAAM,SAAS,CAAC;AAEjB,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,KASpD;IACC,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,CAAC;IAC5D,mCAAmC,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QACjC,IACE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM;YAC5B,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,MAAM;YAC1C,KAAK,CAAC,UAAU,CAAC,MAAM;YAEvB,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,gDAAgD,CACjD,CAAC;QACJ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC;IACxC,CAAC;IACD,MAAM,OAAO,GACX,KAAK,CAAC,+BAA+B,EAAE,wBAAwB,CAAC;IAClE,IAAI,CAAC,OAAO;QACV,MAAM,IAAI,oCAAoC,CAC5C,oDAAoD,CACrD,CAAC;IACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IACzD,mCAAmC,CAAC,YAAY,CAAC,CAAC;IAClD,mCAAmC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n type ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { ProjectionPolicyEvidenceResponse } from \"@tearleads/validators/response\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport {\n assertProjectionVerificationCurrent,\n type ReferencedPrincipalPolicyWarmer,\n type ResolvedProjectionPolicyHistory,\n} from \"./types\";\n\n/** Recover public authorization without admitting historical heads as current policy. */\nexport async function verifyProjectionPolicyEvidence(input: {\n readonly historicalProof?: boolean | undefined;\n readonly evidence: ProjectionPolicyEvidenceResponse;\n readonly organizationId: string;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<ResolvedProjectionPolicyHistory> {\n const stillCurrent = () => input.stillCurrent?.() !== false;\n assertProjectionVerificationCurrent(stillCurrent);\n if (!input.evidence.organization) {\n if (\n input.evidence.groups.length ||\n input.evidence.organizationPayloads.length ||\n input.references.length\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Projection omits required organization history\",\n );\n return { policies: [], stillCurrent };\n }\n const resolve =\n input.warmReferencedPrincipalPolicies?.resolveProjectionHistory;\n if (!resolve)\n throw new ProjectionDependencyUnavailableError(\n \"Private projection history recovery is unavailable\",\n );\n const result = await resolve({ ...input, stillCurrent });\n assertProjectionVerificationCurrent(stillCurrent);\n assertProjectionVerificationCurrent(result.stillCurrent);\n return result;\n}\n"]}