@tearleads/client-sdk 0.1.57 → 0.1.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/Tearleads.d.ts +2 -2
  2. package/Tearleads.js +1 -1
  3. package/Tearleads.js.map +1 -1
  4. package/client/blobs.d.ts +1 -1
  5. package/client/blobs.js.map +1 -1
  6. package/client/deviceFirst.js.map +1 -1
  7. package/client/identity.js +1 -1
  8. package/client/identity.js.map +1 -1
  9. package/client/index.d.ts +1 -1
  10. package/client/index.js +1 -1
  11. package/client/index.js.map +1 -1
  12. package/client/organizations/organizationAccessRestoration.js.map +1 -1
  13. package/client/organizations/organizationDataUsage.js.map +1 -1
  14. package/client/organizations/organizationGroupNameHydration.js.map +1 -1
  15. package/client/organizations/organizationMetadataProfileSync.js +1 -1
  16. package/client/organizations/organizationMetadataProfileSync.js.map +1 -1
  17. package/client/organizations/organizationReadModels.js.map +1 -1
  18. package/client/organizations/organizationWorkflowRuntime.js.map +1 -1
  19. package/client/rootContainerAdoption.js.map +1 -1
  20. package/client/securityIncidents.d.ts +1 -1
  21. package/client/securityIncidents.js.map +1 -1
  22. package/client/session/sessionLoginRefusal.js.map +1 -1
  23. package/client/session/sessionRootAuthority.js.map +1 -1
  24. package/client/session/sessionTypes.d.ts +1 -1
  25. package/client/session/sessionTypes.js.map +1 -1
  26. package/client/userIdentities.d.ts +1 -1
  27. package/client/userIdentities.js.map +1 -1
  28. package/client/workflowRuntime.d.ts +2 -2
  29. package/client/workflowRuntime.js.map +1 -1
  30. package/data/blobs/createBlobStore.d.ts +1 -1
  31. package/data/blobs/createBlobStore.js.map +1 -1
  32. package/data/blobs/encryptedBlobByteSource.js +1 -1
  33. package/data/blobs/encryptedBlobByteSource.js.map +1 -1
  34. package/data/blobs/encryptedBlobEnvelope.d.ts +1 -1
  35. package/data/blobs/encryptedBlobEnvelope.js +2 -2
  36. package/data/blobs/encryptedBlobEnvelope.js.map +1 -1
  37. package/data/blobs/encryptedBlobStore.d.ts +1 -1
  38. package/data/blobs/encryptedBlobStore.js +1 -1
  39. package/data/blobs/encryptedBlobStore.js.map +1 -1
  40. package/data/blobs/memoryBlobStore.d.ts +1 -1
  41. package/data/blobs/memoryBlobStore.js +1 -1
  42. package/data/blobs/memoryBlobStore.js.map +1 -1
  43. package/data/blobs/opfsBlobStore.d.ts +1 -1
  44. package/data/blobs/opfsBlobStore.js +1 -1
  45. package/data/blobs/opfsBlobStore.js.map +1 -1
  46. package/data/containers/containerMetadataDocument.js +1 -1
  47. package/data/containers/containerMetadataDocument.js.map +1 -1
  48. package/data/containers/shared/events.js +1 -1
  49. package/data/containers/shared/events.js.map +1 -1
  50. package/data/containers/shared/heldContainerHeads.js +1 -1
  51. package/data/containers/shared/heldContainerHeads.js.map +1 -1
  52. package/data/containers/shared/mutationAcknowledgement.js +1 -1
  53. package/data/containers/shared/mutationAcknowledgement.js.map +1 -1
  54. package/data/containers/shared/principalPolicies.js +1 -1
  55. package/data/containers/shared/principalPolicies.js.map +1 -1
  56. package/data/containers/shared/readers.js +2 -2
  57. package/data/containers/shared/readers.js.map +1 -1
  58. package/data/documents/attachmentContentIdentity.js +1 -1
  59. package/data/documents/attachmentContentIdentity.js.map +1 -1
  60. package/data/documents/blob/shared/blobEnvelopeStream.js.map +1 -1
  61. package/data/documents/blob/shared/blobSourceSnapshot.d.ts +1 -1
  62. package/data/documents/blob/shared/blobSourceSnapshot.js.map +1 -1
  63. package/data/documents/blob/shared/chunkedBlobCrypto.js.map +1 -1
  64. package/data/documents/blob/shared/encryptedUploadParts.js.map +1 -1
  65. package/data/documents/blob/shared/events.js +1 -1
  66. package/data/documents/blob/shared/events.js.map +1 -1
  67. package/data/documents/blob/shared/types.d.ts +2 -2
  68. package/data/documents/blob/shared/types.js.map +1 -1
  69. package/data/documents/shared/containerKekPathHistory.js +1 -1
  70. package/data/documents/shared/containerKekPathHistory.js.map +1 -1
  71. package/data/documents/shared/containerKekPathVerification.d.ts +1 -1
  72. package/data/documents/shared/containerKekPathVerification.js +1 -1
  73. package/data/documents/shared/events.js +1 -1
  74. package/data/documents/shared/events.js.map +1 -1
  75. package/data/documents/shared/manifestBundleReaders.js +2 -2
  76. package/data/documents/shared/manifestBundleReaders.js.map +1 -1
  77. package/data/documents/shared/projection.d.ts +1 -1
  78. package/data/documents/shared/projection.js +2 -2
  79. package/data/documents/shared/projection.js.map +1 -1
  80. package/data/documents/shared/projectionContentKeys.d.ts +1 -1
  81. package/data/documents/shared/readers.js +3 -3
  82. package/data/documents/shared/readers.js.map +1 -1
  83. package/data/documents/shared/stableDocumentId.js +1 -1
  84. package/data/documents/shared/stableDocumentId.js.map +1 -1
  85. package/data/documents/shared/types.d.ts +1 -1
  86. package/data/documents/shared/types.js +1 -1
  87. package/data/{keyingCanonicalJson.js → keying/canonicalJson.js} +3 -3
  88. package/data/keying/canonicalJson.js.map +1 -0
  89. package/data/keyingProjectionVerification/bundleVerification.js +1 -1
  90. package/data/keyingProjectionVerification/bundleVerification.js.map +1 -1
  91. package/data/keyingProjectionVerification/containerAncestorCitations.js +1 -1
  92. package/data/keyingProjectionVerification/containerAncestorCitations.js.map +1 -1
  93. package/data/keyingProjectionVerification/containerManifestVerification.js +1 -1
  94. package/data/keyingProjectionVerification/containerManifestVerification.js.map +1 -1
  95. package/data/keyingProjectionVerification/documentManifestVerification.js +1 -1
  96. package/data/keyingProjectionVerification/documentManifestVerification.js.map +1 -1
  97. package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js +1 -1
  98. package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
  99. package/data/keyingProjectionVerification/error.js +1 -1
  100. package/data/keyingProjectionVerification/error.js.map +1 -1
  101. package/data/keyingProjectionVerification/index.d.ts +9 -0
  102. package/data/{keyingProjectionVerification.js → keyingProjectionVerification/index.js} +8 -8
  103. package/data/keyingProjectionVerification/index.js.map +1 -0
  104. package/data/keyingProjectionVerification/principalPolicyCache.js +1 -1
  105. package/data/keyingProjectionVerification/principalPolicyCache.js.map +1 -1
  106. package/data/keyingProjectionVerification/principalPolicyVerification.js +1 -1
  107. package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
  108. package/data/keyingProjectionVerification/readers.d.ts +1 -1
  109. package/data/keyingProjectionVerification/readers.js +3 -3
  110. package/data/keyingProjectionVerification/readers.js.map +1 -1
  111. package/data/keyingProjectionVerification/userKeyResolver.d.ts +1 -1
  112. package/data/keyingProjectionVerification/userKeyResolver.js.map +1 -1
  113. package/data/persistence/containers/containerPersistence.js +1 -1
  114. package/data/persistence/containers/containerPersistence.js.map +1 -1
  115. package/data/persistence/documents/documentDiscoveryCandidate.js +1 -1
  116. package/data/persistence/documents/documentDiscoveryCandidate.js.map +1 -1
  117. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js +1 -1
  118. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js.map +1 -1
  119. package/data/persistence/documents/internal/documentProjectionRows.js +1 -1
  120. package/data/persistence/documents/internal/documentProjectionRows.js.map +1 -1
  121. package/data/persistence/documents/internal/documentRows.js +1 -1
  122. package/data/persistence/documents/internal/documentRows.js.map +1 -1
  123. package/data/persistence/principalPolicyBundleIntegrity.js +1 -1
  124. package/data/persistence/principalPolicyBundleIntegrity.js.map +1 -1
  125. package/data/persistence/principalPolicyReferenceCheckpoint.js +1 -1
  126. package/data/persistence/principalPolicyReferenceCheckpoint.js.map +1 -1
  127. package/data/persistence/principalPolicyReferenceIndexPersistence.js +1 -1
  128. package/data/persistence/principalPolicyReferenceIndexPersistence.js.map +1 -1
  129. package/data/persistence/principalPolicyReferencePersistence.js +1 -1
  130. package/data/persistence/principalPolicyReferencePersistence.js.map +1 -1
  131. package/data/persistence/securityIncidentPersistence.js.map +1 -1
  132. package/data/persistence/verifiedPrincipalPolicyBundle.js +1 -1
  133. package/data/persistence/verifiedPrincipalPolicyBundle.js.map +1 -1
  134. package/data/persistence/verifiedPrincipalPolicyCurrent.js +1 -1
  135. package/data/persistence/verifiedPrincipalPolicyCurrent.js.map +1 -1
  136. package/data/principals/principalMutationJournal.js +1 -1
  137. package/data/principals/principalMutationJournal.js.map +1 -1
  138. package/data/{securityIncidents.d.ts → shared/securityIncidents.d.ts} +1 -1
  139. package/data/sqlite/documentRecordPersistence.js +1 -1
  140. package/data/sqlite/documentRecordPersistence.js.map +1 -1
  141. package/data/sync/crdtPeerSeed.d.ts +18 -0
  142. package/data/sync/originatedDocuments.d.ts +1 -1
  143. package/data/sync/originatedDocuments.js.map +1 -1
  144. package/data/sync/syncCoordinator.d.ts +1 -1
  145. package/data/sync/syncCoordinator.js.map +1 -1
  146. package/index.d.ts +4 -4
  147. package/index.js +2 -2
  148. package/index.js.map +1 -1
  149. package/package.json +1 -1
  150. package/stores/container-contents/backgroundHydration.js +1 -1
  151. package/stores/container-contents/backgroundHydration.js.map +1 -1
  152. package/stores/container-contents/containerContentsStore.d.ts +1 -1
  153. package/stores/container-contents/containerContentsStore.js.map +1 -1
  154. package/stores/container-contents/localRefresh.js +1 -1
  155. package/stores/container-contents/localRefresh.js.map +1 -1
  156. package/stores/container-contents/remoteContainerIngestion.js +1 -1
  157. package/stores/container-contents/remoteContainerIngestion.js.map +1 -1
  158. package/stores/container-contents/remoteWriteQueue.js +1 -1
  159. package/stores/container-contents/remoteWriteQueue.js.map +1 -1
  160. package/stores/container-contents/systemContainerHydration.js +1 -1
  161. package/stores/container-contents/systemContainerHydration.js.map +1 -1
  162. package/stores/container-contents/utils.js +1 -1
  163. package/stores/container-contents/utils.js.map +1 -1
  164. package/stores/documents/documentStore/attachmentIntents.js +1 -1
  165. package/stores/documents/documentStore/attachmentIntents.js.map +1 -1
  166. package/stores/documents/documentStore/attachmentSourceUpload.js.map +1 -1
  167. package/stores/documents/documentStore/attachmentStaging.js +1 -1
  168. package/stores/documents/documentStore/attachmentStaging.js.map +1 -1
  169. package/stores/documents/documentStore/attachmentUploadLane.js.map +1 -1
  170. package/stores/documents/documentStore/persistence.js +2 -2
  171. package/stores/documents/documentStore/persistence.js.map +1 -1
  172. package/stores/documents/documentStore/state.js +1 -1
  173. package/stores/documents/documentStore/state.js.map +1 -1
  174. package/stores/documents/documentStore/storedDocument.js +1 -1
  175. package/stores/documents/documentStore/storedDocument.js.map +1 -1
  176. package/stores/documents/documentStore/syncAttachments.js.map +1 -1
  177. package/stores/documents/documentStore.d.ts +1 -1
  178. package/stores/documents/documentStore.js.map +1 -1
  179. package/stores/documents/registry.d.ts +1 -1
  180. package/stores/documents/registry.js.map +1 -1
  181. package/stores/documents/types.d.ts +1 -1
  182. package/stores/documents/types.js.map +1 -1
  183. package/stores/local-projection/registry.d.ts +1 -1
  184. package/stores/local-projection/registry.js.map +1 -1
  185. package/sync/reconciliation/serviceTypes.d.ts +1 -1
  186. package/sync/reconciliation/serviceTypes.js.map +1 -1
  187. package/sync/reconciliation/triggers.d.ts +1 -1
  188. package/sync/reconciliation/triggers.js.map +1 -1
  189. package/workflows/blobs/attachmentBindingVerification.js +2 -2
  190. package/workflows/blobs/attachmentBindingVerification.js.map +1 -1
  191. package/workflows/blobs/blobChunkDecryption.js.map +1 -1
  192. package/workflows/blobs/decrypt.d.ts +1 -1
  193. package/workflows/blobs/decrypt.js +2 -2
  194. package/workflows/blobs/decrypt.js.map +1 -1
  195. package/workflows/blobs/detach.js +2 -2
  196. package/workflows/blobs/detach.js.map +1 -1
  197. package/workflows/blobs/hydrate.d.ts +3 -3
  198. package/workflows/blobs/hydrate.js +1 -1
  199. package/workflows/blobs/hydrate.js.map +1 -1
  200. package/workflows/blobs/hydrationResults.js.map +1 -1
  201. package/workflows/blobs/index.d.ts +2 -2
  202. package/workflows/blobs/index.js +1 -1
  203. package/workflows/blobs/index.js.map +1 -1
  204. package/workflows/blobs/multipartFirstParts.js.map +1 -1
  205. package/workflows/blobs/retainedAttachmentVerification.js +1 -1
  206. package/workflows/blobs/upload.js +3 -3
  207. package/workflows/blobs/upload.js.map +1 -1
  208. package/workflows/container-contents/container-state/createAdoption.js +1 -1
  209. package/workflows/container-contents/container-state/createAdoption.js.map +1 -1
  210. package/workflows/container-contents/container-state/createChild.js +1 -1
  211. package/workflows/container-contents/container-state/createChild.js.map +1 -1
  212. package/workflows/container-contents/container-state/createIntentSync.js +1 -1
  213. package/workflows/container-contents/container-state/createIntentSync.js.map +1 -1
  214. package/workflows/container-contents/container-state/groupGrantVerification.js +1 -1
  215. package/workflows/container-contents/container-state/moveIntentSync.js +1 -1
  216. package/workflows/container-contents/container-state/moveIntentSync.js.map +1 -1
  217. package/workflows/container-contents/container-state/purgeTreeScope.js +1 -1
  218. package/workflows/container-contents/container-state/purgeTreeScope.js.map +1 -1
  219. package/workflows/container-contents/container-state/share.js +1 -1
  220. package/workflows/container-contents/documentDiscoveryInputs.js +1 -1
  221. package/workflows/container-contents/documentDiscoveryInputs.js.map +1 -1
  222. package/workflows/container-contents/documentInfo.d.ts +1 -1
  223. package/workflows/container-contents/documentInfo.js.map +1 -1
  224. package/workflows/container-contents/documentLinks.d.ts +1 -1
  225. package/workflows/container-contents/documentLinks.js +1 -1
  226. package/workflows/container-contents/documentLinks.js.map +1 -1
  227. package/workflows/container-contents/documentMoveIntentSync.js +1 -1
  228. package/workflows/container-contents/documentMoveIntentSync.js.map +1 -1
  229. package/workflows/container-contents/documentPurge.d.ts +1 -1
  230. package/workflows/container-contents/documentPurge.js +1 -1
  231. package/workflows/container-contents/documentPurge.js.map +1 -1
  232. package/workflows/container-contents/documentQueries/rows.js +1 -1
  233. package/workflows/container-contents/documentQueries/rows.js.map +1 -1
  234. package/workflows/container-contents/metadata.d.ts +1 -1
  235. package/workflows/container-contents/metadataMutationPreparation.js +1 -1
  236. package/workflows/container-contents/metadataMutationPreparation.js.map +1 -1
  237. package/workflows/container-contents/metadataRemoteSync.d.ts +1 -1
  238. package/workflows/container-contents/metadataSyncErrors.js.map +1 -1
  239. package/workflows/container-contents/projectionKeys.d.ts +1 -1
  240. package/workflows/container-contents/syncLane.d.ts +1 -1
  241. package/workflows/container-contents/syncLane.js.map +1 -1
  242. package/workflows/containers/child/carriedDescendantRekeys.js +1 -1
  243. package/workflows/containers/child/create.d.ts +1 -1
  244. package/workflows/containers/child/create.js +2 -2
  245. package/workflows/containers/child/create.js.map +1 -1
  246. package/workflows/containers/child/createProjection.js +1 -1
  247. package/workflows/containers/child/createProjection.js.map +1 -1
  248. package/workflows/containers/child/createSubmission.d.ts +2 -2
  249. package/workflows/containers/child/createSubmission.js.map +1 -1
  250. package/workflows/containers/child/move.d.ts +2 -2
  251. package/workflows/containers/child/move.js +2 -2
  252. package/workflows/containers/child/move.js.map +1 -1
  253. package/workflows/containers/child/moveWraps.js +1 -1
  254. package/workflows/containers/child/mutationRequestCore.js +1 -1
  255. package/workflows/containers/child/mutationRequestCore.js.map +1 -1
  256. package/workflows/containers/child/mutationSubmit.js.map +1 -1
  257. package/workflows/containers/child/recite.js.map +1 -1
  258. package/workflows/containers/child/recitePlan.js +1 -1
  259. package/workflows/containers/child/recitePlan.js.map +1 -1
  260. package/workflows/containers/child/rekey.d.ts +1 -1
  261. package/workflows/containers/child/rekey.js +2 -2
  262. package/workflows/containers/child/rekey.js.map +1 -1
  263. package/workflows/containers/child/rekeyProjection.js +1 -1
  264. package/workflows/containers/child/rekeyProjection.js.map +1 -1
  265. package/workflows/containers/child/rekeyRemote.d.ts +2 -2
  266. package/workflows/containers/child/rekeyRemote.js.map +1 -1
  267. package/workflows/containers/child/revoke.d.ts +2 -2
  268. package/workflows/containers/child/revoke.js +2 -2
  269. package/workflows/containers/child/revoke.js.map +1 -1
  270. package/workflows/containers/child/rotationPrincipalPolicies.js +1 -1
  271. package/workflows/containers/child/runtimeCurrentGroupShare.js +1 -1
  272. package/workflows/containers/child/share.d.ts +2 -2
  273. package/workflows/containers/child/share.js +1 -1
  274. package/workflows/containers/child/share.js.map +1 -1
  275. package/workflows/containers/child/shareAncestorRepair.js.map +1 -1
  276. package/workflows/containers/child/shareMaterialization.d.ts +1 -1
  277. package/workflows/containers/child/sharePlanCore.d.ts +1 -1
  278. package/workflows/containers/child/sharePlanCore.js +1 -1
  279. package/workflows/containers/root/create.js +1 -1
  280. package/workflows/containers/root/create.js.map +1 -1
  281. package/workflows/containers/root/initialGroupPolicy.js +1 -1
  282. package/workflows/containers/root/initialGroupPolicy.js.map +1 -1
  283. package/workflows/documents/create.d.ts +1 -1
  284. package/workflows/documents/create.js +1 -1
  285. package/workflows/documents/documentMutationPreparation.js +1 -1
  286. package/workflows/documents/documentMutationPreparation.js.map +1 -1
  287. package/workflows/documents/historyContent.js +1 -1
  288. package/workflows/documents/historyContent.js.map +1 -1
  289. package/workflows/documents/linkSet.js +1 -1
  290. package/workflows/documents/linkSet.js.map +1 -1
  291. package/workflows/documents/linkSetAuthority.js +1 -1
  292. package/workflows/documents/linkSetBlobRewraps.js +2 -2
  293. package/workflows/documents/linkSetBlobRewraps.js.map +1 -1
  294. package/workflows/documents/linkSetRemote.d.ts +1 -1
  295. package/workflows/documents/linkSetRemote.js +1 -1
  296. package/workflows/documents/orphanBlobReclaims.js +1 -1
  297. package/workflows/documents/orphanBlobReclaims.js.map +1 -1
  298. package/workflows/documents/projectionKeys.d.ts +1 -1
  299. package/workflows/documents/purge.d.ts +1 -1
  300. package/workflows/documents/purge.js +2 -2
  301. package/workflows/documents/purge.js.map +1 -1
  302. package/workflows/documents/readOnlySync.d.ts +1 -1
  303. package/workflows/documents/readOnlySync.js +1 -1
  304. package/workflows/documents/readOnlySync.js.map +1 -1
  305. package/workflows/documents/sync.js +1 -1
  306. package/workflows/documents/syncContainerRekeyPreparation.js +1 -1
  307. package/workflows/documents/syncLane.d.ts +1 -1
  308. package/workflows/documents/syncLane.js.map +1 -1
  309. package/workflows/documents/syncPlanIdentity.js +1 -1
  310. package/workflows/documents/syncPlanIdentity.js.map +1 -1
  311. package/workflows/documents/syncRepairAccess.js +1 -1
  312. package/workflows/documents/syncSubmittedResult.js +1 -1
  313. package/workflows/organizations/authoredPrincipalPolicyWarmer.js +1 -1
  314. package/workflows/organizations/authoredPrincipalPolicyWarmer.js.map +1 -1
  315. package/workflows/organizations/containerGrantRevocation.d.ts +2 -2
  316. package/workflows/organizations/containerGrantRevocation.js.map +1 -1
  317. package/workflows/organizations/createCurrentOrganizationGroup.js.map +1 -1
  318. package/workflows/organizations/currentOrganizationGroupNames.js.map +1 -1
  319. package/workflows/organizations/currentOrganizationMutationRetention.js +1 -1
  320. package/workflows/organizations/currentOrganizationMutationRetention.js.map +1 -1
  321. package/workflows/organizations/currentPolicyMutationAcknowledgement.js +1 -1
  322. package/workflows/organizations/currentPolicyMutationAcknowledgement.js.map +1 -1
  323. package/workflows/organizations/groupCreation.d.ts +1 -1
  324. package/workflows/organizations/groupCreation.js.map +1 -1
  325. package/workflows/organizations/groupMetadataAccess.d.ts +1 -1
  326. package/workflows/organizations/groupMetadataContainerAuthority.js.map +1 -1
  327. package/workflows/organizations/groupMetadataRuntime.js.map +1 -1
  328. package/workflows/organizations/groupNameUniqueness.js.map +1 -1
  329. package/workflows/organizations/groupPolicyMutationAcknowledgement.js +1 -1
  330. package/workflows/organizations/groupPolicyMutationAcknowledgement.js.map +1 -1
  331. package/workflows/organizations/groupPolicyRequests.js.map +1 -1
  332. package/workflows/organizations/index.d.ts +0 -1
  333. package/workflows/organizations/index.js +0 -1
  334. package/workflows/organizations/index.js.map +1 -1
  335. package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
  336. package/workflows/organizations/organizationGroupDirectory.js.map +1 -1
  337. package/workflows/organizations/organizationProfile.js +1 -1
  338. package/workflows/organizations/organizationProfile.js.map +1 -1
  339. package/workflows/organizations/policyHistoryCache.js.map +1 -1
  340. package/workflows/organizations/principalContainerRematerialization.js +1 -1
  341. package/workflows/organizations/principalContainerRematerializationPlanning.js.map +1 -1
  342. package/workflows/organizations/principalMutationJournalManagement.js +1 -1
  343. package/workflows/organizations/principalMutationJournalManagement.js.map +1 -1
  344. package/workflows/organizations/principalMutationReceipt.js +1 -1
  345. package/workflows/organizations/principalMutationReceipt.js.map +1 -1
  346. package/workflows/organizations/principalPolicy.d.ts +1 -1
  347. package/workflows/organizations/principalPolicy.js.map +1 -1
  348. package/workflows/organizations/principalPolicyReceiptArtifacts.js +1 -1
  349. package/workflows/organizations/principalPolicyReceiptArtifacts.js.map +1 -1
  350. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.d.ts +4 -24
  351. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +13 -133
  352. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
  353. package/workflows/organizations/rosterProfileContainer.js +1 -1
  354. package/workflows/organizations/rosterProfileContainer.js.map +1 -1
  355. package/workflows/organizations/runtimeCurrentGroupMutation.js +1 -1
  356. package/workflows/organizations/runtimeCurrentGroupMutation.js.map +1 -1
  357. package/workflows/principals/acknowledgedPrincipalCurrents.d.ts +33 -0
  358. package/workflows/principals/acknowledgedPrincipalCurrents.js +140 -0
  359. package/workflows/principals/acknowledgedPrincipalCurrents.js.map +1 -0
  360. package/workflows/{organizations → principals}/acknowledgedPrincipalPredecessor.d.ts +1 -1
  361. package/workflows/{organizations → principals}/acknowledgedPrincipalPredecessor.js +1 -1
  362. package/workflows/principals/acknowledgedPrincipalPredecessor.js.map +1 -0
  363. package/workflows/principals/index.d.ts +1 -0
  364. package/workflows/principals/index.js +1 -0
  365. package/workflows/principals/index.js.map +1 -1
  366. package/workflows/{organizations → principals}/initialPrincipalCurrentPublication.js +5 -7
  367. package/workflows/principals/initialPrincipalCurrentPublication.js.map +1 -0
  368. package/workflows/principals/policyCache.d.ts +1 -1
  369. package/workflows/principals/policyCache.js +2 -2
  370. package/workflows/principals/policyCache.js.map +1 -1
  371. package/workflows/principals/principalAcknowledgementChecks.d.ts +30 -0
  372. package/workflows/principals/principalAcknowledgementChecks.js +2 -0
  373. package/workflows/principals/principalAcknowledgementChecks.js.map +1 -0
  374. package/workflows/{organizations → principals}/principalCurrentPublicationSeal.js.map +1 -1
  375. package/workflows/{organizations → principals}/reconcileAcknowledgedPrincipalCurrent.js +2 -2
  376. package/workflows/principals/reconcileAcknowledgedPrincipalCurrent.js.map +1 -0
  377. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  378. package/workflows/principals/runtimePolicyWarmer.js +1 -1
  379. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
  380. package/workflows/registration/persistRegistrationBootstrap.js +1 -1
  381. package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
  382. package/workflows/runtimeInput.d.ts +3 -3
  383. package/workflows/runtimeInput.js.map +1 -1
  384. package/workflows/sync/index.d.ts +2 -1
  385. package/workflows/sync/index.js +2 -1
  386. package/workflows/sync/index.js.map +1 -1
  387. package/data/keyingCanonicalJson.js.map +0 -1
  388. package/data/keyingProjectionVerification.d.ts +0 -9
  389. package/data/keyingProjectionVerification.js.map +0 -1
  390. package/workflows/organizations/acknowledgedPrincipalPredecessor.js.map +0 -1
  391. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +0 -1
  392. package/workflows/organizations/reconcileAcknowledgedPrincipalCurrent.js.map +0 -1
  393. /package/data/{blobContracts.d.ts → blobs/blobContracts.d.ts} +0 -0
  394. /package/data/{blobContracts.js → blobs/blobContracts.js} +0 -0
  395. /package/data/{blobContracts.js.map → blobs/blobContracts.js.map} +0 -0
  396. /package/data/{accessLevel.js → keying/accessLevel.js} +0 -0
  397. /package/data/{accessLevel.js.map → keying/accessLevel.js.map} +0 -0
  398. /package/data/{stableUuid.js → keying/stableUuid.js} +0 -0
  399. /package/data/{stableUuid.js.map → keying/stableUuid.js.map} +0 -0
  400. /package/data/{principalPolicyStates.js → principals/principalPolicyStates.js} +0 -0
  401. /package/data/{principalPolicyStates.js.map → principals/principalPolicyStates.js.map} +0 -0
  402. /package/data/{domainScope.d.ts → shared/domainScope.d.ts} +0 -0
  403. /package/data/{domainScope.js → shared/domainScope.js} +0 -0
  404. /package/data/{domainScope.js.map → shared/domainScope.js.map} +0 -0
  405. /package/data/{errorMessage.js → shared/errorMessage.js} +0 -0
  406. /package/data/{errorMessage.js.map → shared/errorMessage.js.map} +0 -0
  407. /package/data/{recordReaders.d.ts → shared/recordReaders.d.ts} +0 -0
  408. /package/data/{recordReaders.js → shared/recordReaders.js} +0 -0
  409. /package/data/{recordReaders.js.map → shared/recordReaders.js.map} +0 -0
  410. /package/data/{securityIncidents.js → shared/securityIncidents.js} +0 -0
  411. /package/data/{securityIncidents.js.map → shared/securityIncidents.js.map} +0 -0
  412. /package/data/{crdtPeerSeed.js → sync/crdtPeerSeed.js} +0 -0
  413. /package/data/{crdtPeerSeed.js.map → sync/crdtPeerSeed.js.map} +0 -0
  414. /package/workflows/{organizations → principals}/principalCurrentPublicationSeal.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"mutationAcknowledgement.js","sourceRoot":"","sources":["mutationAcknowledgement.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,oCAAoC,EAKpC,uBAAuB,EACvB,8BAA8B,EAC9B,sCAAsC,EACtC,4BAA4B,GAC7B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EACL,uDAAuD,GAExD,MAAM,4DAA4D,CAAC;AAoBpE,SAAS,oBAAoB,CAAC,KAI7B;IACC,IACE,yBAAyB,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,WAAW,CAAC;QAClE,yBAAyB,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,KAAK,OAAO,CAAC,EAChE,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,CAAC,KAAK,WAAW,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAI,MAAoB,EAAE,KAAa;IACnE,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACtC,uBAAuB,CACrB,yBAAyB,CAAC,IAAI,EAAE,KAAK,CAAC,EACtC,yBAAyB,CAAC,KAAK,EAAE,KAAK,CAAC,CACxC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,KAAkC;IAElC,OAAO,qBAAqB,CAC1B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAC,EACH,kBAAkB,CACnB,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAmC,EACnC,QAAmC;IAEnC,IACE,QAAQ,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;QACzC,QAAQ,CAAC,cAAc,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc;QACrD,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAClD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,2EAA2E;IAC3E,0EAA0E;IAC1E,iDAAiD;IACjD,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,IACE,QAAQ,CAAC,YAAY,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK;QAChD,QAAQ,CAAC,YAAY,CAAC,YAAY,KAAK,IAAI,CAAC,YAAY;QACxD,QAAQ,CAAC,cAAc,CAAC,YAAY,KAAK,IAAI,CAAC,YAAY,EAC1D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,IACE,QAAQ,CAAC,YAAY,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;QACtD,QAAQ,CAAC,YAAY,CAAC,kBAAkB,KAAK,IAAI,CAAC,YAAY;QAC9D,QAAQ,CAAC,YAAY,CAAC,mBAAmB,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC9D,QAAQ,CAAC,YAAY,CAAC,iBAAiB,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAClE,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,SAAS,uBAAuB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,yBAAyB,CACtC,IAAmC,EACnC,QAAmC;IAEnC,MAAM,aAAa,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC;IAC9C,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,yEAAyE;QACzE,yEAAyE;QACzE,0EAA0E;QAC1E,sCAAsC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;QAC9C,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,oEAAoE;YACpE,uEAAuE;YACvE,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;QACJ,CAAC;QACD,IACE,CAAC,MAAM,8BAA8B,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC,MAAM,8BAA8B,CAAC,QAAQ,CAAC,CAAC,EAChD,CAAC;YACD,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,MAAM,8BAA8B,CAAC,OAAO,CAAC,CAAC,KAAK,aAAa,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,IAAmC,EACnC,QAAmC;IAEnC,oBAAoB,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK;QAC3C,QAAQ,EAAE,IAAI,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO;KACf,CAAC,CAAC;IACH,oBAAoB,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI;QAC1C,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,KAAK,EAAE,YAAY;KACpB,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,oBAAoB,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,QAAQ;QACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,UAAU;KAClB,CAAC,CAAC;IACH,oBAAoB,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,KAAK;QACrC,QAAQ,EAAE,IAAI,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO;KACf,CAAC,CAAC;IACH,oBAAoB,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,QAAQ;QACtC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,WAAW;KACnB,CAAC,CAAC;IACH,MAAM,yBAAyB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChD,oBAAoB,CAAC;QACnB,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC;QAC3E,QAAQ,EAAE,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC;QAC3D,KAAK,EAAE,OAAO;KACf,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAG,qBAAqB,CAC3C,QAAQ,CAAC,YAAY,CAAC,gBAAgB,EACtC,2BAA2B,CAC5B,CAAC;IACF,oBAAoB,CAAC;QACnB,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,gBAAgB;QAC1B,KAAK,EAAE,mBAAmB;KAC3B,CAAC,CAAC;IACH,IACE,QAAQ,CAAC,YAAY,CAAC,YAAY;QAChC,CAAC,MAAM,4BAA4B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,QAAQ,CAAC,YAAY,CAAC,aAAa;YACjC,CAAC,MAAM,sCAAsC,CAAC,gBAAgB,CAAC,CAAC;QAClE,QAAQ,CAAC,YAAY,CAAC,yBAAyB;YAC7C,IAAI,CAAC,QAAQ,CAAC,yBAAyB,EACzC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,oBAAoB,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,wBAAwB;QACzC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,wBAAwB;QAChD,KAAK,EAAE,4BAA4B;KACpC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wCAAwC,CAAC,KAG9D;IACC,sBAAsB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,qBAAqB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxD,OAAO;QACL,UAAU,EAAE,oCAAoC,CAAC;YAC/C,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;YAC7B,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY;SACtC,CAAC;QACF,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB;KAC/D,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAKlD;IACC,OAAO,uDAAuD,CAAC;QAC7D,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE;YACL,MAAM,wCAAwC,CAAC;gBAC7C,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC;SACH;QACD,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;AACL,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAKvD;IACC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACb,wDAAwD,CACzD,CAAC;QACJ,CAAC;QACD,OAAO,wCAAwC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CACH,CAAC;IACF,OAAO,uDAAuD,CAAC;QAC7D,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK;QACL,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n accessManifestCheckpointFromManifest,\n type ContainerAccessManifestState,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n compareCanonicalStrings,\n computeContainerKekKeyringHash,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationResponse } from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../../keyingCanonicalJson\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n type LocallyAcknowledgedAccessManifestHead,\n} from \"../../persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\n\nexport interface AuthoredContainerMutationHead {\n readonly body: object;\n readonly containerId: string;\n readonly event: AccessEvent;\n readonly eventHash: string;\n readonly keyEpoch: ContainerKeyEpoch;\n readonly manifest: AccessManifest;\n readonly manifestHash: string;\n /**\n * The keyring the epoch already had, for mutations that keep their epoch.\n * Its artifact is immutable, so the response must echo exactly this.\n */\n readonly previousKeyring?: Record<string, unknown> | null | undefined;\n readonly state: ContainerAccessManifestState;\n readonly wraps: readonly ContainerKeyWrap[];\n}\n\nfunction assertCanonicalMatch(input: {\n readonly actual: unknown;\n readonly expected: unknown;\n readonly label: string;\n}): void {\n if (\n canonicalKeyingJsonString(input.actual, `${input.label} response`) !==\n canonicalKeyingJsonString(input.expected, `${input.label} plan`)\n ) {\n throw new Error(`Container mutation response ${input.label} mismatch`);\n }\n}\n\nfunction sortedCanonicalValues<T>(values: readonly T[], label: string): T[] {\n return [...values].sort((left, right) =>\n compareCanonicalStrings(\n canonicalKeyingJsonString(left, label),\n canonicalKeyingJsonString(right, label),\n ),\n );\n}\n\nfunction expectedRecipientTargets(\n wraps: readonly ContainerKeyWrap[],\n): ContainerKekRecipientTarget[] {\n return sortedCanonicalValues(\n wraps.map((wrap) => ({\n recipientId: wrap.recipientId,\n recipientKeyEpochId: wrap.recipientKeyEpochId,\n recipientKeyFingerprint: wrap.recipientKeyFingerprint,\n recipientKind: wrap.recipientKind,\n })),\n \"recipient target\",\n );\n}\n\nfunction assertResponseIdentity(\n plan: AuthoredContainerMutationHead,\n response: ContainerMutationResponse,\n): void {\n if (\n response.containerId !== plan.containerId ||\n response.organizationId !== plan.state.organizationId ||\n response.parentId !== plan.state.parentContainerId\n ) {\n throw new Error(\"Container mutation response object identity mismatch\");\n }\n // The top-level slot column is what local system-container lookups key on,\n // so it must echo the slot this client signed into the manifest state; an\n // omitted slot is the server's spelling of null.\n if ((response.systemSlot ?? null) !== plan.state.systemSlot) {\n throw new Error(\"Container mutation response system slot mismatch\");\n }\n if (\n response.manifestHead.epoch !== plan.state.epoch ||\n response.manifestHead.manifestHash !== plan.manifestHash ||\n response.accessManifest.manifestHash !== plan.manifestHash\n ) {\n throw new Error(\"Container mutation response manifest head mismatch\");\n }\n if (\n response.containerKek.containerId !== plan.containerId ||\n response.containerKek.accessManifestHash !== plan.manifestHash ||\n response.containerKek.containerKeyEpochId !== plan.keyEpoch.id ||\n response.containerKek.containerKeyEpoch !== plan.keyEpoch.keyEpoch\n ) {\n throw new Error(\"Container mutation response KEK identity mismatch\");\n }\n}\n\n/** A rotation body commits a keyring hash; other bodies do not. */\nfunction readOptionalKeyringHash(body: object): string | null {\n const value = Reflect.get(body, \"keyringHash\");\n return typeof value === \"string\" ? value : null;\n}\n\n/**\n * The response's keyring must be the one this client's own signed event\n * committed to. Without this a server could echo a substituted snapshot and\n * have it acknowledged into durable local state — the acknowledgement is the\n * moment the response becomes trusted, so the commitment is checked here.\n */\nasync function assertAcknowledgedKeyring(\n plan: AuthoredContainerMutationHead,\n response: ContainerMutationResponse,\n): Promise<void> {\n const committedHash = readOptionalKeyringHash(plan.body);\n const keyring = response.containerKek.keyring;\n if (committedHash === null) {\n // A non-rotating mutation keeps its epoch, so the echoed keyring must be\n // the immutable artifact that epoch already had. Accepting anything else\n // would let a server null or substitute the snapshot in the response that\n // becomes the next writer projection.\n const expected = plan.previousKeyring ?? null;\n if (expected === null) {\n // The epoch had no keyring, so the response must not invent one: an\n // injected snapshot would become the next writer projection's history.\n if (keyring) {\n throw new Error(\n \"Container mutation response added a keyring to an unchanged epoch\",\n );\n }\n return;\n }\n if (!keyring) {\n throw new Error(\n \"Container mutation response dropped its unchanged keyring\",\n );\n }\n if (\n (await computeContainerKekKeyringHash(keyring)) !==\n (await computeContainerKekKeyringHash(expected))\n ) {\n throw new Error(\n \"Container mutation response replaced its unchanged keyring\",\n );\n }\n return;\n }\n if (!keyring) {\n throw new Error(\"Container mutation response is missing its keyring\");\n }\n if ((await computeContainerKekKeyringHash(keyring)) !== committedHash) {\n throw new Error(\n \"Container mutation response keyring does not match its signed event\",\n );\n }\n}\n\nasync function assertResponseContent(\n plan: AuthoredContainerMutationHead,\n response: ContainerMutationResponse,\n): Promise<void> {\n assertCanonicalMatch({\n actual: response.accessManifest.event.event,\n expected: plan.event,\n label: \"event\",\n });\n assertCanonicalMatch({\n actual: response.accessManifest.event.body,\n expected: plan.body,\n label: \"event body\",\n });\n if (response.accessManifest.event.eventHash !== plan.eventHash) {\n throw new Error(\"Container mutation response event hash mismatch\");\n }\n assertCanonicalMatch({\n actual: response.accessManifest.manifest,\n expected: plan.manifest,\n label: \"manifest\",\n });\n assertCanonicalMatch({\n actual: response.accessManifest.state,\n expected: plan.state,\n label: \"state\",\n });\n assertCanonicalMatch({\n actual: response.containerKek.keyEpoch,\n expected: plan.keyEpoch,\n label: \"key epoch\",\n });\n await assertAcknowledgedKeyring(plan, response);\n assertCanonicalMatch({\n actual: sortedCanonicalValues(response.containerKek.wraps, \"response wrap\"),\n expected: sortedCanonicalValues(plan.wraps, \"planned wrap\"),\n label: \"wraps\",\n });\n const recipientTargets = expectedRecipientTargets(plan.wraps);\n const responseTargets = sortedCanonicalValues(\n response.containerKek.recipientTargets,\n \"response recipient target\",\n );\n assertCanonicalMatch({\n actual: responseTargets,\n expected: recipientTargets,\n label: \"recipient targets\",\n });\n if (\n response.containerKek.keyEpochHash !==\n (await computeContainerKeyEpochHash(plan.keyEpoch)) ||\n response.containerKek.keyTargetHash !==\n (await computeContainerKekRecipientTargetHash(recipientTargets)) ||\n response.containerKek.parentContainerKeyEpochId !==\n plan.keyEpoch.parentContainerKeyEpochId\n ) {\n throw new Error(\"Container mutation response KEK commitment mismatch\");\n }\n assertCanonicalMatch({\n actual: response.referencedPrincipalHeads,\n expected: plan.manifest.referencedPrincipalHeads,\n label: \"referenced principal heads\",\n });\n}\n\nexport async function locallyAcknowledgedContainerMutationHead(input: {\n readonly plan: AuthoredContainerMutationHead;\n readonly response: ContainerMutationResponse;\n}): Promise<LocallyAcknowledgedAccessManifestHead> {\n assertResponseIdentity(input.plan, input.response);\n await assertResponseContent(input.plan, input.response);\n return {\n checkpoint: accessManifestCheckpointFromManifest({\n manifest: input.plan.manifest,\n manifestHash: input.plan.manifestHash,\n }),\n previousManifestHash: input.plan.manifest.previousManifestHash,\n };\n}\n\n/** Correlates an API acknowledgement to the locally signed plan before pinning. */\nexport async function acknowledgeContainerMutation(input: {\n readonly execSql: ExecSql;\n readonly plan: AuthoredContainerMutationHead;\n readonly response: ContainerMutationResponse;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n return advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads: [\n await locallyAcknowledgedContainerMutationHead({\n plan: input.plan,\n response: input.response,\n }),\n ],\n stillCurrent: input.stillCurrent,\n });\n}\n\n/** Correlates and advances a complete authored mutation batch atomically. */\nexport async function acknowledgeContainerMutationBatch(input: {\n readonly execSql: ExecSql;\n readonly plans: readonly AuthoredContainerMutationHead[];\n readonly responses: readonly ContainerMutationResponse[];\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n if (input.plans.length !== input.responses.length) {\n throw new Error(\"Container mutation acknowledgement batch is incomplete\");\n }\n const heads = await Promise.all(\n input.plans.map(async (plan, index) => {\n const response = input.responses[index];\n if (!response) {\n throw new Error(\n \"Container mutation acknowledgement batch is incomplete\",\n );\n }\n return locallyAcknowledgedContainerMutationHead({ plan, response });\n }),\n );\n return advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads,\n stillCurrent: input.stillCurrent,\n });\n}\n"]}
1
+ {"version":3,"file":"mutationAcknowledgement.js","sourceRoot":"","sources":["mutationAcknowledgement.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n accessManifestCheckpointFromManifest,\n type ContainerAccessManifestState,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n compareCanonicalStrings,\n computeContainerKekKeyringHash,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationResponse } from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../../keying/canonicalJson\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n type LocallyAcknowledgedAccessManifestHead,\n} from \"../../persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\n\nexport interface AuthoredContainerMutationHead {\n readonly body: object;\n readonly containerId: string;\n readonly event: AccessEvent;\n readonly eventHash: string;\n readonly keyEpoch: ContainerKeyEpoch;\n readonly manifest: AccessManifest;\n readonly manifestHash: string;\n /**\n * The keyring the epoch already had, for mutations that keep their epoch.\n * Its artifact is immutable, so the response must echo exactly this.\n */\n readonly previousKeyring?: Record<string, unknown> | null | undefined;\n readonly state: ContainerAccessManifestState;\n readonly wraps: readonly ContainerKeyWrap[];\n}\n\nfunction assertCanonicalMatch(input: {\n readonly actual: unknown;\n readonly expected: unknown;\n readonly label: string;\n}): void {\n if (\n canonicalKeyingJsonString(input.actual, `${input.label} response`) !==\n canonicalKeyingJsonString(input.expected, `${input.label} plan`)\n ) {\n throw new Error(`Container mutation response ${input.label} mismatch`);\n }\n}\n\nfunction sortedCanonicalValues<T>(values: readonly T[], label: string): T[] {\n return [...values].sort((left, right) =>\n compareCanonicalStrings(\n canonicalKeyingJsonString(left, label),\n canonicalKeyingJsonString(right, label),\n ),\n );\n}\n\nfunction expectedRecipientTargets(\n wraps: readonly ContainerKeyWrap[],\n): ContainerKekRecipientTarget[] {\n return sortedCanonicalValues(\n wraps.map((wrap) => ({\n recipientId: wrap.recipientId,\n recipientKeyEpochId: wrap.recipientKeyEpochId,\n recipientKeyFingerprint: wrap.recipientKeyFingerprint,\n recipientKind: wrap.recipientKind,\n })),\n \"recipient target\",\n );\n}\n\nfunction assertResponseIdentity(\n plan: AuthoredContainerMutationHead,\n response: ContainerMutationResponse,\n): void {\n if (\n response.containerId !== plan.containerId ||\n response.organizationId !== plan.state.organizationId ||\n response.parentId !== plan.state.parentContainerId\n ) {\n throw new Error(\"Container mutation response object identity mismatch\");\n }\n // The top-level slot column is what local system-container lookups key on,\n // so it must echo the slot this client signed into the manifest state; an\n // omitted slot is the server's spelling of null.\n if ((response.systemSlot ?? null) !== plan.state.systemSlot) {\n throw new Error(\"Container mutation response system slot mismatch\");\n }\n if (\n response.manifestHead.epoch !== plan.state.epoch ||\n response.manifestHead.manifestHash !== plan.manifestHash ||\n response.accessManifest.manifestHash !== plan.manifestHash\n ) {\n throw new Error(\"Container mutation response manifest head mismatch\");\n }\n if (\n response.containerKek.containerId !== plan.containerId ||\n response.containerKek.accessManifestHash !== plan.manifestHash ||\n response.containerKek.containerKeyEpochId !== plan.keyEpoch.id ||\n response.containerKek.containerKeyEpoch !== plan.keyEpoch.keyEpoch\n ) {\n throw new Error(\"Container mutation response KEK identity mismatch\");\n }\n}\n\n/** A rotation body commits a keyring hash; other bodies do not. */\nfunction readOptionalKeyringHash(body: object): string | null {\n const value = Reflect.get(body, \"keyringHash\");\n return typeof value === \"string\" ? value : null;\n}\n\n/**\n * The response's keyring must be the one this client's own signed event\n * committed to. Without this a server could echo a substituted snapshot and\n * have it acknowledged into durable local state — the acknowledgement is the\n * moment the response becomes trusted, so the commitment is checked here.\n */\nasync function assertAcknowledgedKeyring(\n plan: AuthoredContainerMutationHead,\n response: ContainerMutationResponse,\n): Promise<void> {\n const committedHash = readOptionalKeyringHash(plan.body);\n const keyring = response.containerKek.keyring;\n if (committedHash === null) {\n // A non-rotating mutation keeps its epoch, so the echoed keyring must be\n // the immutable artifact that epoch already had. Accepting anything else\n // would let a server null or substitute the snapshot in the response that\n // becomes the next writer projection.\n const expected = plan.previousKeyring ?? null;\n if (expected === null) {\n // The epoch had no keyring, so the response must not invent one: an\n // injected snapshot would become the next writer projection's history.\n if (keyring) {\n throw new Error(\n \"Container mutation response added a keyring to an unchanged epoch\",\n );\n }\n return;\n }\n if (!keyring) {\n throw new Error(\n \"Container mutation response dropped its unchanged keyring\",\n );\n }\n if (\n (await computeContainerKekKeyringHash(keyring)) !==\n (await computeContainerKekKeyringHash(expected))\n ) {\n throw new Error(\n \"Container mutation response replaced its unchanged keyring\",\n );\n }\n return;\n }\n if (!keyring) {\n throw new Error(\"Container mutation response is missing its keyring\");\n }\n if ((await computeContainerKekKeyringHash(keyring)) !== committedHash) {\n throw new Error(\n \"Container mutation response keyring does not match its signed event\",\n );\n }\n}\n\nasync function assertResponseContent(\n plan: AuthoredContainerMutationHead,\n response: ContainerMutationResponse,\n): Promise<void> {\n assertCanonicalMatch({\n actual: response.accessManifest.event.event,\n expected: plan.event,\n label: \"event\",\n });\n assertCanonicalMatch({\n actual: response.accessManifest.event.body,\n expected: plan.body,\n label: \"event body\",\n });\n if (response.accessManifest.event.eventHash !== plan.eventHash) {\n throw new Error(\"Container mutation response event hash mismatch\");\n }\n assertCanonicalMatch({\n actual: response.accessManifest.manifest,\n expected: plan.manifest,\n label: \"manifest\",\n });\n assertCanonicalMatch({\n actual: response.accessManifest.state,\n expected: plan.state,\n label: \"state\",\n });\n assertCanonicalMatch({\n actual: response.containerKek.keyEpoch,\n expected: plan.keyEpoch,\n label: \"key epoch\",\n });\n await assertAcknowledgedKeyring(plan, response);\n assertCanonicalMatch({\n actual: sortedCanonicalValues(response.containerKek.wraps, \"response wrap\"),\n expected: sortedCanonicalValues(plan.wraps, \"planned wrap\"),\n label: \"wraps\",\n });\n const recipientTargets = expectedRecipientTargets(plan.wraps);\n const responseTargets = sortedCanonicalValues(\n response.containerKek.recipientTargets,\n \"response recipient target\",\n );\n assertCanonicalMatch({\n actual: responseTargets,\n expected: recipientTargets,\n label: \"recipient targets\",\n });\n if (\n response.containerKek.keyEpochHash !==\n (await computeContainerKeyEpochHash(plan.keyEpoch)) ||\n response.containerKek.keyTargetHash !==\n (await computeContainerKekRecipientTargetHash(recipientTargets)) ||\n response.containerKek.parentContainerKeyEpochId !==\n plan.keyEpoch.parentContainerKeyEpochId\n ) {\n throw new Error(\"Container mutation response KEK commitment mismatch\");\n }\n assertCanonicalMatch({\n actual: response.referencedPrincipalHeads,\n expected: plan.manifest.referencedPrincipalHeads,\n label: \"referenced principal heads\",\n });\n}\n\nexport async function locallyAcknowledgedContainerMutationHead(input: {\n readonly plan: AuthoredContainerMutationHead;\n readonly response: ContainerMutationResponse;\n}): Promise<LocallyAcknowledgedAccessManifestHead> {\n assertResponseIdentity(input.plan, input.response);\n await assertResponseContent(input.plan, input.response);\n return {\n checkpoint: accessManifestCheckpointFromManifest({\n manifest: input.plan.manifest,\n manifestHash: input.plan.manifestHash,\n }),\n previousManifestHash: input.plan.manifest.previousManifestHash,\n };\n}\n\n/** Correlates an API acknowledgement to the locally signed plan before pinning. */\nexport async function acknowledgeContainerMutation(input: {\n readonly execSql: ExecSql;\n readonly plan: AuthoredContainerMutationHead;\n readonly response: ContainerMutationResponse;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n return advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads: [\n await locallyAcknowledgedContainerMutationHead({\n plan: input.plan,\n response: input.response,\n }),\n ],\n stillCurrent: input.stillCurrent,\n });\n}\n\n/** Correlates and advances a complete authored mutation batch atomically. */\nexport async function acknowledgeContainerMutationBatch(input: {\n readonly execSql: ExecSql;\n readonly plans: readonly AuthoredContainerMutationHead[];\n readonly responses: readonly ContainerMutationResponse[];\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n if (input.plans.length !== input.responses.length) {\n throw new Error(\"Container mutation acknowledgement batch is incomplete\");\n }\n const heads = await Promise.all(\n input.plans.map(async (plan, index) => {\n const response = input.responses[index];\n if (!response) {\n throw new Error(\n \"Container mutation acknowledgement batch is incomplete\",\n );\n }\n return locallyAcknowledgedContainerMutationHead({ plan, response });\n }),\n );\n return advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads,\n stillCurrent: input.stillCurrent,\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { readCanonicalRecord } from "../../keyingCanonicalJson.js";
1
+ import { readCanonicalRecord } from "../../keying/canonicalJson.js";
2
2
  export function principalPolicyRequestRecord(policy, label = "Container principal policy") {
3
3
  return readCanonicalRecord({
4
4
  principalType: policy.principalType,
@@ -1 +1 @@
1
- {"version":3,"file":"principalPolicies.js","sourceRoot":"","sources":["principalPolicies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAMhE,MAAM,UAAU,4BAA4B,CAC1C,MAAyC,EACzC,KAAK,GAAG,4BAA4B;IAEpC,OAAO,mBAAmB,CACxB;QACE,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE;YACL,GAAG,MAAM,CAAC,KAAK;YACf,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B;QACD,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,EACD,KAAK,CACN,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,MAGC;IAED,OAAO;QACL,MAAM,CAAC,aAAa;QACpB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,OAAO;QACd,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,SAAS;KACjB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,uBAAuB,CAErC,QAAsB;IACtB,MAAM,aAAa,GAAG,IAAI,GAAG,EAAa,CAAC;IAE3C,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import type { VerifiedPrincipalPolicy } from \"@tearleads/crypto\";\nimport { readCanonicalRecord } from \"../../keyingCanonicalJson\";\nimport type {\n PrincipalPolicyCheckpointEvidence,\n PrincipalPolicyCurrentEvidence,\n} from \"../../principals/principalPolicyEvidence\";\n\nexport function principalPolicyRequestRecord(\n policy: PrincipalPolicyCheckpointEvidence,\n label = \"Container principal policy\",\n): Record<string, unknown> {\n return readCanonicalRecord(\n {\n principalType: policy.principalType,\n principalId: policy.principalId,\n version: policy.version,\n keyEpoch: policy.keyEpoch,\n stateHash: policy.stateHash,\n state: {\n ...policy.state,\n stateHash: policy.stateHash,\n },\n projection: policy.projection,\n grants: policy.grants,\n checkpoint: policy.checkpoint,\n },\n label,\n );\n}\n\nfunction principalPolicyKey(\n policy: Pick<\n VerifiedPrincipalPolicy,\n \"keyEpoch\" | \"principalId\" | \"principalType\" | \"stateHash\" | \"version\"\n >,\n): string {\n return [\n policy.principalType,\n policy.principalId,\n policy.version,\n policy.keyEpoch,\n policy.stateHash,\n ].join(\":\");\n}\n\nexport function uniquePrincipalPolicies<\n T extends PrincipalPolicyCurrentEvidence,\n>(policies: readonly T[]): T[] {\n const policiesByKey = new Map<string, T>();\n\n for (const policy of policies) {\n policiesByKey.set(principalPolicyKey(policy), policy);\n }\n\n return [...policiesByKey.values()];\n}\n"]}
1
+ {"version":3,"file":"principalPolicies.js","sourceRoot":"","sources":["principalPolicies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMjE,MAAM,UAAU,4BAA4B,CAC1C,MAAyC,EACzC,KAAK,GAAG,4BAA4B;IAEpC,OAAO,mBAAmB,CACxB;QACE,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE;YACL,GAAG,MAAM,CAAC,KAAK;YACf,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B;QACD,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,EACD,KAAK,CACN,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,MAGC;IAED,OAAO;QACL,MAAM,CAAC,aAAa;QACpB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,OAAO;QACd,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,SAAS;KACjB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,uBAAuB,CAErC,QAAsB;IACtB,MAAM,aAAa,GAAG,IAAI,GAAG,EAAa,CAAC;IAE3C,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import type { VerifiedPrincipalPolicy } from \"@tearleads/crypto\";\nimport { readCanonicalRecord } from \"../../keying/canonicalJson\";\nimport type {\n PrincipalPolicyCheckpointEvidence,\n PrincipalPolicyCurrentEvidence,\n} from \"../../principals/principalPolicyEvidence\";\n\nexport function principalPolicyRequestRecord(\n policy: PrincipalPolicyCheckpointEvidence,\n label = \"Container principal policy\",\n): Record<string, unknown> {\n return readCanonicalRecord(\n {\n principalType: policy.principalType,\n principalId: policy.principalId,\n version: policy.version,\n keyEpoch: policy.keyEpoch,\n stateHash: policy.stateHash,\n state: {\n ...policy.state,\n stateHash: policy.stateHash,\n },\n projection: policy.projection,\n grants: policy.grants,\n checkpoint: policy.checkpoint,\n },\n label,\n );\n}\n\nfunction principalPolicyKey(\n policy: Pick<\n VerifiedPrincipalPolicy,\n \"keyEpoch\" | \"principalId\" | \"principalType\" | \"stateHash\" | \"version\"\n >,\n): string {\n return [\n policy.principalType,\n policy.principalId,\n policy.version,\n policy.keyEpoch,\n policy.stateHash,\n ].join(\":\");\n}\n\nexport function uniquePrincipalPolicies<\n T extends PrincipalPolicyCurrentEvidence,\n>(policies: readonly T[]): T[] {\n const policiesByKey = new Map<string, T>();\n\n for (const policy of policies) {\n policiesByKey.set(principalPolicyKey(policy), policy);\n }\n\n return [...policiesByKey.values()];\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  export { readContainerKeyEpoch } from "../../keyingProjectionVerification/readers.js";
2
- import { readCanonicalRecord } from "../../keyingCanonicalJson.js";
2
+ import { readCanonicalRecord } from "../../keying/canonicalJson.js";
3
3
  import { readContainerKekRecipientTarget, readContainerKeyWrap, } from "../../keyingProjectionVerification/readers.js";
4
- import { readRecordNullableString, readRecordPositiveInteger, readRecordString, readRecordValue, } from "../../recordReaders.js";
4
+ import { readRecordNullableString, readRecordPositiveInteger, readRecordString, readRecordValue, } from "../../shared/recordReaders.js";
5
5
  function readRecordVersion(record, label) {
6
6
  if (readRecordPositiveInteger(record, "version", label) !== 1) {
7
7
  throw new Error(`${label}.version must be 1`);
@@ -1 +1 @@
1
- {"version":3,"file":"readers.js","sourceRoot":"","sources":["readers.ts"],"names":[],"mappings":"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","sourcesContent":["export { readContainerKeyEpoch } from \"../../keyingProjectionVerification/readers\";\n\nimport type {\n ContainerAccessManifestState,\n ContainerDirectGrant,\n ContainerKekRecipientTarget,\n ContainerKeyWrap,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWire } from \"@tearleads/validators/request\";\nimport { readCanonicalRecord } from \"../../keyingCanonicalJson\";\nimport {\n readContainerKekRecipientTarget,\n readContainerKeyWrap,\n} from \"../../keyingProjectionVerification/readers\";\nimport {\n readRecordNullableString,\n readRecordPositiveInteger,\n readRecordString,\n readRecordValue,\n} from \"../../recordReaders\";\n\nfunction readRecordVersion(\n record: Record<string, unknown>,\n label: string,\n): void {\n if (readRecordPositiveInteger(record, \"version\", label) !== 1) {\n throw new Error(`${label}.version must be 1`);\n }\n}\n\nexport function readCanonicalManifestBundle(\n value: unknown,\n label: string,\n): AccessManifestBundleWire {\n const record = readCanonicalRecord(value, label);\n return {\n event: readCanonicalRecord(\n readRecordValue(record, \"event\"),\n `${label}.event`,\n ),\n manifest: readCanonicalRecord(\n readRecordValue(record, \"manifest\"),\n `${label}.manifest`,\n ),\n manifestHash: readRecordString(record, \"manifestHash\", label),\n state: readCanonicalRecord(\n readRecordValue(record, \"state\"),\n `${label}.state`,\n ),\n };\n}\n\nfunction isContainerAccessLevel(\n value: unknown,\n): value is ContainerDirectGrant[\"accessLevel\"] {\n return value === \"admin\" || value === \"read\" || value === \"write\";\n}\n\nfunction isContainerGrantSubjectType(\n value: unknown,\n): value is ContainerDirectGrant[\"subjectType\"] {\n return value === \"group\" || value === \"user\";\n}\n\nfunction isContainerGrantPrincipalType(\n value: unknown,\n): value is ContainerAccessManifestState[\"referencedPrincipalHeads\"][number][\"principalType\"] {\n return value === \"group\";\n}\n\nfunction readContainerDirectGrant(\n value: unknown,\n label: string,\n): ContainerDirectGrant {\n const record = readCanonicalRecord(value, label);\n const accessLevel = readRecordValue(record, \"accessLevel\");\n const subjectType = readRecordValue(record, \"subjectType\");\n if (!isContainerAccessLevel(accessLevel)) {\n throw new Error(`${label}.accessLevel is invalid`);\n }\n if (!isContainerGrantSubjectType(subjectType)) {\n throw new Error(`${label}.subjectType is invalid`);\n }\n\n return {\n accessLevel,\n subjectId: readRecordString(record, \"subjectId\", label),\n subjectType,\n };\n}\n\nfunction readContainerDirectGrants(\n value: unknown,\n label: string,\n): ContainerDirectGrant[] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((grant, index) =>\n readContainerDirectGrant(grant, `${label}[${index}]`),\n );\n}\n\nfunction readReferencedPrincipalHead(\n value: unknown,\n label: string,\n): ContainerAccessManifestState[\"referencedPrincipalHeads\"][number] {\n const record = readCanonicalRecord(value, label);\n const principalType = readRecordValue(record, \"principalType\");\n if (!isContainerGrantPrincipalType(principalType)) {\n throw new Error(`${label}.principalType is invalid`);\n }\n\n return {\n principalType,\n principalId: readRecordString(record, \"principalId\", label),\n version: readRecordPositiveInteger(record, \"version\", label),\n keyEpoch: readRecordPositiveInteger(record, \"keyEpoch\", label),\n stateHash: readRecordString(record, \"stateHash\", label),\n keyFingerprint: readRecordString(record, \"keyFingerprint\", label),\n };\n}\n\nfunction readReferencedPrincipalHeads(\n value: unknown,\n label: string,\n): ContainerAccessManifestState[\"referencedPrincipalHeads\"] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((head, index) =>\n readReferencedPrincipalHead(head, `${label}[${index}]`),\n );\n}\n\nexport function readContainerAccessManifestState(\n value: unknown,\n label: string,\n): ContainerAccessManifestState {\n const record = readCanonicalRecord(value, label);\n readRecordVersion(record, label);\n\n return {\n systemSlot: readRecordNullableString(record, \"systemSlot\", label),\n version: 1,\n containerId: readRecordString(record, \"containerId\", label),\n organizationId: readRecordString(record, \"organizationId\", label),\n epoch: readRecordPositiveInteger(record, \"epoch\", label),\n previousManifestHash: readRecordNullableString(\n record,\n \"previousManifestHash\",\n label,\n ),\n eventHash: readRecordString(record, \"eventHash\", label),\n parentContainerId: readRecordNullableString(\n record,\n \"parentContainerId\",\n label,\n ),\n parentManifestHash: readRecordNullableString(\n record,\n \"parentManifestHash\",\n label,\n ),\n metadataDocumentId: readRecordString(record, \"metadataDocumentId\", label),\n containerKeyEpochId: readRecordNullableString(\n record,\n \"containerKeyEpochId\",\n label,\n ),\n containerKeyPublicKey: readRecordNullableString(\n record,\n \"containerKeyPublicKey\",\n label,\n ),\n directGrants: readContainerDirectGrants(\n readRecordValue(record, \"directGrants\"),\n `${label}.directGrants`,\n ),\n referencedPrincipalHeads: readReferencedPrincipalHeads(\n readRecordValue(record, \"referencedPrincipalHeads\"),\n `${label}.referencedPrincipalHeads`,\n ),\n };\n}\n\nexport function readContainerKeyWraps(\n value: unknown,\n label: string,\n): ContainerKeyWrap[] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((wrap, index) =>\n readContainerKeyWrap(wrap, `${label}[${index}]`),\n );\n}\n\nexport function readContainerKekRecipientTargets(\n value: unknown,\n label: string,\n): ContainerKekRecipientTarget[] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((target, index) =>\n readContainerKekRecipientTarget(target, `${label}[${index}]`),\n );\n}\n"]}
1
+ {"version":3,"file":"readers.js","sourceRoot":"","sources":["readers.ts"],"names":[],"mappings":"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","sourcesContent":["export { readContainerKeyEpoch } from \"../../keyingProjectionVerification/readers\";\n\nimport type {\n ContainerAccessManifestState,\n ContainerDirectGrant,\n ContainerKekRecipientTarget,\n ContainerKeyWrap,\n} from \"@tearleads/crypto\";\nimport type { AccessManifestBundleWire } from \"@tearleads/validators/request\";\nimport { readCanonicalRecord } from \"../../keying/canonicalJson\";\nimport {\n readContainerKekRecipientTarget,\n readContainerKeyWrap,\n} from \"../../keyingProjectionVerification/readers\";\nimport {\n readRecordNullableString,\n readRecordPositiveInteger,\n readRecordString,\n readRecordValue,\n} from \"../../shared/recordReaders\";\n\nfunction readRecordVersion(\n record: Record<string, unknown>,\n label: string,\n): void {\n if (readRecordPositiveInteger(record, \"version\", label) !== 1) {\n throw new Error(`${label}.version must be 1`);\n }\n}\n\nexport function readCanonicalManifestBundle(\n value: unknown,\n label: string,\n): AccessManifestBundleWire {\n const record = readCanonicalRecord(value, label);\n return {\n event: readCanonicalRecord(\n readRecordValue(record, \"event\"),\n `${label}.event`,\n ),\n manifest: readCanonicalRecord(\n readRecordValue(record, \"manifest\"),\n `${label}.manifest`,\n ),\n manifestHash: readRecordString(record, \"manifestHash\", label),\n state: readCanonicalRecord(\n readRecordValue(record, \"state\"),\n `${label}.state`,\n ),\n };\n}\n\nfunction isContainerAccessLevel(\n value: unknown,\n): value is ContainerDirectGrant[\"accessLevel\"] {\n return value === \"admin\" || value === \"read\" || value === \"write\";\n}\n\nfunction isContainerGrantSubjectType(\n value: unknown,\n): value is ContainerDirectGrant[\"subjectType\"] {\n return value === \"group\" || value === \"user\";\n}\n\nfunction isContainerGrantPrincipalType(\n value: unknown,\n): value is ContainerAccessManifestState[\"referencedPrincipalHeads\"][number][\"principalType\"] {\n return value === \"group\";\n}\n\nfunction readContainerDirectGrant(\n value: unknown,\n label: string,\n): ContainerDirectGrant {\n const record = readCanonicalRecord(value, label);\n const accessLevel = readRecordValue(record, \"accessLevel\");\n const subjectType = readRecordValue(record, \"subjectType\");\n if (!isContainerAccessLevel(accessLevel)) {\n throw new Error(`${label}.accessLevel is invalid`);\n }\n if (!isContainerGrantSubjectType(subjectType)) {\n throw new Error(`${label}.subjectType is invalid`);\n }\n\n return {\n accessLevel,\n subjectId: readRecordString(record, \"subjectId\", label),\n subjectType,\n };\n}\n\nfunction readContainerDirectGrants(\n value: unknown,\n label: string,\n): ContainerDirectGrant[] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((grant, index) =>\n readContainerDirectGrant(grant, `${label}[${index}]`),\n );\n}\n\nfunction readReferencedPrincipalHead(\n value: unknown,\n label: string,\n): ContainerAccessManifestState[\"referencedPrincipalHeads\"][number] {\n const record = readCanonicalRecord(value, label);\n const principalType = readRecordValue(record, \"principalType\");\n if (!isContainerGrantPrincipalType(principalType)) {\n throw new Error(`${label}.principalType is invalid`);\n }\n\n return {\n principalType,\n principalId: readRecordString(record, \"principalId\", label),\n version: readRecordPositiveInteger(record, \"version\", label),\n keyEpoch: readRecordPositiveInteger(record, \"keyEpoch\", label),\n stateHash: readRecordString(record, \"stateHash\", label),\n keyFingerprint: readRecordString(record, \"keyFingerprint\", label),\n };\n}\n\nfunction readReferencedPrincipalHeads(\n value: unknown,\n label: string,\n): ContainerAccessManifestState[\"referencedPrincipalHeads\"] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((head, index) =>\n readReferencedPrincipalHead(head, `${label}[${index}]`),\n );\n}\n\nexport function readContainerAccessManifestState(\n value: unknown,\n label: string,\n): ContainerAccessManifestState {\n const record = readCanonicalRecord(value, label);\n readRecordVersion(record, label);\n\n return {\n systemSlot: readRecordNullableString(record, \"systemSlot\", label),\n version: 1,\n containerId: readRecordString(record, \"containerId\", label),\n organizationId: readRecordString(record, \"organizationId\", label),\n epoch: readRecordPositiveInteger(record, \"epoch\", label),\n previousManifestHash: readRecordNullableString(\n record,\n \"previousManifestHash\",\n label,\n ),\n eventHash: readRecordString(record, \"eventHash\", label),\n parentContainerId: readRecordNullableString(\n record,\n \"parentContainerId\",\n label,\n ),\n parentManifestHash: readRecordNullableString(\n record,\n \"parentManifestHash\",\n label,\n ),\n metadataDocumentId: readRecordString(record, \"metadataDocumentId\", label),\n containerKeyEpochId: readRecordNullableString(\n record,\n \"containerKeyEpochId\",\n label,\n ),\n containerKeyPublicKey: readRecordNullableString(\n record,\n \"containerKeyPublicKey\",\n label,\n ),\n directGrants: readContainerDirectGrants(\n readRecordValue(record, \"directGrants\"),\n `${label}.directGrants`,\n ),\n referencedPrincipalHeads: readReferencedPrincipalHeads(\n readRecordValue(record, \"referencedPrincipalHeads\"),\n `${label}.referencedPrincipalHeads`,\n ),\n };\n}\n\nexport function readContainerKeyWraps(\n value: unknown,\n label: string,\n): ContainerKeyWrap[] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((wrap, index) =>\n readContainerKeyWrap(wrap, `${label}[${index}]`),\n );\n}\n\nexport function readContainerKekRecipientTargets(\n value: unknown,\n label: string,\n): ContainerKekRecipientTarget[] {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be an array`);\n }\n return value.map((target, index) =>\n readContainerKekRecipientTarget(target, `${label}[${index}]`),\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { bytesToHex, createIncrementalSha256 } from "../../internal/crypto/index.js";
2
- import { createBlobByteSource, } from "../blobContracts.js";
2
+ import { createBlobByteSource, } from "../blobs/blobContracts.js";
3
3
  /** Kept inside encrypted document content; independent of upload encryption/retries. */
4
4
  export async function attachmentContentSha256(input) {
5
5
  const source = createBlobByteSource(input);
@@ -1 +1 @@
1
- {"version":3,"file":"attachmentContentIdentity.js","sourceRoot":"","sources":["attachmentContentIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAEL,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAE1B,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAA0B;IAE1B,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IAClC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM;YAC7B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import { bytesToHex, createIncrementalSha256 } from \"@tearleads/crypto\";\nimport {\n type BlobByteSourceInput,\n createBlobByteSource,\n} from \"../blobContracts\";\n\n/** Kept inside encrypted document content; independent of upload encryption/retries. */\nexport async function attachmentContentSha256(\n input: BlobByteSourceInput,\n): Promise<string> {\n const source = createBlobByteSource(input);\n const hash = createIncrementalSha256();\n const chunkSize = 5 * 1024 * 1024;\n for (let offset = 0; offset < source.byteLength; offset += chunkSize) {\n const length = Math.min(chunkSize, source.byteLength - offset);\n const bytes = await source.read(offset, length);\n if (bytes.byteLength !== length)\n throw new Error(\"Attachment source returned an unexpected byte length\");\n hash.update(bytes);\n }\n return bytesToHex(hash.digest());\n}\n"]}
1
+ {"version":3,"file":"attachmentContentIdentity.js","sourceRoot":"","sources":["attachmentContentIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAEL,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAA0B;IAE1B,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IAClC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM;YAC7B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import { bytesToHex, createIncrementalSha256 } from \"@tearleads/crypto\";\nimport {\n type BlobByteSourceInput,\n createBlobByteSource,\n} from \"../blobs/blobContracts\";\n\n/** Kept inside encrypted document content; independent of upload encryption/retries. */\nexport async function attachmentContentSha256(\n input: BlobByteSourceInput,\n): Promise<string> {\n const source = createBlobByteSource(input);\n const hash = createIncrementalSha256();\n const chunkSize = 5 * 1024 * 1024;\n for (let offset = 0; offset < source.byteLength; offset += chunkSize) {\n const length = Math.min(chunkSize, source.byteLength - offset);\n const bytes = await source.read(offset, length);\n if (bytes.byteLength !== length)\n throw new Error(\"Attachment source returned an unexpected byte length\");\n hash.update(bytes);\n }\n return bytesToHex(hash.digest());\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"blobEnvelopeStream.js","sourceRoot":"","sources":["blobEnvelopeStream.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,yBAAyB,EACzB,gCAAgC,GACjC,MAAM,mBAAmB,CAAC;AAG3B,gFAAgF;AAChF,MAAM,UAAU,wBAAwB,CAAC,MAAkC;IACzE,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,IAAI,OAAO,GAAe,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,KAAK,EAAE,MAAc,EAAsB,EAAE;QACxD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,MAAM,EAAE,CAAC;YACvB,IAAI,OAAO,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,IAAI;oBACZ,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;gBAChE,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YAC5D,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;YAC9C,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,UAAU;YACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAAC,CAAC;YACtD,MAAM,gBAAgB,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;YAC/C,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClB,KAAK,CAAC,GAAG,CACP,MAAM,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC,EAChD,MAAM,CAAC,UAAU,CAClB,CAAC;YACF,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,CAAC,MAAM;YACV,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;gBACrC,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,qDAAqD;YACvD,CAAC;YACD,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import {\n BLOB_ENVELOPE_PREFIX_BYTES,\n createIncrementalSha256,\n parseBlobEnvelopeV2Header,\n readBlobEnvelopeHeaderByteLength,\n} from \"@tearleads/crypto\";\nimport type { BlobBytes } from \"../../../blobContracts\";\n\n/** Reads exactly one bounded envelope part without retaining previous parts. */\nexport function createBlobEnvelopeStream(stream: ReadableStream<Uint8Array>) {\n const reader = stream.getReader();\n const hash = createIncrementalSha256();\n let pending: Uint8Array = new Uint8Array(0);\n const read = async (length: number): Promise<BlobBytes> => {\n const bytes = new Uint8Array(length);\n let offset = 0;\n while (offset < length) {\n if (pending.byteLength === 0) {\n const chunk = await reader.read();\n if (chunk.done)\n throw new Error(\"Blob encrypted bytes envelope is truncated\");\n pending = chunk.value;\n continue;\n }\n const count = Math.min(length - offset, pending.byteLength);\n bytes.set(pending.subarray(0, count), offset);\n pending = pending.subarray(count);\n offset += count;\n }\n hash.update(bytes);\n return bytes;\n };\n return {\n read,\n async readHeader() {\n const prefix = await read(BLOB_ENVELOPE_PREFIX_BYTES);\n const headerByteLength = readBlobEnvelopeHeaderByteLength(prefix);\n const bytes = new Uint8Array(headerByteLength);\n bytes.set(prefix);\n bytes.set(\n await read(headerByteLength - prefix.byteLength),\n prefix.byteLength,\n );\n return parseBlobEnvelopeV2Header(bytes);\n },\n async finish() {\n if (pending.byteLength > 0)\n throw new Error(\"Blob encrypted bytes length is invalid\");\n while (true) {\n const chunk = await reader.read();\n if (chunk.done) return hash.digest();\n if (chunk.value.byteLength > 0)\n throw new Error(\"Blob encrypted bytes length is invalid\");\n }\n },\n async close() {\n try {\n await reader.cancel();\n } catch {\n /* Preserve the verification or transport failure. */\n }\n reader.releaseLock();\n },\n };\n}\n"]}
1
+ {"version":3,"file":"blobEnvelopeStream.js","sourceRoot":"","sources":["blobEnvelopeStream.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,yBAAyB,EACzB,gCAAgC,GACjC,MAAM,mBAAmB,CAAC;AAG3B,gFAAgF;AAChF,MAAM,UAAU,wBAAwB,CAAC,MAAkC;IACzE,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,IAAI,OAAO,GAAe,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,KAAK,EAAE,MAAc,EAAsB,EAAE;QACxD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,MAAM,EAAE,CAAC;YACvB,IAAI,OAAO,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,IAAI;oBACZ,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;gBAChE,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YAC5D,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;YAC9C,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,UAAU;YACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAAC,CAAC;YACtD,MAAM,gBAAgB,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;YAC/C,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClB,KAAK,CAAC,GAAG,CACP,MAAM,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC,EAChD,MAAM,CAAC,UAAU,CAClB,CAAC;YACF,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,CAAC,MAAM;YACV,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;gBACrC,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,qDAAqD;YACvD,CAAC;YACD,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import {\n BLOB_ENVELOPE_PREFIX_BYTES,\n createIncrementalSha256,\n parseBlobEnvelopeV2Header,\n readBlobEnvelopeHeaderByteLength,\n} from \"@tearleads/crypto\";\nimport type { BlobBytes } from \"../../../blobs/blobContracts\";\n\n/** Reads exactly one bounded envelope part without retaining previous parts. */\nexport function createBlobEnvelopeStream(stream: ReadableStream<Uint8Array>) {\n const reader = stream.getReader();\n const hash = createIncrementalSha256();\n let pending: Uint8Array = new Uint8Array(0);\n const read = async (length: number): Promise<BlobBytes> => {\n const bytes = new Uint8Array(length);\n let offset = 0;\n while (offset < length) {\n if (pending.byteLength === 0) {\n const chunk = await reader.read();\n if (chunk.done)\n throw new Error(\"Blob encrypted bytes envelope is truncated\");\n pending = chunk.value;\n continue;\n }\n const count = Math.min(length - offset, pending.byteLength);\n bytes.set(pending.subarray(0, count), offset);\n pending = pending.subarray(count);\n offset += count;\n }\n hash.update(bytes);\n return bytes;\n };\n return {\n read,\n async readHeader() {\n const prefix = await read(BLOB_ENVELOPE_PREFIX_BYTES);\n const headerByteLength = readBlobEnvelopeHeaderByteLength(prefix);\n const bytes = new Uint8Array(headerByteLength);\n bytes.set(prefix);\n bytes.set(\n await read(headerByteLength - prefix.byteLength),\n prefix.byteLength,\n );\n return parseBlobEnvelopeV2Header(bytes);\n },\n async finish() {\n if (pending.byteLength > 0)\n throw new Error(\"Blob encrypted bytes length is invalid\");\n while (true) {\n const chunk = await reader.read();\n if (chunk.done) return hash.digest();\n if (chunk.value.byteLength > 0)\n throw new Error(\"Blob encrypted bytes length is invalid\");\n }\n },\n async close() {\n try {\n await reader.cancel();\n } catch {\n /* Preserve the verification or transport failure. */\n }\n reader.releaseLock();\n },\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { BlobByteSource, BlobBytes } from "../../../blobContracts.js";
1
+ import type { BlobByteSource, BlobBytes } from "../../../blobs/blobContracts.js";
2
2
  import type { BlobSourceSnapshot } from "./types.js";
3
3
  export type { BlobSourceSnapshot } from "./types.js";
4
4
  export declare function inspectBlobSource(source: BlobByteSource, chunkSize: number): Promise<BlobSourceSnapshot>;
@@ -1 +1 @@
1
- {"version":3,"file":"blobSourceSnapshot.js","sourceRoot":"","sources":["blobSourceSnapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAKxD,KAAK,UAAU,SAAS,CAAC,KAAiB;IACxC,OAAO,UAAU,CACf,IAAI,UAAU,CACZ,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAC/D,CACF,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,UAAkB;IAChD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,KAInC;IACC,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACtE,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAsB,EACtB,SAAiB;IAEjB,sBAAsB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1C,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACvE,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,uBAAuB,EAAE,CAAC;IAE7C,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,UAAU,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,UAAU,GAAG,4BAA4B,CAAC;YAC9C,UAAU;YACV,UAAU;YACV,SAAS;YACT,mBAAmB,EAAE,MAAM,CAAC,UAAU;SACvC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC;YACvC,UAAU;YACV,MAAM,EAAE,UAAU,GAAG,SAAS;YAC9B,MAAM;SACP,CAAC,CAAC;QACH,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,WAAW,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,WAAW;QACX,SAAS;QACT,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAIjD;IACC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAC/C,IAAI,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,UAAU,GAAG,qBAAqB,CACtC,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,SAAS,CACnB,CAAC;IACF,MAAM,UAAU,GAAG,4BAA4B,CAAC;QAC9C,UAAU;QACV,UAAU;QACV,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,mBAAmB,EAAE,QAAQ,CAAC,UAAU;KACzC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC;QACvC,UAAU;QACV,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC,SAAS;QACvC,MAAM;KACP,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,wBAAwB,UAAU,kCAAkC,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import {\n blobChunkPlaintextByteLength,\n bytesToHex,\n computeBlobChunkCount,\n createIncrementalSha256,\n normalizeBlobChunkSize,\n} from \"@tearleads/crypto\";\nimport type { BlobByteSource, BlobBytes } from \"../../../blobContracts\";\nimport { asWebCryptoBytes } from \"../../shared/readers\";\nimport type { BlobSourceSnapshot } from \"./types\";\n\nexport type { BlobSourceSnapshot } from \"./types\";\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n return bytesToHex(\n new Uint8Array(\n await crypto.subtle.digest(\"SHA-256\", asWebCryptoBytes(bytes)),\n ),\n );\n}\n\nfunction assertSourceByteLength(byteLength: number): void {\n if (!Number.isSafeInteger(byteLength) || byteLength < 0) {\n throw new Error(\n \"Blob source byte length must be a non-negative safe integer\",\n );\n }\n}\n\nasync function readExactSourceBytes(input: {\n readonly byteLength: number;\n readonly offset: number;\n readonly source: BlobByteSource;\n}): Promise<BlobBytes> {\n const bytes = await input.source.read(input.offset, input.byteLength);\n if (bytes.byteLength !== input.byteLength) {\n throw new Error(\"Blob source returned an unexpected byte length\");\n }\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy;\n}\n\nexport async function inspectBlobSource(\n source: BlobByteSource,\n chunkSize: number,\n): Promise<BlobSourceSnapshot> {\n assertSourceByteLength(source.byteLength);\n normalizeBlobChunkSize(chunkSize);\n const chunkCount = computeBlobChunkCount(source.byteLength, chunkSize);\n const chunkSha256: string[] = [];\n const objectHash = createIncrementalSha256();\n\n for (let chunkIndex = 0; chunkIndex < chunkCount; chunkIndex += 1) {\n const byteLength = blobChunkPlaintextByteLength({\n chunkCount,\n chunkIndex,\n chunkSize,\n plaintextByteLength: source.byteLength,\n });\n const bytes = await readExactSourceBytes({\n byteLength,\n offset: chunkIndex * chunkSize,\n source,\n });\n objectHash.update(bytes);\n chunkSha256.push(await sha256Hex(bytes));\n }\n\n return {\n byteLength: source.byteLength,\n chunkSha256,\n chunkSize,\n sha256: bytesToHex(objectHash.digest()),\n };\n}\n\nexport async function readVerifiedBlobSourceChunk(input: {\n readonly chunkIndex: number;\n readonly snapshot: BlobSourceSnapshot;\n readonly source: BlobByteSource;\n}): Promise<BlobBytes> {\n const { chunkIndex, snapshot, source } = input;\n if (source.byteLength !== snapshot.byteLength) {\n throw new Error(\"Blob source byte length changed after inspection\");\n }\n const chunkCount = computeBlobChunkCount(\n snapshot.byteLength,\n snapshot.chunkSize,\n );\n const byteLength = blobChunkPlaintextByteLength({\n chunkCount,\n chunkIndex,\n chunkSize: snapshot.chunkSize,\n plaintextByteLength: snapshot.byteLength,\n });\n const bytes = await readExactSourceBytes({\n byteLength,\n offset: chunkIndex * snapshot.chunkSize,\n source,\n });\n if ((await sha256Hex(bytes)) !== snapshot.chunkSha256[chunkIndex]) {\n throw new Error(\n `Blob plaintext chunk ${chunkIndex} changed after source inspection`,\n );\n }\n return bytes;\n}\n"]}
1
+ {"version":3,"file":"blobSourceSnapshot.js","sourceRoot":"","sources":["blobSourceSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n blobChunkPlaintextByteLength,\n bytesToHex,\n computeBlobChunkCount,\n createIncrementalSha256,\n normalizeBlobChunkSize,\n} from \"@tearleads/crypto\";\nimport type { BlobByteSource, BlobBytes } from \"../../../blobs/blobContracts\";\nimport { asWebCryptoBytes } from \"../../shared/readers\";\nimport type { BlobSourceSnapshot } from \"./types\";\n\nexport type { BlobSourceSnapshot } from \"./types\";\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n return bytesToHex(\n new Uint8Array(\n await crypto.subtle.digest(\"SHA-256\", asWebCryptoBytes(bytes)),\n ),\n );\n}\n\nfunction assertSourceByteLength(byteLength: number): void {\n if (!Number.isSafeInteger(byteLength) || byteLength < 0) {\n throw new Error(\n \"Blob source byte length must be a non-negative safe integer\",\n );\n }\n}\n\nasync function readExactSourceBytes(input: {\n readonly byteLength: number;\n readonly offset: number;\n readonly source: BlobByteSource;\n}): Promise<BlobBytes> {\n const bytes = await input.source.read(input.offset, input.byteLength);\n if (bytes.byteLength !== input.byteLength) {\n throw new Error(\"Blob source returned an unexpected byte length\");\n }\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy;\n}\n\nexport async function inspectBlobSource(\n source: BlobByteSource,\n chunkSize: number,\n): Promise<BlobSourceSnapshot> {\n assertSourceByteLength(source.byteLength);\n normalizeBlobChunkSize(chunkSize);\n const chunkCount = computeBlobChunkCount(source.byteLength, chunkSize);\n const chunkSha256: string[] = [];\n const objectHash = createIncrementalSha256();\n\n for (let chunkIndex = 0; chunkIndex < chunkCount; chunkIndex += 1) {\n const byteLength = blobChunkPlaintextByteLength({\n chunkCount,\n chunkIndex,\n chunkSize,\n plaintextByteLength: source.byteLength,\n });\n const bytes = await readExactSourceBytes({\n byteLength,\n offset: chunkIndex * chunkSize,\n source,\n });\n objectHash.update(bytes);\n chunkSha256.push(await sha256Hex(bytes));\n }\n\n return {\n byteLength: source.byteLength,\n chunkSha256,\n chunkSize,\n sha256: bytesToHex(objectHash.digest()),\n };\n}\n\nexport async function readVerifiedBlobSourceChunk(input: {\n readonly chunkIndex: number;\n readonly snapshot: BlobSourceSnapshot;\n readonly source: BlobByteSource;\n}): Promise<BlobBytes> {\n const { chunkIndex, snapshot, source } = input;\n if (source.byteLength !== snapshot.byteLength) {\n throw new Error(\"Blob source byte length changed after inspection\");\n }\n const chunkCount = computeBlobChunkCount(\n snapshot.byteLength,\n snapshot.chunkSize,\n );\n const byteLength = blobChunkPlaintextByteLength({\n chunkCount,\n chunkIndex,\n chunkSize: snapshot.chunkSize,\n plaintextByteLength: snapshot.byteLength,\n });\n const bytes = await readExactSourceBytes({\n byteLength,\n offset: chunkIndex * snapshot.chunkSize,\n source,\n });\n if ((await sha256Hex(bytes)) !== snapshot.chunkSha256[chunkIndex]) {\n throw new Error(\n `Blob plaintext chunk ${chunkIndex} changed after source inspection`,\n );\n }\n return bytes;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"chunkedBlobCrypto.js","sourceRoot":"","sources":["chunkedBlobCrypto.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,EACvB,UAAU,EACV,+BAA+B,EAC/B,qBAAqB,EACrB,8BAA8B,EAC9B,mCAAmC,EACnC,cAAc,EACd,uBAAuB,EACvB,iBAAiB,EACjB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EACL,gCAAgC,EAChC,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAGpE,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AA4BnE,KAAK,UAAU,2BAA2B,CACxC,KAAiC,EACjC,QAA4B;IAE5B,MAAM,SAAS,GAAG,sBAAsB,CACtC,KAAK,CAAC,SAAS,IAAI,6BAA6B,CACjD,CAAC;IACF,MAAM,mBAAmB,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;IACpD,MAAM,SAAS,GAAG,qBAAqB,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IACxE,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC,gBAAgB,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,SAAS,IAAI,cAAc,EAAE,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;QACpC,SAAS;QACT,SAAS;QACT,eAAe,EAAE,QAAQ,CAAC,MAAM;KACjC,CAAC,CAAC;IAEH,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxD,mCAAmC,CAAC;YAClC,OAAO,EAAE,CAAC;YACV,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,UAAU,EAAE,MAAM;YAClB,QAAQ,EAAE,KAAK,CAAC,MAAM;YACtB,eAAe;YACf,eAAe,EAAE,+BAA+B;YAChD,eAAe;SAChB,CAAC;QACF,uBAAuB,CAAC;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,mBAAmB;YAC/B,UAAU,EAAE,SAAS;YACrB,SAAS;YACT,eAAe;SAChB,CAAC;KACH,CAAC,CAAC;IACH,MAAM,kBAAkB,GAAG,MAAM,wBAAwB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC;QACjD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,eAAe;QACf,kBAAkB;QAClB,eAAe;QACf,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IACH,OAAO;QACL,MAAM;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS;QACT,eAAe;QACf,eAAe;QACf,WAAW,EAAE,0BAA0B,CAAC;YACtC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,mBAAmB;YAC/B,UAAU,EAAE,SAAS;YACrB,SAAS;YACT,eAAe;YACf,eAAe;YACf,eAAe,EAAE,+BAA+B;YAChD,MAAM,EAAE,2BAA2B;YACnC,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC;YACzB,YAAY;YACZ,eAAe;YACf,OAAO,EAAE,4BAA4B;SACtC,CAAC;QACF,YAAY;QACZ,eAAe;QACf,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,SAAS;QACT,mBAAmB;QACnB,SAAS;KACV,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,OAA8B,EAC9B,UAAkB,EAClB,SAAoB;IAEpB,OAAO,IAAI,UAAU,CACnB,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CACzB;QACE,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,iBAAiB,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC;QACjD,cAAc,EAAE,gCAAgC,CAAC;YAC/C,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,UAAU;YACV,wBAAwB,EAAE,SAAS,CAAC,UAAU;YAC9C,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;SACjD,CAAC;KACH,EACD,OAAO,CAAC,SAAS,EACjB,SAAS,CACV,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,MAAsB,EACtB,QAA4B,EAC5B,OAA8B;IAE9B,MAAM,UAAU,GAAG,uBAAuB,EAAE,CAAC;IAC7C,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,UAAU,IAAI,CAAC,EAAE,CAAC;QACzE,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC;YAClD,UAAU;YACV,QAAQ;YACR,MAAM;SACP,CAAC,CAAC;QACH,UAAU,CAAC,MAAM,CAAC,MAAM,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,wBAAwB,CAAC,KAKjC;IACC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACpD,MAAM,UAAU,GAAG,8BAA8B,CAAC;QAChD,UAAU,EAAE,OAAO,CAAC,SAAS;QAC7B,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,UAAU;QAChD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;IACH,OAAO;QACL,UAAU;QACV,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,eAAe,EAAE,QAAQ,CAAC,MAAM;QAChC,MAAM;QACN,GAAG,0BAA0B,CAAC;YAC5B,UAAU;YACV,SAAS,EAAE,OAAO,CAAC,SAAS,GAAG,iBAAiB;YAChD,MAAM,EAAE,OAAO,CAAC,WAAW;YAC3B,KAAK,CAAC,YAAY,CAAC,UAAU;gBAC3B,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC;oBAClD,UAAU;oBACV,QAAQ;oBACR,MAAM;iBACP,CAAC,CAAC;gBACH,OAAO,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;YAC1D,CAAC;SACF,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAiC;IAEjC,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,SAAS,GAAG,sBAAsB,CACtC,KAAK,CAAC,SAAS,IAAI,6BAA6B,CACjD,CAAC;IACF,MAAM,QAAQ,GACZ,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnE,IACE,QAAQ,CAAC,UAAU,KAAK,OAAO,CAAC,mBAAmB;QACnD,QAAQ,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,EACxC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5E,OAAO,wBAAwB,CAAC;QAC9B,OAAO;QACP,MAAM;QACN,QAAQ;QACR,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n AES_256_KEY_BYTES,\n AES_GCM_TAG_BYTES,\n assertAesGcmIv,\n BLOB_CHUNK_SIZE_BYTES,\n BLOB_ENCRYPTED_BYTES_FORMAT,\n BLOB_ENCRYPTED_BYTES_VERSION,\n blobContentMetadataHash,\n bytesToHex,\n CONTENT_RECORD_ENCRYPTION_SUITE,\n computeBlobChunkCount,\n computeBlobEncryptedByteLength,\n computeContentRecordNonceDomainHash,\n createAesGcmIv,\n createIncrementalSha256,\n deriveBlobChunkIv,\n encodeBlobEnvelopeV2Header,\n normalizeBlobChunkSize,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type { BlobContentKeyBundleRequest } from \"@tearleads/validators/request\";\nimport type { BlobByteSource, BlobBytes } from \"../../../blobContracts\";\nimport { importContentKeyMaterial } from \"../../shared/contentRecordKeys\";\nimport {\n contentRecordAdditionalDataBytes,\n deriveBlobBaseIv,\n deriveBlobContentRecordKey,\n} from \"./blobRecordCrypto\";\nimport {\n type BlobSourceSnapshot,\n inspectBlobSource,\n readVerifiedBlobSourceChunk,\n} from \"./blobSourceSnapshot\";\nimport { createEncryptedUploadParts } from \"./encryptedUploadParts\";\nimport type { BlobEncryptionPlan } from \"./types\";\n\nexport const DEFAULT_BLOB_CHUNK_SIZE_BYTES = BLOB_CHUNK_SIZE_BYTES;\n\ninterface PrepareBlobEncryptionInput {\n readonly blobId: string;\n readonly chunkSize?: number | undefined;\n readonly contentKey: Uint8Array;\n readonly contentKeyBundle: BlobContentKeyBundleRequest;\n readonly nonceSeed?: Uint8Array | undefined;\n readonly organizationId: string;\n readonly source: BlobByteSource;\n readonly sourceSnapshot?: BlobSourceSnapshot | undefined;\n}\n\ninterface BlobEncryptionContext {\n readonly baseIv: BlobBytes;\n readonly blobId: string;\n readonly chunkSize: number;\n readonly contentKeyEpoch: number;\n readonly contentRecordId: string;\n readonly headerBytes: BlobBytes;\n readonly metadataHash: string;\n readonly nonceDomainHash: string;\n readonly organizationId: string;\n readonly partCount: number;\n readonly plaintextByteLength: number;\n readonly recordKey: CryptoKey;\n}\n\nasync function createBlobEncryptionContext(\n input: PrepareBlobEncryptionInput,\n snapshot: BlobSourceSnapshot,\n): Promise<BlobEncryptionContext> {\n const chunkSize = normalizeBlobChunkSize(\n input.chunkSize ?? DEFAULT_BLOB_CHUNK_SIZE_BYTES,\n );\n const plaintextByteLength = input.source.byteLength;\n const partCount = computeBlobChunkCount(plaintextByteLength, chunkSize);\n const contentRecordId = input.blobId;\n const { contentKeyEpoch } = input.contentKeyBundle;\n const nonceSeed = new Uint8Array(input.nonceSeed ?? createAesGcmIv());\n const baseIv = await deriveBlobBaseIv({\n chunkSize,\n nonceSeed,\n plaintextSha256: snapshot.sha256,\n });\n\n const [nonceDomainHash, metadataHash] = await Promise.all([\n computeContentRecordNonceDomainHash({\n version: 1,\n organizationId: input.organizationId,\n objectKind: \"blob\",\n objectId: input.blobId,\n contentKeyEpoch,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n contentRecordId,\n }),\n blobContentMetadataHash({\n blobId: input.blobId,\n byteLength: plaintextByteLength,\n chunkCount: partCount,\n chunkSize,\n contentKeyEpoch,\n }),\n ]);\n const contentKeyMaterial = await importContentKeyMaterial(input.contentKey);\n const recordKey = await deriveBlobContentRecordKey({\n blobId: input.blobId,\n contentKeyEpoch,\n contentKeyMaterial,\n contentRecordId,\n organizationId: input.organizationId,\n usage: \"encrypt\",\n });\n return {\n baseIv,\n blobId: input.blobId,\n chunkSize,\n contentKeyEpoch,\n contentRecordId,\n headerBytes: encodeBlobEnvelopeV2Header({\n blobId: input.blobId,\n byteLength: plaintextByteLength,\n chunkCount: partCount,\n chunkSize,\n contentKeyEpoch,\n contentRecordId,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n format: BLOB_ENCRYPTED_BYTES_FORMAT,\n iv: bytesToBase64(baseIv),\n metadataHash,\n nonceDomainHash,\n version: BLOB_ENCRYPTED_BYTES_VERSION,\n }),\n metadataHash,\n nonceDomainHash,\n organizationId: input.organizationId,\n partCount,\n plaintextByteLength,\n recordKey,\n };\n}\n\nasync function encryptBlobChunk(\n context: BlobEncryptionContext,\n chunkIndex: number,\n plaintext: BlobBytes,\n): Promise<BlobBytes> {\n return new Uint8Array(\n await crypto.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: deriveBlobChunkIv(context.baseIv, chunkIndex),\n additionalData: contentRecordAdditionalDataBytes({\n blobId: context.blobId,\n chunkCount: context.partCount,\n chunkIndex,\n chunkPlaintextByteLength: plaintext.byteLength,\n chunkSize: context.chunkSize,\n contentKeyEpoch: context.contentKeyEpoch,\n contentRecordId: context.contentRecordId,\n metadataHash: context.metadataHash,\n nonceDomainHash: context.nonceDomainHash,\n organizationId: context.organizationId,\n plaintextByteLength: context.plaintextByteLength,\n }),\n },\n context.recordKey,\n plaintext,\n ),\n );\n}\n\nasync function runEncryptionHashPass(\n source: BlobByteSource,\n snapshot: BlobSourceSnapshot,\n context: BlobEncryptionContext,\n): Promise<string> {\n const objectHash = createIncrementalSha256();\n objectHash.update(context.headerBytes);\n for (let chunkIndex = 0; chunkIndex < context.partCount; chunkIndex += 1) {\n const plaintext = await readVerifiedBlobSourceChunk({\n chunkIndex,\n snapshot,\n source,\n });\n objectHash.update(await encryptBlobChunk(context, chunkIndex, plaintext));\n }\n return bytesToHex(objectHash.digest());\n}\n\nfunction createBlobEncryptionPlan(input: {\n readonly context: BlobEncryptionContext;\n readonly sha256: string;\n readonly snapshot: BlobSourceSnapshot;\n readonly source: BlobByteSource;\n}): BlobEncryptionPlan {\n const { context, sha256, snapshot, source } = input;\n const byteLength = computeBlobEncryptedByteLength({\n chunkCount: context.partCount,\n headerByteLength: context.headerBytes.byteLength,\n plaintextByteLength: context.plaintextByteLength,\n });\n return {\n byteLength,\n chunkSize: context.chunkSize,\n metadataHash: context.metadataHash,\n plaintextByteLength: context.plaintextByteLength,\n plaintextSha256: snapshot.sha256,\n sha256,\n ...createEncryptedUploadParts({\n byteLength,\n chunkSize: context.chunkSize + AES_GCM_TAG_BYTES,\n header: context.headerBytes,\n async encryptChunk(chunkIndex) {\n const plaintext = await readVerifiedBlobSourceChunk({\n chunkIndex,\n snapshot,\n source,\n });\n return encryptBlobChunk(context, chunkIndex, plaintext);\n },\n }),\n };\n}\n\nexport async function prepareBlobEncryption(\n input: PrepareBlobEncryptionInput,\n): Promise<BlobEncryptionPlan> {\n if (input.contentKey.byteLength !== AES_256_KEY_BYTES) {\n throw new Error(\"Blob content key must be 32 bytes\");\n }\n if (input.nonceSeed) {\n assertAesGcmIv(input.nonceSeed, \"Blob nonce seed is invalid\");\n }\n const chunkSize = normalizeBlobChunkSize(\n input.chunkSize ?? DEFAULT_BLOB_CHUNK_SIZE_BYTES,\n );\n const snapshot =\n input.sourceSnapshot ?? (await inspectBlobSource(input.source, chunkSize));\n const context = await createBlobEncryptionContext(input, snapshot);\n if (\n snapshot.byteLength !== context.plaintextByteLength ||\n snapshot.chunkSize !== context.chunkSize\n ) {\n throw new Error(\"Blob source snapshot does not match encryption layout\");\n }\n const sha256 = await runEncryptionHashPass(input.source, snapshot, context);\n return createBlobEncryptionPlan({\n context,\n sha256,\n snapshot,\n source: input.source,\n });\n}\n"]}
1
+ {"version":3,"file":"chunkedBlobCrypto.js","sourceRoot":"","sources":["chunkedBlobCrypto.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AES_256_KEY_BYTES,\n AES_GCM_TAG_BYTES,\n assertAesGcmIv,\n BLOB_CHUNK_SIZE_BYTES,\n BLOB_ENCRYPTED_BYTES_FORMAT,\n BLOB_ENCRYPTED_BYTES_VERSION,\n blobContentMetadataHash,\n bytesToHex,\n CONTENT_RECORD_ENCRYPTION_SUITE,\n computeBlobChunkCount,\n computeBlobEncryptedByteLength,\n computeContentRecordNonceDomainHash,\n createAesGcmIv,\n createIncrementalSha256,\n deriveBlobChunkIv,\n encodeBlobEnvelopeV2Header,\n normalizeBlobChunkSize,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type { BlobContentKeyBundleRequest } from \"@tearleads/validators/request\";\nimport type { BlobByteSource, BlobBytes } from \"../../../blobs/blobContracts\";\nimport { importContentKeyMaterial } from \"../../shared/contentRecordKeys\";\nimport {\n contentRecordAdditionalDataBytes,\n deriveBlobBaseIv,\n deriveBlobContentRecordKey,\n} from \"./blobRecordCrypto\";\nimport {\n type BlobSourceSnapshot,\n inspectBlobSource,\n readVerifiedBlobSourceChunk,\n} from \"./blobSourceSnapshot\";\nimport { createEncryptedUploadParts } from \"./encryptedUploadParts\";\nimport type { BlobEncryptionPlan } from \"./types\";\n\nexport const DEFAULT_BLOB_CHUNK_SIZE_BYTES = BLOB_CHUNK_SIZE_BYTES;\n\ninterface PrepareBlobEncryptionInput {\n readonly blobId: string;\n readonly chunkSize?: number | undefined;\n readonly contentKey: Uint8Array;\n readonly contentKeyBundle: BlobContentKeyBundleRequest;\n readonly nonceSeed?: Uint8Array | undefined;\n readonly organizationId: string;\n readonly source: BlobByteSource;\n readonly sourceSnapshot?: BlobSourceSnapshot | undefined;\n}\n\ninterface BlobEncryptionContext {\n readonly baseIv: BlobBytes;\n readonly blobId: string;\n readonly chunkSize: number;\n readonly contentKeyEpoch: number;\n readonly contentRecordId: string;\n readonly headerBytes: BlobBytes;\n readonly metadataHash: string;\n readonly nonceDomainHash: string;\n readonly organizationId: string;\n readonly partCount: number;\n readonly plaintextByteLength: number;\n readonly recordKey: CryptoKey;\n}\n\nasync function createBlobEncryptionContext(\n input: PrepareBlobEncryptionInput,\n snapshot: BlobSourceSnapshot,\n): Promise<BlobEncryptionContext> {\n const chunkSize = normalizeBlobChunkSize(\n input.chunkSize ?? DEFAULT_BLOB_CHUNK_SIZE_BYTES,\n );\n const plaintextByteLength = input.source.byteLength;\n const partCount = computeBlobChunkCount(plaintextByteLength, chunkSize);\n const contentRecordId = input.blobId;\n const { contentKeyEpoch } = input.contentKeyBundle;\n const nonceSeed = new Uint8Array(input.nonceSeed ?? createAesGcmIv());\n const baseIv = await deriveBlobBaseIv({\n chunkSize,\n nonceSeed,\n plaintextSha256: snapshot.sha256,\n });\n\n const [nonceDomainHash, metadataHash] = await Promise.all([\n computeContentRecordNonceDomainHash({\n version: 1,\n organizationId: input.organizationId,\n objectKind: \"blob\",\n objectId: input.blobId,\n contentKeyEpoch,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n contentRecordId,\n }),\n blobContentMetadataHash({\n blobId: input.blobId,\n byteLength: plaintextByteLength,\n chunkCount: partCount,\n chunkSize,\n contentKeyEpoch,\n }),\n ]);\n const contentKeyMaterial = await importContentKeyMaterial(input.contentKey);\n const recordKey = await deriveBlobContentRecordKey({\n blobId: input.blobId,\n contentKeyEpoch,\n contentKeyMaterial,\n contentRecordId,\n organizationId: input.organizationId,\n usage: \"encrypt\",\n });\n return {\n baseIv,\n blobId: input.blobId,\n chunkSize,\n contentKeyEpoch,\n contentRecordId,\n headerBytes: encodeBlobEnvelopeV2Header({\n blobId: input.blobId,\n byteLength: plaintextByteLength,\n chunkCount: partCount,\n chunkSize,\n contentKeyEpoch,\n contentRecordId,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n format: BLOB_ENCRYPTED_BYTES_FORMAT,\n iv: bytesToBase64(baseIv),\n metadataHash,\n nonceDomainHash,\n version: BLOB_ENCRYPTED_BYTES_VERSION,\n }),\n metadataHash,\n nonceDomainHash,\n organizationId: input.organizationId,\n partCount,\n plaintextByteLength,\n recordKey,\n };\n}\n\nasync function encryptBlobChunk(\n context: BlobEncryptionContext,\n chunkIndex: number,\n plaintext: BlobBytes,\n): Promise<BlobBytes> {\n return new Uint8Array(\n await crypto.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: deriveBlobChunkIv(context.baseIv, chunkIndex),\n additionalData: contentRecordAdditionalDataBytes({\n blobId: context.blobId,\n chunkCount: context.partCount,\n chunkIndex,\n chunkPlaintextByteLength: plaintext.byteLength,\n chunkSize: context.chunkSize,\n contentKeyEpoch: context.contentKeyEpoch,\n contentRecordId: context.contentRecordId,\n metadataHash: context.metadataHash,\n nonceDomainHash: context.nonceDomainHash,\n organizationId: context.organizationId,\n plaintextByteLength: context.plaintextByteLength,\n }),\n },\n context.recordKey,\n plaintext,\n ),\n );\n}\n\nasync function runEncryptionHashPass(\n source: BlobByteSource,\n snapshot: BlobSourceSnapshot,\n context: BlobEncryptionContext,\n): Promise<string> {\n const objectHash = createIncrementalSha256();\n objectHash.update(context.headerBytes);\n for (let chunkIndex = 0; chunkIndex < context.partCount; chunkIndex += 1) {\n const plaintext = await readVerifiedBlobSourceChunk({\n chunkIndex,\n snapshot,\n source,\n });\n objectHash.update(await encryptBlobChunk(context, chunkIndex, plaintext));\n }\n return bytesToHex(objectHash.digest());\n}\n\nfunction createBlobEncryptionPlan(input: {\n readonly context: BlobEncryptionContext;\n readonly sha256: string;\n readonly snapshot: BlobSourceSnapshot;\n readonly source: BlobByteSource;\n}): BlobEncryptionPlan {\n const { context, sha256, snapshot, source } = input;\n const byteLength = computeBlobEncryptedByteLength({\n chunkCount: context.partCount,\n headerByteLength: context.headerBytes.byteLength,\n plaintextByteLength: context.plaintextByteLength,\n });\n return {\n byteLength,\n chunkSize: context.chunkSize,\n metadataHash: context.metadataHash,\n plaintextByteLength: context.plaintextByteLength,\n plaintextSha256: snapshot.sha256,\n sha256,\n ...createEncryptedUploadParts({\n byteLength,\n chunkSize: context.chunkSize + AES_GCM_TAG_BYTES,\n header: context.headerBytes,\n async encryptChunk(chunkIndex) {\n const plaintext = await readVerifiedBlobSourceChunk({\n chunkIndex,\n snapshot,\n source,\n });\n return encryptBlobChunk(context, chunkIndex, plaintext);\n },\n }),\n };\n}\n\nexport async function prepareBlobEncryption(\n input: PrepareBlobEncryptionInput,\n): Promise<BlobEncryptionPlan> {\n if (input.contentKey.byteLength !== AES_256_KEY_BYTES) {\n throw new Error(\"Blob content key must be 32 bytes\");\n }\n if (input.nonceSeed) {\n assertAesGcmIv(input.nonceSeed, \"Blob nonce seed is invalid\");\n }\n const chunkSize = normalizeBlobChunkSize(\n input.chunkSize ?? DEFAULT_BLOB_CHUNK_SIZE_BYTES,\n );\n const snapshot =\n input.sourceSnapshot ?? (await inspectBlobSource(input.source, chunkSize));\n const context = await createBlobEncryptionContext(input, snapshot);\n if (\n snapshot.byteLength !== context.plaintextByteLength ||\n snapshot.chunkSize !== context.chunkSize\n ) {\n throw new Error(\"Blob source snapshot does not match encryption layout\");\n }\n const sha256 = await runEncryptionHashPass(input.source, snapshot, context);\n return createBlobEncryptionPlan({\n context,\n sha256,\n snapshot,\n source: input.source,\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"encryptedUploadParts.js","sourceRoot":"","sources":["encryptedUploadParts.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,MAAM,UAAU,0BAA0B,CAAC,KAK1C;IACC,6EAA6E;IAC7E,gFAAgF;IAChF,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAC;IACzD,SAAS,iBAAiB,CAAC,KAAa;QACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,GAAG,QAAQ,CAAC,CAAC;IACjE,CAAC;IACD,OAAO;QACL,SAAS;QACT,iBAAiB;QACjB,KAAK,CAAC,WAAW,CAAC,KAAa;YAC7B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,MAAM,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;YAC/B,MAAM,GAAG,GAAG,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;YACtC,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,MAAM,CAAC,GAAG,CACR,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CACrE,CAAC;YACJ,CAAC;YACD,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxD,OAAO,QAAQ,GAAG,GAAG,EAAE,CAAC;gBACtB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAC3B,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,SAAS,CACvD,CAAC;gBACF,MAAM,UAAU,GACd,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC;gBACzD,sEAAsE;gBACtE,yEAAyE;gBACzE,uEAAuE;gBACvE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;gBACnD,MAAM,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;gBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAC;gBACnE,IAAI,MAAM,IAAI,CAAC;oBACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBACrE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;gBACtE,QAAQ,IAAI,MAAM,CAAC;YACrB,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { BlobBytes } from \"../../../blobContracts\";\n\n/** Repartition the envelope without changing its encryption or buffering the file. */\nexport function createEncryptedUploadParts(input: {\n readonly byteLength: number;\n readonly chunkSize: number;\n readonly header: BlobBytes;\n readonly encryptChunk: (index: number) => Promise<BlobBytes>;\n}) {\n // Including the header in the fixed transport size keeps even a maximum-size\n // envelope within 10,000 parts. R2 requires equal sizes for all nonfinal parts.\n const partSize = input.chunkSize + input.header.byteLength;\n const partCount = Math.ceil(input.byteLength / partSize);\n function getPartByteLength(index: number): number {\n if (!Number.isInteger(index) || index < 0 || index >= partCount) {\n throw new Error(\"Blob encryption part index is out of range\");\n }\n return Math.min(partSize, input.byteLength - index * partSize);\n }\n return {\n partCount,\n getPartByteLength,\n async encryptPart(index: number): Promise<BlobBytes> {\n const output = new Uint8Array(getPartByteLength(index));\n const start = index * partSize;\n const end = start + output.byteLength;\n if (start < input.header.byteLength) {\n output.set(\n input.header.subarray(start, Math.min(end, input.header.byteLength)),\n );\n }\n let position = Math.max(start, input.header.byteLength);\n while (position < end) {\n const chunkIndex = Math.floor(\n (position - input.header.byteLength) / input.chunkSize,\n );\n const chunkStart =\n input.header.byteLength + chunkIndex * input.chunkSize;\n // Adjacent transport parts can re-read and re-encrypt a shared chunk.\n // Independent calls keep memory bounded during concurrent upload/resume;\n // the tradeoff is up to two encryptions per chunk in this upload pass.\n const chunk = await input.encryptChunk(chunkIndex);\n const offset = position - chunkStart;\n const length = Math.min(chunk.byteLength - offset, end - position);\n if (length <= 0)\n throw new Error(\"Encrypted blob chunk is shorter than its layout\");\n output.set(chunk.subarray(offset, offset + length), position - start);\n position += length;\n }\n return output;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"encryptedUploadParts.js","sourceRoot":"","sources":["encryptedUploadParts.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,MAAM,UAAU,0BAA0B,CAAC,KAK1C;IACC,6EAA6E;IAC7E,gFAAgF;IAChF,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAC;IACzD,SAAS,iBAAiB,CAAC,KAAa;QACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,GAAG,QAAQ,CAAC,CAAC;IACjE,CAAC;IACD,OAAO;QACL,SAAS;QACT,iBAAiB;QACjB,KAAK,CAAC,WAAW,CAAC,KAAa;YAC7B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,MAAM,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;YAC/B,MAAM,GAAG,GAAG,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;YACtC,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,MAAM,CAAC,GAAG,CACR,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CACrE,CAAC;YACJ,CAAC;YACD,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxD,OAAO,QAAQ,GAAG,GAAG,EAAE,CAAC;gBACtB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAC3B,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,SAAS,CACvD,CAAC;gBACF,MAAM,UAAU,GACd,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC;gBACzD,sEAAsE;gBACtE,yEAAyE;gBACzE,uEAAuE;gBACvE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;gBACnD,MAAM,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;gBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAC;gBACnE,IAAI,MAAM,IAAI,CAAC;oBACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBACrE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;gBACtE,QAAQ,IAAI,MAAM,CAAC;YACrB,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { BlobBytes } from \"../../../blobs/blobContracts\";\n\n/** Repartition the envelope without changing its encryption or buffering the file. */\nexport function createEncryptedUploadParts(input: {\n readonly byteLength: number;\n readonly chunkSize: number;\n readonly header: BlobBytes;\n readonly encryptChunk: (index: number) => Promise<BlobBytes>;\n}) {\n // Including the header in the fixed transport size keeps even a maximum-size\n // envelope within 10,000 parts. R2 requires equal sizes for all nonfinal parts.\n const partSize = input.chunkSize + input.header.byteLength;\n const partCount = Math.ceil(input.byteLength / partSize);\n function getPartByteLength(index: number): number {\n if (!Number.isInteger(index) || index < 0 || index >= partCount) {\n throw new Error(\"Blob encryption part index is out of range\");\n }\n return Math.min(partSize, input.byteLength - index * partSize);\n }\n return {\n partCount,\n getPartByteLength,\n async encryptPart(index: number): Promise<BlobBytes> {\n const output = new Uint8Array(getPartByteLength(index));\n const start = index * partSize;\n const end = start + output.byteLength;\n if (start < input.header.byteLength) {\n output.set(\n input.header.subarray(start, Math.min(end, input.header.byteLength)),\n );\n }\n let position = Math.max(start, input.header.byteLength);\n while (position < end) {\n const chunkIndex = Math.floor(\n (position - input.header.byteLength) / input.chunkSize,\n );\n const chunkStart =\n input.header.byteLength + chunkIndex * input.chunkSize;\n // Adjacent transport parts can re-read and re-encrypt a shared chunk.\n // Independent calls keep memory bounded during concurrent upload/resume;\n // the tradeoff is up to two encryptions per chunk in this upload pass.\n const chunk = await input.encryptChunk(chunkIndex);\n const offset = position - chunkStart;\n const length = Math.min(chunk.byteLength - offset, end - position);\n if (length <= 0)\n throw new Error(\"Encrypted blob chunk is shorter than its layout\");\n output.set(chunk.subarray(offset, offset + length), position - start);\n position += length;\n }\n return output;\n },\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { CONTENT_RECORD_ENCRYPTION_SUITE, computeAccessEventBodyHash, computeContentRecordNonceDomainHash, computeWriteHeaderHash, signAccessEvent, signWriteHeader, } from "../../../../internal/crypto/index.js";
2
- import { readCanonicalJson } from "../../../keyingCanonicalJson.js";
2
+ import { readCanonicalJson } from "../../../keying/canonicalJson.js";
3
3
  import { uniqueSortedStrings } from "../../shared/readers.js";
4
4
  async function signBlobAttachmentBodyEvent(body, input) {
5
5
  const bodyLabel = body.eventType === "attachment.bind"
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["events.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AttachmentBindAccessEventBody,\n type AttachmentDetachAccessEventBody,\n CONTENT_RECORD_ENCRYPTION_SUITE,\n computeAccessEventBodyHash,\n computeContentRecordNonceDomainHash,\n computeWriteHeaderHash,\n signAccessEvent,\n signWriteHeader,\n type UnsignedAccessEvent,\n type WriteHeader,\n} from \"@tearleads/crypto\";\nimport type { ContainerManifestRef } from \"@tearleads/validators/request\";\nimport { readCanonicalJson } from \"../../../keyingCanonicalJson\";\nimport { uniqueSortedStrings } from \"../../shared/readers\";\nimport type { DocumentCreateAuthor } from \"../../shared/types\";\nimport type { BlobEncryptionPlan, DocumentManifestIdentity } from \"./types\";\n\nasync function signBlobAttachmentBodyEvent<\n Body extends AttachmentBindAccessEventBody | AttachmentDetachAccessEventBody,\n>(\n body: Body,\n input: {\n author: DocumentCreateAuthor;\n blobId: string;\n eventId: string;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n },\n): Promise<{ body: Body; event: AccessEvent }> {\n const bodyLabel =\n body.eventType === \"attachment.bind\"\n ? \"Blob attachment bind body\"\n : \"Blob attachment detach body\";\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId,\n eventType: body.eventType,\n objectKind: \"blob\",\n objectId: input.blobId,\n organizationId: input.manifestIdentity.organizationId,\n previousManifestHash: null,\n dependencyManifestHashes: uniqueSortedStrings([\n input.manifestIdentity.manifestHash,\n ...input.authorizingContainerPathRefs.flatMap((path) =>\n path.map((ref) => ref.manifestHash),\n ),\n ]),\n bodyHash: await computeAccessEventBodyHash(\n readCanonicalJson(body, bodyLabel),\n ),\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n };\n\n return {\n body,\n event: await signAccessEvent(unsignedEvent, input.author.signerPrivateKey),\n };\n}\n\nexport async function signBlobAttachmentEvent(input: {\n author: DocumentCreateAuthor;\n bindingId: string;\n blobId: string;\n documentId: string;\n eventId: string;\n expectedBindingId: string | null;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n slotId: string;\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n}): Promise<{ body: AttachmentBindAccessEventBody; event: AccessEvent }> {\n return signBlobAttachmentBodyEvent(\n {\n eventType: \"attachment.bind\",\n bindingId: input.bindingId,\n blobId: input.blobId,\n documentId: input.documentId,\n slotId: input.slotId,\n expectedBindingId: input.expectedBindingId,\n documentManifestHash: input.manifestIdentity.manifestHash,\n },\n input,\n );\n}\n\nexport async function signBlobAttachmentDetachEvent(input: {\n author: DocumentCreateAuthor;\n bindingId: string;\n blobId: string;\n documentId: string;\n eventId: string;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n slotId: string;\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n}): Promise<{ body: AttachmentDetachAccessEventBody; event: AccessEvent }> {\n return signBlobAttachmentBodyEvent(\n {\n eventType: \"attachment.detach\",\n bindingId: input.bindingId,\n blobId: input.blobId,\n documentId: input.documentId,\n slotId: input.slotId,\n documentManifestHash: input.manifestIdentity.manifestHash,\n },\n input,\n );\n}\n\nexport async function signBlobAttachmentWriteHeader(input: {\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n author: DocumentCreateAuthor;\n blobAccessManifestHash: string;\n blobId: string;\n contentKeyEpoch: number;\n encrypted: BlobEncryptionPlan;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n targetHash: string;\n}): Promise<{ writeHeader: WriteHeader; writeHeaderHash: string }> {\n const writeHeader = await signWriteHeader(\n {\n version: 1,\n dependencyManifestHashes: uniqueSortedStrings(\n input.authorizingContainerPathRefs.flatMap((path) =>\n path.map((ref) => ref.manifestHash),\n ),\n ),\n organizationId: input.manifestIdentity.organizationId,\n objectKind: \"blob\",\n objectId: input.blobId,\n accessManifestHash: input.blobAccessManifestHash,\n contentKeyEpoch: input.contentKeyEpoch,\n targetHash: input.targetHash,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n contentRecordId: input.blobId,\n nonceDomainHash: await computeContentRecordNonceDomainHash({\n version: 1,\n organizationId: input.manifestIdentity.organizationId,\n objectKind: \"blob\",\n objectId: input.blobId,\n contentKeyEpoch: input.contentKeyEpoch,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n contentRecordId: input.blobId,\n }),\n metadataHash: input.encrypted.metadataHash,\n ciphertextHash: input.encrypted.sha256,\n writerUserId: input.author.signerUserId,\n writerDeviceId: input.author.signerDeviceId,\n writerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n },\n input.author.signerPrivateKey,\n );\n\n return {\n writeHeader,\n writeHeaderHash: await computeWriteHeaderHash(writeHeader),\n };\n}\n"]}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["events.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AttachmentBindAccessEventBody,\n type AttachmentDetachAccessEventBody,\n CONTENT_RECORD_ENCRYPTION_SUITE,\n computeAccessEventBodyHash,\n computeContentRecordNonceDomainHash,\n computeWriteHeaderHash,\n signAccessEvent,\n signWriteHeader,\n type UnsignedAccessEvent,\n type WriteHeader,\n} from \"@tearleads/crypto\";\nimport type { ContainerManifestRef } from \"@tearleads/validators/request\";\nimport { readCanonicalJson } from \"../../../keying/canonicalJson\";\nimport { uniqueSortedStrings } from \"../../shared/readers\";\nimport type { DocumentCreateAuthor } from \"../../shared/types\";\nimport type { BlobEncryptionPlan, DocumentManifestIdentity } from \"./types\";\n\nasync function signBlobAttachmentBodyEvent<\n Body extends AttachmentBindAccessEventBody | AttachmentDetachAccessEventBody,\n>(\n body: Body,\n input: {\n author: DocumentCreateAuthor;\n blobId: string;\n eventId: string;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n },\n): Promise<{ body: Body; event: AccessEvent }> {\n const bodyLabel =\n body.eventType === \"attachment.bind\"\n ? \"Blob attachment bind body\"\n : \"Blob attachment detach body\";\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId,\n eventType: body.eventType,\n objectKind: \"blob\",\n objectId: input.blobId,\n organizationId: input.manifestIdentity.organizationId,\n previousManifestHash: null,\n dependencyManifestHashes: uniqueSortedStrings([\n input.manifestIdentity.manifestHash,\n ...input.authorizingContainerPathRefs.flatMap((path) =>\n path.map((ref) => ref.manifestHash),\n ),\n ]),\n bodyHash: await computeAccessEventBodyHash(\n readCanonicalJson(body, bodyLabel),\n ),\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n };\n\n return {\n body,\n event: await signAccessEvent(unsignedEvent, input.author.signerPrivateKey),\n };\n}\n\nexport async function signBlobAttachmentEvent(input: {\n author: DocumentCreateAuthor;\n bindingId: string;\n blobId: string;\n documentId: string;\n eventId: string;\n expectedBindingId: string | null;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n slotId: string;\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n}): Promise<{ body: AttachmentBindAccessEventBody; event: AccessEvent }> {\n return signBlobAttachmentBodyEvent(\n {\n eventType: \"attachment.bind\",\n bindingId: input.bindingId,\n blobId: input.blobId,\n documentId: input.documentId,\n slotId: input.slotId,\n expectedBindingId: input.expectedBindingId,\n documentManifestHash: input.manifestIdentity.manifestHash,\n },\n input,\n );\n}\n\nexport async function signBlobAttachmentDetachEvent(input: {\n author: DocumentCreateAuthor;\n bindingId: string;\n blobId: string;\n documentId: string;\n eventId: string;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n slotId: string;\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n}): Promise<{ body: AttachmentDetachAccessEventBody; event: AccessEvent }> {\n return signBlobAttachmentBodyEvent(\n {\n eventType: \"attachment.detach\",\n bindingId: input.bindingId,\n blobId: input.blobId,\n documentId: input.documentId,\n slotId: input.slotId,\n documentManifestHash: input.manifestIdentity.manifestHash,\n },\n input,\n );\n}\n\nexport async function signBlobAttachmentWriteHeader(input: {\n authorizingContainerPathRefs: readonly (readonly ContainerManifestRef[])[];\n author: DocumentCreateAuthor;\n blobAccessManifestHash: string;\n blobId: string;\n contentKeyEpoch: number;\n encrypted: BlobEncryptionPlan;\n manifestIdentity: DocumentManifestIdentity;\n signedAt: string;\n targetHash: string;\n}): Promise<{ writeHeader: WriteHeader; writeHeaderHash: string }> {\n const writeHeader = await signWriteHeader(\n {\n version: 1,\n dependencyManifestHashes: uniqueSortedStrings(\n input.authorizingContainerPathRefs.flatMap((path) =>\n path.map((ref) => ref.manifestHash),\n ),\n ),\n organizationId: input.manifestIdentity.organizationId,\n objectKind: \"blob\",\n objectId: input.blobId,\n accessManifestHash: input.blobAccessManifestHash,\n contentKeyEpoch: input.contentKeyEpoch,\n targetHash: input.targetHash,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n contentRecordId: input.blobId,\n nonceDomainHash: await computeContentRecordNonceDomainHash({\n version: 1,\n organizationId: input.manifestIdentity.organizationId,\n objectKind: \"blob\",\n objectId: input.blobId,\n contentKeyEpoch: input.contentKeyEpoch,\n encryptionSuite: CONTENT_RECORD_ENCRYPTION_SUITE,\n contentRecordId: input.blobId,\n }),\n metadataHash: input.encrypted.metadataHash,\n ciphertextHash: input.encrypted.sha256,\n writerUserId: input.author.signerUserId,\n writerDeviceId: input.author.signerDeviceId,\n writerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n },\n input.author.signerPrivateKey,\n );\n\n return {\n writeHeader,\n writeHeaderHash: await computeWriteHeaderHash(writeHeader),\n };\n}\n"]}
@@ -2,8 +2,8 @@ import type { RequestFailureKind, RequestResultOptions, UploadMultipartBlobPartB
2
2
  import type { BlobContentKeyTarget, BlobEnvelopeHeaderRecord, BlobEnvelopeRecord, WriteHeader } from "../../../../internal/crypto/index.js";
3
3
  import type { BlobAttachmentBindRequest, BlobAttachmentDetachRequest, BlobContentKeyBundleRequest, InitiateMultipartBlobStageRequest } from "../../../../internal/validators/request/index.js";
4
4
  import type { BlobAttachmentBindResponse, BlobAttachmentDetachResponse, BlobAttachmentSummary, DocumentWriterProjectionResponse, InitiateMultipartBlobStageResponse, MultipartBlobStageStatusResponse, UploadMultipartBlobPartResponse } from "../../../../internal/validators/response/index.js";
5
- import type { BlobByteSourceInput, BlobBytes } from "../../../blobContracts.js";
6
- import type { ProjectionUserKeyResolver, ReferencedPrincipalPolicyWarmer } from "../../../keyingProjectionVerification.js";
5
+ import type { BlobByteSourceInput, BlobBytes } from "../../../blobs/blobContracts.js";
6
+ import type { ProjectionUserKeyResolver, ReferencedPrincipalPolicyWarmer } from "../../../keyingProjectionVerification/index.js";
7
7
  import type { ExecSql } from "../../../sqlite/sqlSchema.js";
8
8
  import type { DocumentCreateAuthor } from "../../shared/types.js";
9
9
  export declare const BLOB_CONTENT_RECORD_KEY_INFO_DOMAIN = "tearleads.blob.content-record-key-info";
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAkCA,MAAM,CAAC,MAAM,mCAAmC,GAC9C,wCAAwC,CAAC;AAC3C,MAAM,CAAC,MAAM,8BAA8B,GACzC,mCAAmC,CAAC;AACtC,MAAM,CAAC,MAAM,gCAAgC,GAC3C,qCAAqC,CAAC;AACxC,MAAM,CAAC,MAAM,6BAA6B,GACxC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;AACtE,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC","sourcesContent":["import type {\n RequestFailureKind,\n RequestResultOptions,\n UploadMultipartBlobPartBytesRequest,\n} from \"@tearleads/api-client\";\nimport type {\n BlobContentKeyTarget,\n BlobEnvelopeHeaderRecord,\n BlobEnvelopeRecord,\n WriteHeader,\n} from \"@tearleads/crypto\";\nimport type {\n BlobAttachmentBindRequest,\n BlobAttachmentDetachRequest,\n BlobContentKeyBundleRequest,\n InitiateMultipartBlobStageRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n BlobAttachmentBindResponse,\n BlobAttachmentDetachResponse,\n BlobAttachmentSummary,\n DocumentWriterProjectionResponse,\n InitiateMultipartBlobStageResponse,\n MultipartBlobStageStatusResponse,\n UploadMultipartBlobPartResponse,\n} from \"@tearleads/validators/response\";\nimport type { BlobByteSourceInput, BlobBytes } from \"../../../blobContracts\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../keyingProjectionVerification\";\nimport type { ExecSql } from \"../../../sqlite/sqlSchema\";\nimport type { DocumentCreateAuthor } from \"../../shared/types\";\n\nexport const BLOB_CONTENT_RECORD_KEY_INFO_DOMAIN =\n \"tearleads.blob.content-record-key-info\";\nexport const BLOB_CONTENT_RECORD_AAD_DOMAIN =\n \"tearleads.blob.content-record-aad\";\nexport const BLOB_CONTENT_RECORD_NONCE_DOMAIN =\n \"tearleads.blob.content-record-nonce\";\nexport const BLOB_CONTENT_RECORD_HKDF_SALT: Uint8Array<ArrayBuffer> =\n new TextEncoder().encode(\"tearleads.blob.content-record-hkdf-salt\");\nexport const TEXT_ENCODER = new TextEncoder();\n\nexport interface BlobAttachmentRequestOptions {\n readonly expectedPaymentRequiredOrganizationId?: string | undefined;\n}\n\nexport interface BlobAttachmentApi {\n bindBlobAttachment(\n blobId: string,\n input: BlobAttachmentBindRequest,\n options?: BlobAttachmentRequestOptions,\n ): Promise<BlobAttachmentBindResponse | null>;\n clearWriterProjectionCaches?(): void;\n evictDocumentWriterProjection?(documentId: string): void;\n getRequestFailure?(input: {\n method: \"DELETE\" | \"GET\" | \"POST\" | \"PUT\";\n path: string;\n }): {\n readonly code?: string | undefined;\n readonly kind: RequestFailureKind;\n readonly message: string;\n readonly status: number | null;\n } | null;\n getDocumentWriterProjection(\n documentId: string,\n ): Promise<DocumentWriterProjectionResponse | null>;\n getMultipartBlobStage(\n stageId: string,\n ): Promise<MultipartBlobStageStatusResponse | null>;\n initiateMultipartBlobStage(\n input: InitiateMultipartBlobStageRequest,\n ): Promise<InitiateMultipartBlobStageResponse | null>;\n uploadMultipartBlobPartBytes(\n stageId: string,\n partNumber: number,\n input: UploadMultipartBlobPartBytesRequest,\n options?: RequestResultOptions,\n ): Promise<UploadMultipartBlobPartResponse | null>;\n}\n\nexport interface BlobAttachmentDetachApi {\n detachBlobAttachment(\n blobId: string,\n bindingId: string,\n input: BlobAttachmentDetachRequest,\n options?: BlobAttachmentRequestOptions,\n ): Promise<BlobAttachmentDetachResponse | null>;\n getDocumentWriterProjection(\n documentId: string,\n ): Promise<DocumentWriterProjectionResponse | null>;\n}\n\nexport type { BlobContentKeyTarget };\n\n/**\n * Aliases of the crypto parser's own types. The parser is shared with the API,\n * so restating these shapes here would let the two drift apart silently.\n */\nexport type BlobEncryptedBytesRecord = BlobEnvelopeRecord;\n\n/**\n * The envelope as the header establishes it. Streaming readers hold this\n * before any ciphertext is read, so it has no `chunks`: an empty array there\n * would read as an empty object rather than an unread one.\n */\nexport type BlobEncryptedBytesHeader = BlobEnvelopeHeaderRecord;\n\nexport type BlobEncryptedChunk = BlobEnvelopeRecord[\"chunks\"][number];\n\nexport interface BlobSourceSnapshot {\n readonly byteLength: number;\n readonly chunkSha256: readonly string[];\n readonly chunkSize: number;\n readonly sha256: string;\n}\n\nexport interface BlobEncryptionPlan {\n readonly byteLength: number;\n readonly chunkSize: number;\n readonly metadataHash: string;\n readonly partCount: number;\n readonly plaintextByteLength: number;\n readonly plaintextSha256: string;\n readonly sha256: string;\n encryptPart(index: number): Promise<BlobBytes>;\n getPartByteLength(index: number): number;\n}\n\nexport interface DocumentManifestIdentity {\n documentId: string;\n manifestHash: string;\n organizationId: string;\n}\n\nexport interface BlobAttachmentMaterial {\n blobAccessManifestHash: string;\n contentKeyBundle: BlobContentKeyBundleRequest;\n encrypted: BlobEncryptionPlan;\n manifestIdentity: DocumentManifestIdentity;\n targetHash: string;\n targets: BlobContentKeyTarget[];\n writerProjection: DocumentWriterProjectionResponse;\n}\n\n/**\n * Progress for an in-flight multipart blob upload.\n */\nexport interface MultipartUploadProgress {\n readonly bytesTotal: number;\n readonly bytesUploaded: number;\n readonly partsCompleted: number;\n readonly partsTotal: number;\n}\n\nexport type MultipartUploadProgressListener = (\n progress: MultipartUploadProgress,\n) => void;\n\n/**\n * Fires once a multipart stage has been opened (or resumed), with its id and\n * plaintext chunk size. Callers persist both so a later attempt can reproduce\n * the same encrypted parts and resume instead of orphaning the partial upload.\n */\nexport type MultipartStageResolvedListener = (input: {\n readonly partSize: number;\n readonly stageId: string;\n}) => void | Promise<void>;\n\nexport interface UploadDocumentAttachmentInput {\n apiClient: BlobAttachmentApi;\n author: DocumentCreateAuthor;\n blobId?: string | undefined;\n bindingId?: string | undefined;\n bytes: BlobByteSourceInput;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId: string;\n eventId?: string | undefined;\n execSql: ExecSql;\n expectedBindingId: string | null;\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n // A persisted nonce seed. The plaintext digest derives the envelope IV from\n // it, then each chunk derives a unique IV. Same-source retries reproduce the\n // encrypted parts; changed bytes cannot reuse their AES-GCM nonces.\n nonceSeed?: Uint8Array | undefined;\n multipart?: MultipartBlobUploadOptions | undefined;\n onMultipartProgress?: MultipartUploadProgressListener | undefined;\n onStageResolved?: MultipartStageResolvedListener | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n slotId: string;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n writerProjection?: DocumentWriterProjectionResponse | undefined;\n}\n\nexport interface MultipartBlobUploadOptions {\n /** Exactly 5 MiB per plaintext encryption chunk; transport parts include envelope overhead. */\n readonly partSize: number;\n // The id of a previously opened stage to resume. When set, the upload refetches\n // that stage and skips parts the server already has instead of opening a new\n // one; if the stage is gone (expired), it falls back to a fresh stage.\n readonly resumeStageId?: string | undefined;\n readonly uploadConcurrency?: number | undefined;\n}\n\nexport interface UploadDocumentAttachmentResult {\n blobId: string;\n bindingId: string;\n request: BlobAttachmentBindRequest;\n response: BlobAttachmentBindResponse;\n sha256: string;\n byteLength: number;\n writeHeader: WriteHeader;\n writeHeaderHash: string;\n writerProjection: DocumentWriterProjectionResponse;\n}\n\nexport interface DetachDocumentAttachmentInput {\n apiClient: BlobAttachmentDetachApi;\n author: DocumentCreateAuthor;\n bindingId: string;\n blobId: string;\n documentId: string;\n eventId?: string | undefined;\n execSql: ExecSql;\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n slotId: string;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n writerProjection?: DocumentWriterProjectionResponse | undefined;\n}\n\nexport interface DetachDocumentAttachmentResult {\n request: BlobAttachmentDetachRequest;\n response: BlobAttachmentDetachResponse;\n writerProjection: DocumentWriterProjectionResponse;\n}\n\nexport interface DecryptDocumentAttachmentBlobInput {\n binding: BlobAttachmentSummary;\n encryptedBytes: BlobBytes;\n expectedDocumentId: string;\n expectedSlotId: string;\n execSql: ExecSql;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n targetSecretKey: Uint8Array;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n writerProjection: DocumentWriterProjectionResponse;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAqCA,MAAM,CAAC,MAAM,mCAAmC,GAC9C,wCAAwC,CAAC;AAC3C,MAAM,CAAC,MAAM,8BAA8B,GACzC,mCAAmC,CAAC;AACtC,MAAM,CAAC,MAAM,gCAAgC,GAC3C,qCAAqC,CAAC;AACxC,MAAM,CAAC,MAAM,6BAA6B,GACxC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;AACtE,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC","sourcesContent":["import type {\n RequestFailureKind,\n RequestResultOptions,\n UploadMultipartBlobPartBytesRequest,\n} from \"@tearleads/api-client\";\nimport type {\n BlobContentKeyTarget,\n BlobEnvelopeHeaderRecord,\n BlobEnvelopeRecord,\n WriteHeader,\n} from \"@tearleads/crypto\";\nimport type {\n BlobAttachmentBindRequest,\n BlobAttachmentDetachRequest,\n BlobContentKeyBundleRequest,\n InitiateMultipartBlobStageRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n BlobAttachmentBindResponse,\n BlobAttachmentDetachResponse,\n BlobAttachmentSummary,\n DocumentWriterProjectionResponse,\n InitiateMultipartBlobStageResponse,\n MultipartBlobStageStatusResponse,\n UploadMultipartBlobPartResponse,\n} from \"@tearleads/validators/response\";\nimport type {\n BlobByteSourceInput,\n BlobBytes,\n} from \"../../../blobs/blobContracts\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../keyingProjectionVerification\";\nimport type { ExecSql } from \"../../../sqlite/sqlSchema\";\nimport type { DocumentCreateAuthor } from \"../../shared/types\";\n\nexport const BLOB_CONTENT_RECORD_KEY_INFO_DOMAIN =\n \"tearleads.blob.content-record-key-info\";\nexport const BLOB_CONTENT_RECORD_AAD_DOMAIN =\n \"tearleads.blob.content-record-aad\";\nexport const BLOB_CONTENT_RECORD_NONCE_DOMAIN =\n \"tearleads.blob.content-record-nonce\";\nexport const BLOB_CONTENT_RECORD_HKDF_SALT: Uint8Array<ArrayBuffer> =\n new TextEncoder().encode(\"tearleads.blob.content-record-hkdf-salt\");\nexport const TEXT_ENCODER = new TextEncoder();\n\nexport interface BlobAttachmentRequestOptions {\n readonly expectedPaymentRequiredOrganizationId?: string | undefined;\n}\n\nexport interface BlobAttachmentApi {\n bindBlobAttachment(\n blobId: string,\n input: BlobAttachmentBindRequest,\n options?: BlobAttachmentRequestOptions,\n ): Promise<BlobAttachmentBindResponse | null>;\n clearWriterProjectionCaches?(): void;\n evictDocumentWriterProjection?(documentId: string): void;\n getRequestFailure?(input: {\n method: \"DELETE\" | \"GET\" | \"POST\" | \"PUT\";\n path: string;\n }): {\n readonly code?: string | undefined;\n readonly kind: RequestFailureKind;\n readonly message: string;\n readonly status: number | null;\n } | null;\n getDocumentWriterProjection(\n documentId: string,\n ): Promise<DocumentWriterProjectionResponse | null>;\n getMultipartBlobStage(\n stageId: string,\n ): Promise<MultipartBlobStageStatusResponse | null>;\n initiateMultipartBlobStage(\n input: InitiateMultipartBlobStageRequest,\n ): Promise<InitiateMultipartBlobStageResponse | null>;\n uploadMultipartBlobPartBytes(\n stageId: string,\n partNumber: number,\n input: UploadMultipartBlobPartBytesRequest,\n options?: RequestResultOptions,\n ): Promise<UploadMultipartBlobPartResponse | null>;\n}\n\nexport interface BlobAttachmentDetachApi {\n detachBlobAttachment(\n blobId: string,\n bindingId: string,\n input: BlobAttachmentDetachRequest,\n options?: BlobAttachmentRequestOptions,\n ): Promise<BlobAttachmentDetachResponse | null>;\n getDocumentWriterProjection(\n documentId: string,\n ): Promise<DocumentWriterProjectionResponse | null>;\n}\n\nexport type { BlobContentKeyTarget };\n\n/**\n * Aliases of the crypto parser's own types. The parser is shared with the API,\n * so restating these shapes here would let the two drift apart silently.\n */\nexport type BlobEncryptedBytesRecord = BlobEnvelopeRecord;\n\n/**\n * The envelope as the header establishes it. Streaming readers hold this\n * before any ciphertext is read, so it has no `chunks`: an empty array there\n * would read as an empty object rather than an unread one.\n */\nexport type BlobEncryptedBytesHeader = BlobEnvelopeHeaderRecord;\n\nexport type BlobEncryptedChunk = BlobEnvelopeRecord[\"chunks\"][number];\n\nexport interface BlobSourceSnapshot {\n readonly byteLength: number;\n readonly chunkSha256: readonly string[];\n readonly chunkSize: number;\n readonly sha256: string;\n}\n\nexport interface BlobEncryptionPlan {\n readonly byteLength: number;\n readonly chunkSize: number;\n readonly metadataHash: string;\n readonly partCount: number;\n readonly plaintextByteLength: number;\n readonly plaintextSha256: string;\n readonly sha256: string;\n encryptPart(index: number): Promise<BlobBytes>;\n getPartByteLength(index: number): number;\n}\n\nexport interface DocumentManifestIdentity {\n documentId: string;\n manifestHash: string;\n organizationId: string;\n}\n\nexport interface BlobAttachmentMaterial {\n blobAccessManifestHash: string;\n contentKeyBundle: BlobContentKeyBundleRequest;\n encrypted: BlobEncryptionPlan;\n manifestIdentity: DocumentManifestIdentity;\n targetHash: string;\n targets: BlobContentKeyTarget[];\n writerProjection: DocumentWriterProjectionResponse;\n}\n\n/**\n * Progress for an in-flight multipart blob upload.\n */\nexport interface MultipartUploadProgress {\n readonly bytesTotal: number;\n readonly bytesUploaded: number;\n readonly partsCompleted: number;\n readonly partsTotal: number;\n}\n\nexport type MultipartUploadProgressListener = (\n progress: MultipartUploadProgress,\n) => void;\n\n/**\n * Fires once a multipart stage has been opened (or resumed), with its id and\n * plaintext chunk size. Callers persist both so a later attempt can reproduce\n * the same encrypted parts and resume instead of orphaning the partial upload.\n */\nexport type MultipartStageResolvedListener = (input: {\n readonly partSize: number;\n readonly stageId: string;\n}) => void | Promise<void>;\n\nexport interface UploadDocumentAttachmentInput {\n apiClient: BlobAttachmentApi;\n author: DocumentCreateAuthor;\n blobId?: string | undefined;\n bindingId?: string | undefined;\n bytes: BlobByteSourceInput;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId: string;\n eventId?: string | undefined;\n execSql: ExecSql;\n expectedBindingId: string | null;\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n // A persisted nonce seed. The plaintext digest derives the envelope IV from\n // it, then each chunk derives a unique IV. Same-source retries reproduce the\n // encrypted parts; changed bytes cannot reuse their AES-GCM nonces.\n nonceSeed?: Uint8Array | undefined;\n multipart?: MultipartBlobUploadOptions | undefined;\n onMultipartProgress?: MultipartUploadProgressListener | undefined;\n onStageResolved?: MultipartStageResolvedListener | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n slotId: string;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n writerProjection?: DocumentWriterProjectionResponse | undefined;\n}\n\nexport interface MultipartBlobUploadOptions {\n /** Exactly 5 MiB per plaintext encryption chunk; transport parts include envelope overhead. */\n readonly partSize: number;\n // The id of a previously opened stage to resume. When set, the upload refetches\n // that stage and skips parts the server already has instead of opening a new\n // one; if the stage is gone (expired), it falls back to a fresh stage.\n readonly resumeStageId?: string | undefined;\n readonly uploadConcurrency?: number | undefined;\n}\n\nexport interface UploadDocumentAttachmentResult {\n blobId: string;\n bindingId: string;\n request: BlobAttachmentBindRequest;\n response: BlobAttachmentBindResponse;\n sha256: string;\n byteLength: number;\n writeHeader: WriteHeader;\n writeHeaderHash: string;\n writerProjection: DocumentWriterProjectionResponse;\n}\n\nexport interface DetachDocumentAttachmentInput {\n apiClient: BlobAttachmentDetachApi;\n author: DocumentCreateAuthor;\n bindingId: string;\n blobId: string;\n documentId: string;\n eventId?: string | undefined;\n execSql: ExecSql;\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n slotId: string;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n writerProjection?: DocumentWriterProjectionResponse | undefined;\n}\n\nexport interface DetachDocumentAttachmentResult {\n request: BlobAttachmentDetachRequest;\n response: BlobAttachmentDetachResponse;\n writerProjection: DocumentWriterProjectionResponse;\n}\n\nexport interface DecryptDocumentAttachmentBlobInput {\n binding: BlobAttachmentSummary;\n encryptedBytes: BlobBytes;\n expectedDocumentId: string;\n expectedSlotId: string;\n execSql: ExecSql;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n targetSecretKey: Uint8Array;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n writerProjection: DocumentWriterProjectionResponse;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { computeContainerKekKeyringHash, computeContainerKekMaterialId, isContainerKekMaterialId, KeyingVerificationError, normalizeContainerAccessEventBody, normalizeContainerKekKeyring, openContainerKekKeyring, } from "../../../internal/crypto/index.js";
2
- import { readCanonicalJson, readCanonicalRecord, } from "../../keyingCanonicalJson.js";
2
+ import { readCanonicalJson, readCanonicalRecord, } from "../../keying/canonicalJson.js";
3
3
  import { readContainerKeyEpoch } from "../../keyingProjectionVerification/readers.js";
4
4
  import { verifyContainerKekEntries } from "./containerKekEntryVerification.js";
5
5
  import { readManifestContainerId } from "./readers.js";
@@ -1 +1 @@
1
- {"version":3,"file":"containerKekPathHistory.js","sourceRoot":"","sources":["containerKekPathHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeContainerKekKeyringHash,\n computeContainerKekMaterialId,\n isContainerKekMaterialId,\n KeyingVerificationError,\n normalizeContainerAccessEventBody,\n normalizeContainerKekKeyring,\n openContainerKekKeyring,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../keyingCanonicalJson\";\nimport { readContainerKeyEpoch } from \"../../keyingProjectionVerification/readers\";\nimport { verifyContainerKekEntries } from \"./containerKekEntryVerification\";\nimport { readManifestContainerId } from \"./readers\";\nimport type { UnwrappedContainerKek } from \"./types\";\n\ntype ProjectionKek = ContainerWriterProjectionResponse[\"containerKeks\"][number];\ntype VerifiedManifests = ReadonlyMap<string, VerifiedContainerAccessManifest>;\n\n/** The projection proves a predecessor existed, but no retained keyring can recover it. */\nexport class ContainerKekHistoryUnavailableError extends Error {\n constructor(label: string) {\n super(`${label} keyring is missing`);\n this.name = \"ContainerKekHistoryUnavailableError\";\n }\n}\n\nexport function projectionKekLabel(index: number): string {\n return `Container writer projection KEK[${index}]`;\n}\n\nexport async function assertUnwrappedContainerKekMatchesMaterialId(input: {\n label: string;\n keyMaterial: Uint8Array;\n kek: Pick<\n ProjectionKek,\n \"containerId\" | \"containerKeyEpoch\" | \"containerKeyEpochId\"\n >;\n}): Promise<void> {\n if (!isContainerKekMaterialId(input.kek.containerKeyEpochId)) {\n throw new Error(\n `${input.label} KEK epoch id does not commit to key material`,\n );\n }\n const expectedId = await computeContainerKekMaterialId({\n containerId: input.kek.containerId,\n keyEpoch: input.kek.containerKeyEpoch,\n keyMaterial: input.keyMaterial,\n });\n if (expectedId !== input.kek.containerKeyEpochId) {\n throw new Error(\n `${input.label} KEK material does not match committed epoch id`,\n );\n }\n}\n\nfunction sameContainerManifestHistory(kek: ProjectionKek) {\n return kek.containerManifestHistory.filter(\n (bundle) => readManifestContainerId(bundle) === kek.containerId,\n );\n}\n\n/**\n * Proves the served keyring is the one the rotation that minted the current\n * epoch committed to in its signed event body.\n */\nasync function assertKeyringCommitment(input: {\n currentManifest: ContainerWriterProjectionResponse[\"path\"][number];\n index: number;\n kek: ProjectionKek;\n keyring: ReturnType<typeof normalizeContainerKekKeyring>;\n}): Promise<void> {\n const rotationManifestHash = readContainerKeyEpoch(\n input.kek.keyEpoch,\n `${projectionKekLabel(input.index)} key epoch`,\n ).accessManifestHash;\n const rotationManifest =\n rotationManifestHash === input.currentManifest.manifestHash\n ? input.currentManifest\n : sameContainerManifestHistory(input.kek).find(\n (bundle) => bundle.manifestHash === rotationManifestHash,\n );\n if (!rotationManifest) {\n throw new Error(\n `${projectionKekLabel(input.index)} keyring signer is missing`,\n );\n }\n const eventBundle = readCanonicalRecord(\n rotationManifest.event,\n `${projectionKekLabel(input.index)} keyring event`,\n );\n const eventBody = normalizeContainerAccessEventBody(\n readCanonicalJson(\n Reflect.get(eventBundle, \"body\"),\n `${projectionKekLabel(input.index)} keyring event body`,\n ),\n );\n if (\n (eventBody.eventType !== \"container.move\" &&\n eventBody.eventType !== \"container.rekey\" &&\n eventBody.eventType !== \"container.revoke\") ||\n eventBody.keyringHash !==\n (await computeContainerKekKeyringHash(input.keyring))\n ) {\n throw new Error(\n `${projectionKekLabel(input.index)} keyring does not match its signed event`,\n );\n }\n}\n\nasync function openVerifiedKeyringEntries(input: {\n currentManifest: ContainerWriterProjectionResponse[\"path\"][number];\n index: number;\n kek: ProjectionKek;\n successorKeyMaterial: Uint8Array;\n verifiedByHash: VerifiedManifests;\n verifyKeyringCommitment: boolean;\n}): Promise<Awaited<ReturnType<typeof openContainerKekKeyring>>> {\n const { kek } = input;\n const keyring = normalizeContainerKekKeyring(kek.keyring);\n if (\n keyring.containerId !== kek.containerId ||\n keyring.containerKeyEpochId !== kek.containerKeyEpochId\n ) {\n throw new Error(\n `${projectionKekLabel(input.index)} keyring is inconsistent`,\n );\n }\n if (input.verifyKeyringCommitment) {\n await assertKeyringCommitment({\n currentManifest: input.currentManifest,\n index: input.index,\n kek,\n keyring,\n });\n }\n\n let entries: Awaited<ReturnType<typeof openContainerKekKeyring>>;\n try {\n entries = await openContainerKekKeyring({\n keyEpoch: kek.containerKeyEpoch,\n keyring,\n successorContainerKey: input.successorKeyMaterial,\n });\n } catch (error) {\n if (error instanceof KeyingVerificationError) {\n throw error;\n }\n // Label opaque AEAD failures; structural verification errors already\n // carry their own diagnosis.\n throw new Error(\n `${projectionKekLabel(input.index)} keyring could not be opened`,\n { cause: error },\n );\n }\n // Per-entry material-id verification proves an entry's key matches the id\n // it declares, but a poisoned keyring can declare a self-consistent FAKE\n // id — fresh key, matching commitment — for an epoch the container never\n // had. Anchor every entry the projection can name to the epoch id its\n // signed history actually committed; anything else is a forged epoch.\n await verifyContainerKekEntries(kek.containerId, entries);\n\n // Every epoch id the signed manifest history names must be present in the\n // keyring. A forged entry can be self-consistent, but it cannot also make\n // the real epoch id — which a signed state already named — disappear.\n const entryEpochIds = new Set(\n entries.map((entry) => entry.containerKeyEpochId),\n );\n const signedEpochIds = signedHistoryEpochIds({\n headManifestHash: input.currentManifest.manifestHash,\n kek,\n verifiedByHash: input.verifiedByHash,\n });\n for (const historicalEpochId of signedEpochIds) {\n if (!entryEpochIds.has(historicalEpochId)) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${projectionKekLabel(input.index)} keyring omits an epoch its manifest history commits to`,\n );\n }\n }\n return entries;\n}\n\n/**\n * Epoch ids named by verified historical manifest states for this container.\n * Those states are signed, so an id they name is an epoch the container\n * provably had — and a keyring that omits it in favor of a forged id for the\n * same position is detectable even when no epoch RECORD was shipped.\n */\nexport function manifestHistoryEpochIds(kek: ProjectionKek): Set<string> {\n const epochIds = new Set<string>();\n for (const bundle of sameContainerManifestHistory(kek)) {\n const state = readCanonicalRecord(\n bundle.state,\n \"Container writer projection historical manifest state\",\n );\n const containerKeyEpochId = Reflect.get(state, \"containerKeyEpochId\");\n if (\n typeof containerKeyEpochId === \"string\" &&\n containerKeyEpochId !== kek.containerKeyEpochId\n ) {\n epochIds.add(containerKeyEpochId);\n }\n }\n return epochIds;\n}\n\n/**\n * The epoch ids this KEK's own history names, plus every one its head's\n * verified lineage names wherever the projection served it. Verification pools\n * every KEK's history, so a server can serve a container's older manifests\n * under another KEK; walking the lineage keeps a forged keyring id from passing\n * because the real id it displaces moved (#2365 finding 32). The walk stops at\n * the first manifest verification did not record, so it only ever adds ids.\n */\nexport function signedHistoryEpochIds(input: {\n readonly headManifestHash: string;\n readonly kek: ProjectionKek;\n readonly verifiedByHash: VerifiedManifests;\n}): Set<string> {\n const epochIds = manifestHistoryEpochIds(input.kek);\n const visited = new Set<string>();\n let current = input.verifiedByHash.get(input.headManifestHash);\n while (\n current &&\n current.state.containerId === input.kek.containerId &&\n !visited.has(current.manifestHash)\n ) {\n visited.add(current.manifestHash);\n const epochId = current.state.containerKeyEpochId;\n if (epochId !== null && epochId !== input.kek.containerKeyEpochId) {\n epochIds.add(epochId);\n }\n const previousHash = current.state.previousManifestHash;\n current =\n previousHash === null\n ? undefined\n : input.verifiedByHash.get(previousHash);\n }\n return epochIds;\n}\n\nfunction admitKeyringEntry(input: {\n entry: Awaited<ReturnType<typeof openContainerKekKeyring>>[number];\n index: number;\n kek: ProjectionKek;\n keksByEpochId: Map<string, UnwrappedContainerKek>;\n}): void {\n const { entry, kek } = input;\n const cached = input.keksByEpochId.get(entry.containerKeyEpochId);\n if (cached) {\n if (cached.containerId !== kek.containerId) {\n throw new Error(\n `${projectionKekLabel(input.index)} cached historical KEK is inconsistent`,\n );\n }\n return;\n }\n input.keksByEpochId.set(entry.containerKeyEpochId, {\n containerId: kek.containerId,\n // A keyring entry is key material plus the epoch id that commits to it —\n // there is no epoch record, so no fingerprint. Selection falls back to the\n // epoch id and AEAD authenticates; the commitment check above is what\n // makes the material itself trustworthy.\n keyEpochHash: null,\n keyMaterial: entry.keyMaterial,\n });\n}\n\n/**\n * Opens the sealed keyring for one path index and admits every entry into\n * `keksByEpochId` after verifying it against the material-id commitment its\n * ordinal position implies (entry i is key epoch i + 1). No chain walk:\n * one decrypt yields the container's complete retained history, and entry\n * verification is independent per entry.\n */\nexport async function unwrapKeyringContainerKeksAtIndex(input: {\n currentManifest: ContainerWriterProjectionResponse[\"path\"][number];\n index: number;\n kek: ProjectionKek;\n keksByEpochId: Map<string, UnwrappedContainerKek>;\n successorKeyMaterial: Uint8Array | null;\n /** Every manifest projection verification recorded; anchors the keyring. */\n verifiedByHash: VerifiedManifests;\n verifyKeyringCommitment: boolean;\n}): Promise<void> {\n const { kek, successorKeyMaterial } = input;\n if (!successorKeyMaterial) {\n return;\n }\n\n if (kek.keyring === null) {\n if (kek.containerKeyEpoch !== 1) {\n throw new ContainerKekHistoryUnavailableError(\n projectionKekLabel(input.index),\n );\n }\n return;\n }\n\n const entries = await openVerifiedKeyringEntries({\n currentManifest: input.currentManifest,\n index: input.index,\n kek,\n successorKeyMaterial,\n verifiedByHash: input.verifiedByHash,\n verifyKeyringCommitment: input.verifyKeyringCommitment,\n });\n for (const entry of entries) {\n admitKeyringEntry({\n entry,\n index: input.index,\n kek,\n keksByEpochId: input.keksByEpochId,\n });\n }\n}\n\n/**\n * Epoch ids this projection implies exist but that were not recovered —\n * used to attribute history failures to the material they orphan.\n */\nexport function projectedUnreachablePredecessorEpochIds(input: {\n kek: ProjectionKek;\n keksByEpochId: ReadonlyMap<string, UnwrappedContainerKek>;\n}): string[] {\n const projectedEpochIds = new Set<string>();\n for (const bundle of sameContainerManifestHistory(input.kek)) {\n const state = readCanonicalRecord(\n bundle.state,\n \"Container writer projection historical manifest state\",\n );\n const containerKeyEpochId = Reflect.get(state, \"containerKeyEpochId\");\n if (typeof containerKeyEpochId === \"string\") {\n projectedEpochIds.add(containerKeyEpochId);\n }\n }\n projectedEpochIds.delete(input.kek.containerKeyEpochId);\n return [...projectedEpochIds].filter(\n (containerKeyEpochId) => !input.keksByEpochId.has(containerKeyEpochId),\n );\n}\n"]}
1
+ {"version":3,"file":"containerKekPathHistory.js","sourceRoot":"","sources":["containerKekPathHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeContainerKekKeyringHash,\n computeContainerKekMaterialId,\n isContainerKekMaterialId,\n KeyingVerificationError,\n normalizeContainerAccessEventBody,\n normalizeContainerKekKeyring,\n openContainerKekKeyring,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../keying/canonicalJson\";\nimport { readContainerKeyEpoch } from \"../../keyingProjectionVerification/readers\";\nimport { verifyContainerKekEntries } from \"./containerKekEntryVerification\";\nimport { readManifestContainerId } from \"./readers\";\nimport type { UnwrappedContainerKek } from \"./types\";\n\ntype ProjectionKek = ContainerWriterProjectionResponse[\"containerKeks\"][number];\ntype VerifiedManifests = ReadonlyMap<string, VerifiedContainerAccessManifest>;\n\n/** The projection proves a predecessor existed, but no retained keyring can recover it. */\nexport class ContainerKekHistoryUnavailableError extends Error {\n constructor(label: string) {\n super(`${label} keyring is missing`);\n this.name = \"ContainerKekHistoryUnavailableError\";\n }\n}\n\nexport function projectionKekLabel(index: number): string {\n return `Container writer projection KEK[${index}]`;\n}\n\nexport async function assertUnwrappedContainerKekMatchesMaterialId(input: {\n label: string;\n keyMaterial: Uint8Array;\n kek: Pick<\n ProjectionKek,\n \"containerId\" | \"containerKeyEpoch\" | \"containerKeyEpochId\"\n >;\n}): Promise<void> {\n if (!isContainerKekMaterialId(input.kek.containerKeyEpochId)) {\n throw new Error(\n `${input.label} KEK epoch id does not commit to key material`,\n );\n }\n const expectedId = await computeContainerKekMaterialId({\n containerId: input.kek.containerId,\n keyEpoch: input.kek.containerKeyEpoch,\n keyMaterial: input.keyMaterial,\n });\n if (expectedId !== input.kek.containerKeyEpochId) {\n throw new Error(\n `${input.label} KEK material does not match committed epoch id`,\n );\n }\n}\n\nfunction sameContainerManifestHistory(kek: ProjectionKek) {\n return kek.containerManifestHistory.filter(\n (bundle) => readManifestContainerId(bundle) === kek.containerId,\n );\n}\n\n/**\n * Proves the served keyring is the one the rotation that minted the current\n * epoch committed to in its signed event body.\n */\nasync function assertKeyringCommitment(input: {\n currentManifest: ContainerWriterProjectionResponse[\"path\"][number];\n index: number;\n kek: ProjectionKek;\n keyring: ReturnType<typeof normalizeContainerKekKeyring>;\n}): Promise<void> {\n const rotationManifestHash = readContainerKeyEpoch(\n input.kek.keyEpoch,\n `${projectionKekLabel(input.index)} key epoch`,\n ).accessManifestHash;\n const rotationManifest =\n rotationManifestHash === input.currentManifest.manifestHash\n ? input.currentManifest\n : sameContainerManifestHistory(input.kek).find(\n (bundle) => bundle.manifestHash === rotationManifestHash,\n );\n if (!rotationManifest) {\n throw new Error(\n `${projectionKekLabel(input.index)} keyring signer is missing`,\n );\n }\n const eventBundle = readCanonicalRecord(\n rotationManifest.event,\n `${projectionKekLabel(input.index)} keyring event`,\n );\n const eventBody = normalizeContainerAccessEventBody(\n readCanonicalJson(\n Reflect.get(eventBundle, \"body\"),\n `${projectionKekLabel(input.index)} keyring event body`,\n ),\n );\n if (\n (eventBody.eventType !== \"container.move\" &&\n eventBody.eventType !== \"container.rekey\" &&\n eventBody.eventType !== \"container.revoke\") ||\n eventBody.keyringHash !==\n (await computeContainerKekKeyringHash(input.keyring))\n ) {\n throw new Error(\n `${projectionKekLabel(input.index)} keyring does not match its signed event`,\n );\n }\n}\n\nasync function openVerifiedKeyringEntries(input: {\n currentManifest: ContainerWriterProjectionResponse[\"path\"][number];\n index: number;\n kek: ProjectionKek;\n successorKeyMaterial: Uint8Array;\n verifiedByHash: VerifiedManifests;\n verifyKeyringCommitment: boolean;\n}): Promise<Awaited<ReturnType<typeof openContainerKekKeyring>>> {\n const { kek } = input;\n const keyring = normalizeContainerKekKeyring(kek.keyring);\n if (\n keyring.containerId !== kek.containerId ||\n keyring.containerKeyEpochId !== kek.containerKeyEpochId\n ) {\n throw new Error(\n `${projectionKekLabel(input.index)} keyring is inconsistent`,\n );\n }\n if (input.verifyKeyringCommitment) {\n await assertKeyringCommitment({\n currentManifest: input.currentManifest,\n index: input.index,\n kek,\n keyring,\n });\n }\n\n let entries: Awaited<ReturnType<typeof openContainerKekKeyring>>;\n try {\n entries = await openContainerKekKeyring({\n keyEpoch: kek.containerKeyEpoch,\n keyring,\n successorContainerKey: input.successorKeyMaterial,\n });\n } catch (error) {\n if (error instanceof KeyingVerificationError) {\n throw error;\n }\n // Label opaque AEAD failures; structural verification errors already\n // carry their own diagnosis.\n throw new Error(\n `${projectionKekLabel(input.index)} keyring could not be opened`,\n { cause: error },\n );\n }\n // Per-entry material-id verification proves an entry's key matches the id\n // it declares, but a poisoned keyring can declare a self-consistent FAKE\n // id — fresh key, matching commitment — for an epoch the container never\n // had. Anchor every entry the projection can name to the epoch id its\n // signed history actually committed; anything else is a forged epoch.\n await verifyContainerKekEntries(kek.containerId, entries);\n\n // Every epoch id the signed manifest history names must be present in the\n // keyring. A forged entry can be self-consistent, but it cannot also make\n // the real epoch id — which a signed state already named — disappear.\n const entryEpochIds = new Set(\n entries.map((entry) => entry.containerKeyEpochId),\n );\n const signedEpochIds = signedHistoryEpochIds({\n headManifestHash: input.currentManifest.manifestHash,\n kek,\n verifiedByHash: input.verifiedByHash,\n });\n for (const historicalEpochId of signedEpochIds) {\n if (!entryEpochIds.has(historicalEpochId)) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n `${projectionKekLabel(input.index)} keyring omits an epoch its manifest history commits to`,\n );\n }\n }\n return entries;\n}\n\n/**\n * Epoch ids named by verified historical manifest states for this container.\n * Those states are signed, so an id they name is an epoch the container\n * provably had — and a keyring that omits it in favor of a forged id for the\n * same position is detectable even when no epoch RECORD was shipped.\n */\nexport function manifestHistoryEpochIds(kek: ProjectionKek): Set<string> {\n const epochIds = new Set<string>();\n for (const bundle of sameContainerManifestHistory(kek)) {\n const state = readCanonicalRecord(\n bundle.state,\n \"Container writer projection historical manifest state\",\n );\n const containerKeyEpochId = Reflect.get(state, \"containerKeyEpochId\");\n if (\n typeof containerKeyEpochId === \"string\" &&\n containerKeyEpochId !== kek.containerKeyEpochId\n ) {\n epochIds.add(containerKeyEpochId);\n }\n }\n return epochIds;\n}\n\n/**\n * The epoch ids this KEK's own history names, plus every one its head's\n * verified lineage names wherever the projection served it. Verification pools\n * every KEK's history, so a server can serve a container's older manifests\n * under another KEK; walking the lineage keeps a forged keyring id from passing\n * because the real id it displaces moved (#2365 finding 32). The walk stops at\n * the first manifest verification did not record, so it only ever adds ids.\n */\nexport function signedHistoryEpochIds(input: {\n readonly headManifestHash: string;\n readonly kek: ProjectionKek;\n readonly verifiedByHash: VerifiedManifests;\n}): Set<string> {\n const epochIds = manifestHistoryEpochIds(input.kek);\n const visited = new Set<string>();\n let current = input.verifiedByHash.get(input.headManifestHash);\n while (\n current &&\n current.state.containerId === input.kek.containerId &&\n !visited.has(current.manifestHash)\n ) {\n visited.add(current.manifestHash);\n const epochId = current.state.containerKeyEpochId;\n if (epochId !== null && epochId !== input.kek.containerKeyEpochId) {\n epochIds.add(epochId);\n }\n const previousHash = current.state.previousManifestHash;\n current =\n previousHash === null\n ? undefined\n : input.verifiedByHash.get(previousHash);\n }\n return epochIds;\n}\n\nfunction admitKeyringEntry(input: {\n entry: Awaited<ReturnType<typeof openContainerKekKeyring>>[number];\n index: number;\n kek: ProjectionKek;\n keksByEpochId: Map<string, UnwrappedContainerKek>;\n}): void {\n const { entry, kek } = input;\n const cached = input.keksByEpochId.get(entry.containerKeyEpochId);\n if (cached) {\n if (cached.containerId !== kek.containerId) {\n throw new Error(\n `${projectionKekLabel(input.index)} cached historical KEK is inconsistent`,\n );\n }\n return;\n }\n input.keksByEpochId.set(entry.containerKeyEpochId, {\n containerId: kek.containerId,\n // A keyring entry is key material plus the epoch id that commits to it —\n // there is no epoch record, so no fingerprint. Selection falls back to the\n // epoch id and AEAD authenticates; the commitment check above is what\n // makes the material itself trustworthy.\n keyEpochHash: null,\n keyMaterial: entry.keyMaterial,\n });\n}\n\n/**\n * Opens the sealed keyring for one path index and admits every entry into\n * `keksByEpochId` after verifying it against the material-id commitment its\n * ordinal position implies (entry i is key epoch i + 1). No chain walk:\n * one decrypt yields the container's complete retained history, and entry\n * verification is independent per entry.\n */\nexport async function unwrapKeyringContainerKeksAtIndex(input: {\n currentManifest: ContainerWriterProjectionResponse[\"path\"][number];\n index: number;\n kek: ProjectionKek;\n keksByEpochId: Map<string, UnwrappedContainerKek>;\n successorKeyMaterial: Uint8Array | null;\n /** Every manifest projection verification recorded; anchors the keyring. */\n verifiedByHash: VerifiedManifests;\n verifyKeyringCommitment: boolean;\n}): Promise<void> {\n const { kek, successorKeyMaterial } = input;\n if (!successorKeyMaterial) {\n return;\n }\n\n if (kek.keyring === null) {\n if (kek.containerKeyEpoch !== 1) {\n throw new ContainerKekHistoryUnavailableError(\n projectionKekLabel(input.index),\n );\n }\n return;\n }\n\n const entries = await openVerifiedKeyringEntries({\n currentManifest: input.currentManifest,\n index: input.index,\n kek,\n successorKeyMaterial,\n verifiedByHash: input.verifiedByHash,\n verifyKeyringCommitment: input.verifyKeyringCommitment,\n });\n for (const entry of entries) {\n admitKeyringEntry({\n entry,\n index: input.index,\n kek,\n keksByEpochId: input.keksByEpochId,\n });\n }\n}\n\n/**\n * Epoch ids this projection implies exist but that were not recovered —\n * used to attribute history failures to the material they orphan.\n */\nexport function projectedUnreachablePredecessorEpochIds(input: {\n kek: ProjectionKek;\n keksByEpochId: ReadonlyMap<string, UnwrappedContainerKek>;\n}): string[] {\n const projectedEpochIds = new Set<string>();\n for (const bundle of sameContainerManifestHistory(input.kek)) {\n const state = readCanonicalRecord(\n bundle.state,\n \"Container writer projection historical manifest state\",\n );\n const containerKeyEpochId = Reflect.get(state, \"containerKeyEpochId\");\n if (typeof containerKeyEpochId === \"string\") {\n projectedEpochIds.add(containerKeyEpochId);\n }\n }\n projectedEpochIds.delete(input.kek.containerKeyEpochId);\n return [...projectedEpochIds].filter(\n (containerKeyEpochId) => !input.keksByEpochId.has(containerKeyEpochId),\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { VerifiedContainerAccessManifest } from "../../../internal/crypto/index.js";
2
2
  import type { ContainerWriterProjectionResponse } from "../../../internal/validators/response/index.js";
3
- import { type PrincipalPolicyCache } from "../../keyingProjectionVerification.js";
3
+ import { type PrincipalPolicyCache } from "../../keyingProjectionVerification/index.js";
4
4
  import type { ExecSql } from "../../sqlite/sqlSchema.js";
5
5
  import type { ProjectionVerificationOptions } from "./types.js";
6
6
  export type UnwrapContainerKekPathInput = {