@noy-db/hub 0.2.0-pre.1 → 0.2.0-pre.2

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 (237) hide show
  1. package/dist/aggregate/index.cjs.map +1 -1
  2. package/dist/aggregate/index.js +2 -2
  3. package/dist/attestation/index.cjs +305 -0
  4. package/dist/attestation/index.cjs.map +1 -0
  5. package/dist/attestation/index.d.cts +52 -0
  6. package/dist/attestation/index.d.ts +52 -0
  7. package/dist/attestation/index.js +36 -0
  8. package/dist/attestation/index.js.map +1 -0
  9. package/dist/blobs/index.cjs.map +1 -1
  10. package/dist/blobs/index.d.cts +4 -3
  11. package/dist/blobs/index.d.ts +4 -3
  12. package/dist/blobs/index.js +9 -7
  13. package/dist/blobs/index.js.map +1 -1
  14. package/dist/bundle/index.cjs +16701 -129
  15. package/dist/bundle/index.cjs.map +1 -1
  16. package/dist/bundle/index.d.cts +172 -3
  17. package/dist/bundle/index.d.ts +172 -3
  18. package/dist/bundle/index.js +533 -5
  19. package/dist/bundle/index.js.map +1 -1
  20. package/dist/{chunk-5SCJ5UEF.js → chunk-243PNUA6.js} +2 -2
  21. package/dist/{chunk-WCA2NROQ.js → chunk-2PAQNPE3.js} +2 -2
  22. package/dist/chunk-3QAKZ37R.js +83 -0
  23. package/dist/chunk-3QAKZ37R.js.map +1 -0
  24. package/dist/chunk-3S4BJX25.js +36 -0
  25. package/dist/chunk-3S4BJX25.js.map +1 -0
  26. package/dist/chunk-3XHOCQK4.js +118 -0
  27. package/dist/chunk-3XHOCQK4.js.map +1 -0
  28. package/dist/{chunk-4TFSM22V.js → chunk-3Y53S2SA.js} +3 -3
  29. package/dist/{chunk-6HPZY4ON.js → chunk-3Z2TPHC4.js} +3 -3
  30. package/dist/chunk-4HIL6AHQ.js +57 -0
  31. package/dist/chunk-4HIL6AHQ.js.map +1 -0
  32. package/dist/{chunk-DYECX3IX.js → chunk-7BRE6EUA.js} +2 -2
  33. package/dist/{chunk-DYBQG5PQ.js → chunk-7BUTTVMR.js} +2 -2
  34. package/dist/{chunk-KESP7GOK.js → chunk-7Q5PLD5C.js} +3 -3
  35. package/dist/{chunk-UA4RI7OT.js → chunk-7Z23ZFLV.js} +4 -4
  36. package/dist/chunk-AHPFONIL.js +59 -0
  37. package/dist/chunk-AHPFONIL.js.map +1 -0
  38. package/dist/{chunk-EGQYGYIU.js → chunk-CXSCDO5T.js} +2 -2
  39. package/dist/chunk-E535SAN4.js +8834 -0
  40. package/dist/chunk-E535SAN4.js.map +1 -0
  41. package/dist/{chunk-CBAHB2BF.js → chunk-EUYOGYGV.js} +6 -69
  42. package/dist/chunk-EUYOGYGV.js.map +1 -0
  43. package/dist/{chunk-OMLIZL2P.js → chunk-FAQVNJD4.js} +2 -2
  44. package/dist/{chunk-I6MX32UC.js → chunk-G6FRSBKK.js} +4 -4
  45. package/dist/{chunk-FCXOFQAJ.js → chunk-GIV6DWBG.js} +2 -2
  46. package/dist/{chunk-34YSDCDP.js → chunk-HXJXPZRE.js} +2 -2
  47. package/dist/{chunk-23TTQXVO.js → chunk-J4KLMEUL.js} +2 -2
  48. package/dist/{chunk-VMIO4IXG.js → chunk-JYQTXEIO.js} +5 -228
  49. package/dist/chunk-JYQTXEIO.js.map +1 -0
  50. package/dist/{chunk-NIOHFJPJ.js → chunk-LRAZDV5X.js} +6 -118
  51. package/dist/chunk-LRAZDV5X.js.map +1 -0
  52. package/dist/{chunk-P7EQ2S5O.js → chunk-MUWOSVEP.js} +2 -2
  53. package/dist/chunk-NWZ3I6R6.js +79 -0
  54. package/dist/chunk-NWZ3I6R6.js.map +1 -0
  55. package/dist/{chunk-HB3Z2GCR.js → chunk-OVZDFEOR.js} +2 -2
  56. package/dist/chunk-PFSNOPBQ.js +233 -0
  57. package/dist/chunk-PFSNOPBQ.js.map +1 -0
  58. package/dist/{chunk-UZXLQCHP.js → chunk-PLI5TV7N.js} +2 -2
  59. package/dist/{chunk-PA6R5ZCI.js → chunk-Q6W2CMEJ.js} +3 -3
  60. package/dist/{chunk-537VFZTR.js → chunk-QPEXPHJR.js} +4 -4
  61. package/dist/{chunk-ZNOEIM6Y.js → chunk-QXQRKXCU.js} +2 -2
  62. package/dist/{chunk-RD5LYKD6.js → chunk-RTZVQAJ7.js} +2 -2
  63. package/dist/{chunk-DPMFBCV6.js → chunk-TBKOGSYR.js} +2 -2
  64. package/dist/{chunk-DPMFBCV6.js.map → chunk-TBKOGSYR.js.map} +1 -1
  65. package/dist/chunk-UND4XIB6.js +251 -0
  66. package/dist/chunk-UND4XIB6.js.map +1 -0
  67. package/dist/{chunk-7H6DOO3E.js → chunk-VCGTOS2A.js} +211 -36
  68. package/dist/chunk-VCGTOS2A.js.map +1 -0
  69. package/dist/{chunk-MKSA2V7A.js → chunk-VE6YVP32.js} +2 -2
  70. package/dist/{chunk-5DWL3JBF.js → chunk-VK5EER6C.js} +2 -2
  71. package/dist/{chunk-MIQHZESA.js → chunk-VPSUZLOJ.js} +4 -4
  72. package/dist/{chunk-MIQHZESA.js.map → chunk-VPSUZLOJ.js.map} +1 -1
  73. package/dist/{chunk-XGSOTWYX.js → chunk-VRBCTEKQ.js} +2 -2
  74. package/dist/{chunk-ADQ5MQ54.js → chunk-W3XXT26A.js} +29 -1
  75. package/dist/{chunk-ADQ5MQ54.js.map → chunk-W3XXT26A.js.map} +1 -1
  76. package/dist/{chunk-2AXFIYHT.js → chunk-XG3PTSCD.js} +1 -1
  77. package/dist/chunk-XG3PTSCD.js.map +1 -0
  78. package/dist/{chunk-SIZWEV2Y.js → chunk-Y2RKOPNC.js} +4 -4
  79. package/dist/{chunk-SIZWEV2Y.js.map → chunk-Y2RKOPNC.js.map} +1 -1
  80. package/dist/{chunk-Z72JH4KG.js → chunk-YTXSFG3C.js} +4 -34
  81. package/dist/chunk-YTXSFG3C.js.map +1 -0
  82. package/dist/consent/index.cjs.map +1 -1
  83. package/dist/consent/index.d.cts +4 -3
  84. package/dist/consent/index.d.ts +4 -3
  85. package/dist/consent/index.js +3 -3
  86. package/dist/{crypto-A7FRXYHC.js → crypto-5ZDIY3NG.js} +3 -3
  87. package/dist/{delegation-YBA4X4JN.js → delegation-QYXZW25W.js} +5 -5
  88. package/dist/derivations/index.cjs.map +1 -1
  89. package/dist/derivations/index.d.cts +5 -4
  90. package/dist/derivations/index.d.ts +5 -4
  91. package/dist/derivations/index.js +4 -4
  92. package/dist/{dev-unlock-DRwVSy2S.d.cts → dev-unlock-DQCNDfFp.d.cts} +1 -1
  93. package/dist/{dev-unlock-D9s-loPr.d.ts → dev-unlock-utkybTKb.d.ts} +1 -1
  94. package/dist/executor-AS2IDHKZ.js +11 -0
  95. package/dist/executor-HLXFXNFM.js +8 -0
  96. package/dist/executor-HN6YBHZ5.js +8 -0
  97. package/dist/guards/index.cjs.map +1 -1
  98. package/dist/guards/index.d.cts +5 -4
  99. package/dist/guards/index.d.ts +5 -4
  100. package/dist/guards/index.js +3 -3
  101. package/dist/{hash-DXXXusyk.d.ts → hash-DcoYWfJ_.d.ts} +1 -1
  102. package/dist/{hash-DtRih9MQ.d.cts → hash-jDowCrK2.d.cts} +1 -1
  103. package/dist/history/index.cjs +1 -1
  104. package/dist/history/index.cjs.map +1 -1
  105. package/dist/history/index.d.cts +5 -4
  106. package/dist/history/index.d.ts +5 -4
  107. package/dist/history/index.js +5 -5
  108. package/dist/i18n/index.cjs.map +1 -1
  109. package/dist/i18n/index.d.cts +4 -3
  110. package/dist/i18n/index.d.ts +4 -3
  111. package/dist/i18n/index.js +13 -11
  112. package/dist/i18n/index.js.map +1 -1
  113. package/dist/{index-CNwA-B6-.d.ts → index-BCKdioeh.d.ts} +29 -1
  114. package/dist/{index-CmVgTkqk.d.cts → index-BMjrzNZr.d.cts} +29 -1
  115. package/dist/index.cjs +507 -37
  116. package/dist/index.cjs.map +1 -1
  117. package/dist/index.d.cts +12 -11
  118. package/dist/index.d.ts +12 -11
  119. package/dist/index.js +106 -8817
  120. package/dist/index.js.map +1 -1
  121. package/dist/indexing/index.cjs.map +1 -1
  122. package/dist/indexing/index.js +2 -2
  123. package/dist/issue-ORP37MVW.js +12 -0
  124. package/dist/{ledger-3TXNP47J.js → ledger-3IU5GMXA.js} +5 -5
  125. package/dist/materialized-views/index.cjs.map +1 -1
  126. package/dist/materialized-views/index.d.cts +6 -5
  127. package/dist/materialized-views/index.d.ts +6 -5
  128. package/dist/materialized-views/index.js +6 -6
  129. package/dist/noydb-5H3C24GG.js +34 -0
  130. package/dist/overlay-views/index.cjs.map +1 -1
  131. package/dist/overlay-views/index.d.cts +5 -4
  132. package/dist/overlay-views/index.d.ts +5 -4
  133. package/dist/overlay-views/index.js +6 -4
  134. package/dist/periods/index.cjs.map +1 -1
  135. package/dist/periods/index.d.cts +4 -3
  136. package/dist/periods/index.d.ts +4 -3
  137. package/dist/periods/index.js +5 -5
  138. package/dist/{public-envelope-PY6NKFLI.js → public-envelope-U3CMEOMV.js} +3 -3
  139. package/dist/query/index.cjs.map +1 -1
  140. package/dist/query/index.d.cts +1 -1
  141. package/dist/query/index.d.ts +1 -1
  142. package/dist/query/index.js +3 -3
  143. package/dist/{registry-3L3N3PTG.js → registry-3ALP62P6.js} +3 -3
  144. package/dist/registry-7HE6VJGC.js +8 -0
  145. package/dist/registry-PSIPG2QR.js +8 -0
  146. package/dist/registry-PSIPG2QR.js.map +1 -0
  147. package/dist/revoke-KY2GB4KP.js +17 -0
  148. package/dist/revoke-KY2GB4KP.js.map +1 -0
  149. package/dist/session/index.cjs.map +1 -1
  150. package/dist/session/index.d.cts +5 -4
  151. package/dist/session/index.d.ts +5 -4
  152. package/dist/session/index.js +3 -3
  153. package/dist/shadow/index.cjs.map +1 -1
  154. package/dist/shadow/index.d.cts +4 -3
  155. package/dist/shadow/index.d.ts +4 -3
  156. package/dist/shadow/index.js +2 -2
  157. package/dist/signer-GRI5TZKH.js +18 -0
  158. package/dist/signer-GRI5TZKH.js.map +1 -0
  159. package/dist/{stale-HSC5YO2O.js → stale-OTOF3FH7.js} +2 -2
  160. package/dist/stale-OTOF3FH7.js.map +1 -0
  161. package/dist/store/index.cjs.map +1 -1
  162. package/dist/store/index.d.cts +4 -3
  163. package/dist/store/index.d.ts +4 -3
  164. package/dist/store/index.js +2 -2
  165. package/dist/sync/index.cjs.map +1 -1
  166. package/dist/sync/index.d.cts +3 -2
  167. package/dist/sync/index.d.ts +3 -2
  168. package/dist/sync/index.js +3 -3
  169. package/dist/team/index.cjs.map +1 -1
  170. package/dist/team/index.d.cts +4 -3
  171. package/dist/team/index.d.ts +4 -3
  172. package/dist/team/index.js +12 -10
  173. package/dist/tx/index.cjs.map +1 -1
  174. package/dist/tx/index.d.cts +4 -3
  175. package/dist/tx/index.d.ts +4 -3
  176. package/dist/tx/index.js +2 -2
  177. package/dist/{types-DW9RGSSs.d.ts → types-BoFFiskX.d.ts} +119 -3
  178. package/dist/{types-C4lwMKKF.d.cts → types-DJG8HG6F.d.cts} +119 -3
  179. package/dist/{index-hdFvZkBP.d.cts → ulid-BmBgooGm.d.ts} +51 -33
  180. package/dist/{index-4agOpzqd.d.ts → ulid-C7ms9oli.d.cts} +51 -33
  181. package/dist/util/index.cjs.map +1 -1
  182. package/dist/util/index.js +1 -1
  183. package/dist/{with-derivation-g-pGoMzL.d.ts → with-derivation-BKXXa8Vt.d.ts} +1 -1
  184. package/dist/{with-derivation-C8LDlV7t.d.cts → with-derivation-BjQ7q4NE.d.cts} +1 -1
  185. package/dist/{with-guard-DWOCK4Ca.d.ts → with-guard-C25yNjzd.d.ts} +1 -1
  186. package/dist/{with-guard-jI1x9Z3k.d.cts → with-guard-DQme5DKE.d.cts} +1 -1
  187. package/dist/{with-materialized-view-DcTx4H3j.d.cts → with-materialized-view-BbEPFIIJ.d.cts} +1 -1
  188. package/dist/{with-materialized-view-DaKR-N6J.d.ts → with-materialized-view-CqnRwI2S.d.ts} +1 -1
  189. package/dist/{with-overlayed-view-N7jYuNOS.d.ts → with-overlayed-view-Ct1fSJt-.d.ts} +1 -1
  190. package/dist/{with-overlayed-view-D-6oWAgM.d.cts → with-overlayed-view-bwlmmFjx.d.cts} +1 -1
  191. package/package.json +15 -3
  192. package/dist/chunk-2AXFIYHT.js.map +0 -1
  193. package/dist/chunk-7H6DOO3E.js.map +0 -1
  194. package/dist/chunk-CBAHB2BF.js.map +0 -1
  195. package/dist/chunk-NIOHFJPJ.js.map +0 -1
  196. package/dist/chunk-VMIO4IXG.js.map +0 -1
  197. package/dist/chunk-Z72JH4KG.js.map +0 -1
  198. package/dist/executor-7E3VFGW7.js +0 -11
  199. package/dist/executor-CEWX2FQI.js +0 -8
  200. package/dist/executor-X4SQ3ZLC.js +0 -8
  201. package/dist/registry-O47PUPSY.js +0 -8
  202. package/dist/registry-WLLMODKN.js +0 -8
  203. /package/dist/{chunk-5SCJ5UEF.js.map → chunk-243PNUA6.js.map} +0 -0
  204. /package/dist/{chunk-WCA2NROQ.js.map → chunk-2PAQNPE3.js.map} +0 -0
  205. /package/dist/{chunk-4TFSM22V.js.map → chunk-3Y53S2SA.js.map} +0 -0
  206. /package/dist/{chunk-6HPZY4ON.js.map → chunk-3Z2TPHC4.js.map} +0 -0
  207. /package/dist/{chunk-DYECX3IX.js.map → chunk-7BRE6EUA.js.map} +0 -0
  208. /package/dist/{chunk-DYBQG5PQ.js.map → chunk-7BUTTVMR.js.map} +0 -0
  209. /package/dist/{chunk-KESP7GOK.js.map → chunk-7Q5PLD5C.js.map} +0 -0
  210. /package/dist/{chunk-UA4RI7OT.js.map → chunk-7Z23ZFLV.js.map} +0 -0
  211. /package/dist/{chunk-EGQYGYIU.js.map → chunk-CXSCDO5T.js.map} +0 -0
  212. /package/dist/{chunk-OMLIZL2P.js.map → chunk-FAQVNJD4.js.map} +0 -0
  213. /package/dist/{chunk-I6MX32UC.js.map → chunk-G6FRSBKK.js.map} +0 -0
  214. /package/dist/{chunk-FCXOFQAJ.js.map → chunk-GIV6DWBG.js.map} +0 -0
  215. /package/dist/{chunk-34YSDCDP.js.map → chunk-HXJXPZRE.js.map} +0 -0
  216. /package/dist/{chunk-23TTQXVO.js.map → chunk-J4KLMEUL.js.map} +0 -0
  217. /package/dist/{chunk-P7EQ2S5O.js.map → chunk-MUWOSVEP.js.map} +0 -0
  218. /package/dist/{chunk-HB3Z2GCR.js.map → chunk-OVZDFEOR.js.map} +0 -0
  219. /package/dist/{chunk-UZXLQCHP.js.map → chunk-PLI5TV7N.js.map} +0 -0
  220. /package/dist/{chunk-PA6R5ZCI.js.map → chunk-Q6W2CMEJ.js.map} +0 -0
  221. /package/dist/{chunk-537VFZTR.js.map → chunk-QPEXPHJR.js.map} +0 -0
  222. /package/dist/{chunk-ZNOEIM6Y.js.map → chunk-QXQRKXCU.js.map} +0 -0
  223. /package/dist/{chunk-RD5LYKD6.js.map → chunk-RTZVQAJ7.js.map} +0 -0
  224. /package/dist/{chunk-MKSA2V7A.js.map → chunk-VE6YVP32.js.map} +0 -0
  225. /package/dist/{chunk-5DWL3JBF.js.map → chunk-VK5EER6C.js.map} +0 -0
  226. /package/dist/{chunk-XGSOTWYX.js.map → chunk-VRBCTEKQ.js.map} +0 -0
  227. /package/dist/{crypto-A7FRXYHC.js.map → crypto-5ZDIY3NG.js.map} +0 -0
  228. /package/dist/{delegation-YBA4X4JN.js.map → delegation-QYXZW25W.js.map} +0 -0
  229. /package/dist/{executor-7E3VFGW7.js.map → executor-AS2IDHKZ.js.map} +0 -0
  230. /package/dist/{executor-CEWX2FQI.js.map → executor-HLXFXNFM.js.map} +0 -0
  231. /package/dist/{executor-X4SQ3ZLC.js.map → executor-HN6YBHZ5.js.map} +0 -0
  232. /package/dist/{ledger-3TXNP47J.js.map → issue-ORP37MVW.js.map} +0 -0
  233. /package/dist/{public-envelope-PY6NKFLI.js.map → ledger-3IU5GMXA.js.map} +0 -0
  234. /package/dist/{registry-3L3N3PTG.js.map → noydb-5H3C24GG.js.map} +0 -0
  235. /package/dist/{registry-O47PUPSY.js.map → public-envelope-U3CMEOMV.js.map} +0 -0
  236. /package/dist/{registry-WLLMODKN.js.map → registry-3ALP62P6.js.map} +0 -0
  237. /package/dist/{stale-HSC5YO2O.js.map → registry-7HE6VJGC.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -46,7 +46,7 @@ var init_types = __esm({
46
46
  });
47
47
 
48
48
  // src/errors.ts
49
- var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, GroupCardinalityError, IndexRequiredError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError;
49
+ var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, GroupCardinalityError, IndexRequiredError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError;
50
50
  var init_errors = __esm({
51
51
  "src/errors.ts"() {
52
52
  "use strict";
@@ -563,6 +563,12 @@ Resolutions:
563
563
  this.id = id;
564
564
  }
565
565
  };
566
+ AttestationError = class extends NoydbError {
567
+ constructor(message) {
568
+ super("ATTESTATION", message);
569
+ this.name = "AttestationError";
570
+ }
571
+ };
566
572
  SessionExpiredError = class extends NoydbError {
567
573
  sessionId;
568
574
  constructor(sessionId) {
@@ -3298,6 +3304,185 @@ var init_fanout_sidecar = __esm({
3298
3304
  }
3299
3305
  });
3300
3306
 
3307
+ // src/attestation/signer.ts
3308
+ var signer_exports = {};
3309
+ __export(signer_exports, {
3310
+ ATTESTATIONS_COLLECTION: () => ATTESTATIONS_COLLECTION,
3311
+ REVOKED_RECORD_ID: () => REVOKED_RECORD_ID,
3312
+ SIGNER_RECORD_ID: () => SIGNER_RECORD_ID,
3313
+ loadOrCreateSigner: () => loadOrCreateSigner,
3314
+ loadSigner: () => loadSigner
3315
+ });
3316
+ async function loadSigner(store, vault, getDEK) {
3317
+ const existing = await store.get(vault, ATTESTATIONS_COLLECTION, SIGNER_RECORD_ID);
3318
+ if (!existing) return null;
3319
+ const dek = await getDEK(ATTESTATIONS_COLLECTION);
3320
+ const json = await decrypt(existing._iv, existing._data, dek);
3321
+ return JSON.parse(json);
3322
+ }
3323
+ async function loadOrCreateSigner(store, vault, getDEK) {
3324
+ const existing = await loadSigner(store, vault, getDEK);
3325
+ if (existing) return existing;
3326
+ const dek = await getDEK(ATTESTATIONS_COLLECTION);
3327
+ const signer = await (0, import_attestation.generateDocSigningKeyPair)();
3328
+ const { iv, data } = await encrypt(JSON.stringify(signer), dek);
3329
+ const env = {
3330
+ _noydb: NOYDB_FORMAT_VERSION,
3331
+ _v: 1,
3332
+ _ts: (/* @__PURE__ */ new Date()).toISOString(),
3333
+ _iv: iv,
3334
+ _data: data
3335
+ };
3336
+ try {
3337
+ await store.put(vault, ATTESTATIONS_COLLECTION, SIGNER_RECORD_ID, env, 0);
3338
+ return signer;
3339
+ } catch (e) {
3340
+ if (!(e instanceof ConflictError)) throw e;
3341
+ const winner = await loadSigner(store, vault, getDEK);
3342
+ if (!winner) {
3343
+ throw new ConflictError(0, "loadOrCreateSigner: signer mint lost a concurrent race but the winning record could not be re-read.");
3344
+ }
3345
+ return winner;
3346
+ }
3347
+ }
3348
+ var import_attestation, ATTESTATIONS_COLLECTION, SIGNER_RECORD_ID, REVOKED_RECORD_ID;
3349
+ var init_signer = __esm({
3350
+ "src/attestation/signer.ts"() {
3351
+ "use strict";
3352
+ init_types();
3353
+ init_crypto();
3354
+ init_errors();
3355
+ import_attestation = require("@noy-db/attestation");
3356
+ ATTESTATIONS_COLLECTION = "_attestations";
3357
+ SIGNER_RECORD_ID = "_signer";
3358
+ REVOKED_RECORD_ID = "_revoked";
3359
+ }
3360
+ });
3361
+
3362
+ // src/attestation/issue.ts
3363
+ var issue_exports = {};
3364
+ __export(issue_exports, {
3365
+ issueAttestationCore: () => issueAttestationCore
3366
+ });
3367
+ async function issueAttestationCore(ctx, args) {
3368
+ if (ctx.role !== "owner") {
3369
+ throw new AttestationError(`issueAttestation requires the 'owner' role; caller is '${ctx.role}'. Issuing a signed attestation is the firm's identity operation.`);
3370
+ }
3371
+ const src = await ctx.readRecord(args.collection, args.id);
3372
+ if (!src) throw new AttestationError(`issueAttestation: source record '${args.collection}/${args.id}' not found.`);
3373
+ const dek = await ctx.getDEK();
3374
+ const signer = await loadOrCreateSigner(ctx.store, ctx.vault, () => Promise.resolve(dek));
3375
+ const saltB64 = (0, import_attestation2.bytesToB64url)(crypto.getRandomValues(new Uint8Array(16)));
3376
+ let fieldHashes;
3377
+ try {
3378
+ fieldHashes = await (0, import_attestation2.computeFieldHashes)(saltB64, args.fieldSchema, src.record);
3379
+ } catch (e) {
3380
+ throw new AttestationError(`issueAttestation: ${e.message}`);
3381
+ }
3382
+ const docId = generateULID();
3383
+ const sig = await (0, import_attestation2.signPayloadCore)({ v: 1, docId, salt: saltB64, keyId: signer.keyId, fieldHashes }, signer.privateKeyPkcs8B64);
3384
+ const payload = { v: 1, docId, salt: saltB64, alg: "ed25519", keyId: signer.keyId, fieldHashes, sig };
3385
+ const index = {
3386
+ docId,
3387
+ issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
3388
+ keyId: signer.keyId,
3389
+ fieldPaths: args.fieldSchema.fields.map((f) => f.path),
3390
+ sourceRefs: [{ collection: args.collection, id: args.id, version: src.version }]
3391
+ };
3392
+ const { iv, data } = await encrypt(JSON.stringify(index), dek);
3393
+ const env = { _noydb: NOYDB_FORMAT_VERSION, _v: 1, _ts: index.issuedAt, _iv: iv, _data: data };
3394
+ await ctx.store.put(ctx.vault, ATTESTATIONS_COLLECTION, docId, env);
3395
+ return { docId, qr: (0, import_attestation2.encodeQr)(payload), payload, keyId: signer.keyId, publicKeyB64: signer.publicKeyB64 };
3396
+ }
3397
+ var import_attestation2;
3398
+ var init_issue = __esm({
3399
+ "src/attestation/issue.ts"() {
3400
+ "use strict";
3401
+ init_types();
3402
+ init_crypto();
3403
+ init_errors();
3404
+ init_ulid();
3405
+ init_signer();
3406
+ import_attestation2 = require("@noy-db/attestation");
3407
+ }
3408
+ });
3409
+
3410
+ // src/attestation/revoke.ts
3411
+ var revoke_exports = {};
3412
+ __export(revoke_exports, {
3413
+ getRevokedDocIdsCore: () => getRevokedDocIdsCore,
3414
+ publishRevocationListCore: () => publishRevocationListCore,
3415
+ revokeDocCore: () => revokeDocCore,
3416
+ unrevokeDocCore: () => unrevokeDocCore
3417
+ });
3418
+ function requireOwner(ctx, op) {
3419
+ if (ctx.role !== "owner") {
3420
+ throw new AttestationError(`${op} requires the 'owner' role; caller is '${ctx.role}'. Revocation is the firm's identity operation.`);
3421
+ }
3422
+ }
3423
+ async function readSet(store, vault, dek) {
3424
+ const env = await store.get(vault, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID);
3425
+ if (!env) return { docIds: /* @__PURE__ */ new Set(), version: void 0 };
3426
+ const set = JSON.parse(await decrypt(env._iv, env._data, dek));
3427
+ return { docIds: new Set(set.docIds), version: env._v };
3428
+ }
3429
+ async function mutateSet(ctx, mutate) {
3430
+ const dek = await ctx.getDEK();
3431
+ for (let attempt = 0; attempt < 2; attempt++) {
3432
+ const { docIds, version } = await readSet(ctx.store, ctx.vault, dek);
3433
+ mutate(docIds);
3434
+ const payload = { docIds: [...docIds].sort(), updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
3435
+ const { iv, data } = await encrypt(JSON.stringify(payload), dek);
3436
+ const expectedVersion = version ?? 0;
3437
+ const env = {
3438
+ _noydb: NOYDB_FORMAT_VERSION,
3439
+ _v: expectedVersion + 1,
3440
+ _ts: payload.updatedAt,
3441
+ _iv: iv,
3442
+ _data: data
3443
+ };
3444
+ try {
3445
+ await ctx.store.put(ctx.vault, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID, env, expectedVersion);
3446
+ return;
3447
+ } catch (e) {
3448
+ if (e instanceof ConflictError && attempt === 0) continue;
3449
+ throw e;
3450
+ }
3451
+ }
3452
+ }
3453
+ async function revokeDocCore(ctx, docId) {
3454
+ requireOwner(ctx, "revokeAttestation");
3455
+ const issued = await ctx.store.get(ctx.vault, ATTESTATIONS_COLLECTION, docId);
3456
+ if (!issued) throw new AttestationError(`revokeAttestation: attestation '${docId}' not found (was it issued by this vault?).`);
3457
+ await mutateSet(ctx, (ids) => ids.add(docId));
3458
+ }
3459
+ async function unrevokeDocCore(ctx, docId) {
3460
+ requireOwner(ctx, "unrevokeAttestation");
3461
+ await mutateSet(ctx, (ids) => ids.delete(docId));
3462
+ }
3463
+ async function getRevokedDocIdsCore(ctx) {
3464
+ const dek = await ctx.getDEK();
3465
+ const { docIds } = await readSet(ctx.store, ctx.vault, dek);
3466
+ return [...docIds].sort();
3467
+ }
3468
+ async function publishRevocationListCore(ctx) {
3469
+ requireOwner(ctx, "publishRevocationList");
3470
+ const docIds = await getRevokedDocIdsCore(ctx);
3471
+ const signer = await loadOrCreateSigner(ctx.store, ctx.vault, () => ctx.getDEK());
3472
+ return (0, import_attestation3.signRevocationList)(docIds, (/* @__PURE__ */ new Date()).toISOString(), signer.keyId, signer.privateKeyPkcs8B64);
3473
+ }
3474
+ var import_attestation3;
3475
+ var init_revoke = __esm({
3476
+ "src/attestation/revoke.ts"() {
3477
+ "use strict";
3478
+ init_types();
3479
+ init_crypto();
3480
+ init_errors();
3481
+ init_signer();
3482
+ import_attestation3 = require("@noy-db/attestation");
3483
+ }
3484
+ });
3485
+
3301
3486
  // src/guards/registry.ts
3302
3487
  var registry_exports2 = {};
3303
3488
  __export(registry_exports2, {
@@ -3695,6 +3880,7 @@ __export(src_exports, {
3695
3880
  Aggregation: () => Aggregation,
3696
3881
  AlreadyElevatedError: () => AlreadyElevatedError,
3697
3882
  AmendmentForbiddenError: () => AmendmentForbiddenError,
3883
+ AttestationError: () => AttestationError,
3698
3884
  BLOB_CHUNKS_COLLECTION: () => BLOB_CHUNKS_COLLECTION,
3699
3885
  BLOB_COLLECTION: () => BLOB_COLLECTION,
3700
3886
  BLOB_INDEX_COLLECTION: () => BLOB_INDEX_COLLECTION,
@@ -3768,6 +3954,7 @@ __export(src_exports, {
3768
3954
  MaterializedViewCycleError: () => MaterializedViewCycleError,
3769
3955
  MaterializedViewSourceUnknownError: () => MaterializedViewSourceUnknownError,
3770
3956
  MaterializedViewTooLargeError: () => MaterializedViewTooLargeError,
3957
+ MemoryRecipientSealer: () => MemoryRecipientSealer,
3771
3958
  MemorySealingKeyProvider: () => MemorySealingKeyProvider,
3772
3959
  MissingTranslationError: () => MissingTranslationError,
3773
3960
  NOYDB_BACKUP_VERSION: () => NOYDB_BACKUP_VERSION,
@@ -5878,7 +6065,9 @@ var ALLOWED_HEADER_KEYS = /* @__PURE__ */ new Set([
5878
6065
  "bodyBytes",
5879
6066
  "bodySha256",
5880
6067
  "publicEnvelope",
5881
- "autoUnlock"
6068
+ "autoUnlock",
6069
+ "bundleKind",
6070
+ "transferSeal"
5882
6071
  ]);
5883
6072
  function validateBundleHeader(parsed) {
5884
6073
  if (parsed === null || typeof parsed !== "object") {
@@ -5941,6 +6130,47 @@ function validateBundleHeader(parsed) {
5941
6130
  );
5942
6131
  }
5943
6132
  }
6133
+ if (h["bundleKind"] !== void 0) {
6134
+ if (h["bundleKind"] !== "snapshot" && h["bundleKind"] !== "extracted-partition") {
6135
+ const got = typeof h["bundleKind"] === "string" ? `"${h["bundleKind"]}"` : typeof h["bundleKind"];
6136
+ throw new Error(
6137
+ `.noydb bundle header.bundleKind must be 'snapshot' or 'extracted-partition' when present, got ${got}.`
6138
+ );
6139
+ }
6140
+ }
6141
+ if (h["transferSeal"] !== void 0) {
6142
+ const ts = h["transferSeal"];
6143
+ if (ts === null || typeof ts !== "object" || Array.isArray(ts)) {
6144
+ throw new Error(`.noydb bundle header.transferSeal must be a JSON object when present, got ${typeof ts}.`);
6145
+ }
6146
+ const t = ts;
6147
+ if (t["v"] !== 1) {
6148
+ throw new Error(`.noydb bundle header.transferSeal.v must be 1, got ${String(t["v"])}.`);
6149
+ }
6150
+ if (t["alg"] !== "aes-256-gcm-pre-shared") {
6151
+ throw new Error(`.noydb bundle header.transferSeal.alg must be 'aes-256-gcm-pre-shared', got ${String(t["alg"])}.`);
6152
+ }
6153
+ if (typeof t["sealId"] !== "string" || t["sealId"].length === 0) {
6154
+ throw new Error(`.noydb bundle header.transferSeal.sealId must be a non-empty string, got ${String(t["sealId"])}.`);
6155
+ }
6156
+ }
6157
+ const isExtracted = h["bundleKind"] === "extracted-partition";
6158
+ const hasSeal = h["transferSeal"] !== void 0;
6159
+ if (hasSeal && !isExtracted) {
6160
+ throw new Error(
6161
+ `.noydb bundle header.transferSeal requires bundleKind === 'extracted-partition'.`
6162
+ );
6163
+ }
6164
+ if (isExtracted && !hasSeal) {
6165
+ throw new Error(
6166
+ `.noydb bundle header with bundleKind === 'extracted-partition' must carry a transferSeal indicator.`
6167
+ );
6168
+ }
6169
+ if (isExtracted && h["autoUnlock"] !== void 0) {
6170
+ throw new Error(
6171
+ `.noydb bundle header cannot carry both autoUnlock and bundleKind === 'extracted-partition' \u2014 an extracted partition is unlocked via its transfer seal, not an auto-credential.`
6172
+ );
6173
+ }
5944
6174
  }
5945
6175
  function encodeBundleHeader(header) {
5946
6176
  validateBundleHeader(header);
@@ -5950,7 +6180,9 @@ function encodeBundleHeader(header) {
5950
6180
  bodyBytes: header.bodyBytes,
5951
6181
  bodySha256: header.bodySha256,
5952
6182
  ...header.publicEnvelope !== void 0 ? { publicEnvelope: header.publicEnvelope } : {},
5953
- ...header.autoUnlock !== void 0 ? { autoUnlock: header.autoUnlock } : {}
6183
+ ...header.autoUnlock !== void 0 ? { autoUnlock: header.autoUnlock } : {},
6184
+ ...header.bundleKind !== void 0 ? { bundleKind: header.bundleKind } : {},
6185
+ ...header.transferSeal !== void 0 ? { transferSeal: header.transferSeal } : {}
5954
6186
  });
5955
6187
  return new TextEncoder().encode(json);
5956
6188
  }
@@ -6012,10 +6244,19 @@ function normalizeAutoUnlock(opts) {
6012
6244
  return { mode: "unsealed", perUser: toAutoCredentials(opts.autoPassphrases.perUser) };
6013
6245
  }
6014
6246
  if (opts.sealedCredentials !== void 0) {
6015
- return { mode: "sealed", provider: opts.sealedCredentials.provider, perUser: opts.sealedCredentials.perUser };
6247
+ if (opts.sealedCredentials.mode === "recipient-target") {
6248
+ const perUser = {};
6249
+ const hints = {};
6250
+ for (const [userId, entry] of Object.entries(opts.sealedCredentials.perUser)) {
6251
+ perUser[userId] = entry.credential;
6252
+ hints[userId] = entry.hint;
6253
+ }
6254
+ return { mode: "sealed-recipient", provider: opts.sealedCredentials.provider, perUser, hints };
6255
+ }
6256
+ return { mode: "sealed-self", provider: opts.sealedCredentials.provider, perUser: opts.sealedCredentials.perUser };
6016
6257
  }
6017
6258
  return {
6018
- mode: "sealed",
6259
+ mode: "sealed-self",
6019
6260
  provider: opts.sealedPassphrases.provider,
6020
6261
  perUser: toAutoCredentials(opts.sealedPassphrases.perUser)
6021
6262
  };
@@ -6045,10 +6286,52 @@ function validateAutoUnlockOptions(opts, normalized) {
6045
6286
  }
6046
6287
  return "unsealed";
6047
6288
  }
6048
- const mode = opts.sealedCredentials?.mode ?? opts.sealedPassphrases?.mode;
6049
- if (mode !== "self-target") {
6289
+ if (normalized.mode === "sealed-recipient") {
6290
+ const provider = normalized.provider;
6291
+ if (provider === void 0 || typeof provider.publishRecipientHint !== "function" || typeof provider.sealForRecipient !== "function") {
6292
+ throw new ValidationError(
6293
+ "writeNoydbBundle: `sealedCredentials.provider` for mode 'recipient-target' must be a RecipientSealer (publishRecipientHint + sealForRecipient). Self-only providers (MemorySealingKeyProvider, at-macos-keychain, etc.) do not satisfy this contract."
6294
+ );
6295
+ }
6296
+ const hints = normalized.hints;
6297
+ if (hints === void 0) {
6298
+ throw new Error("unreachable \u2014 sealed-recipient normalization must populate hints");
6299
+ }
6300
+ for (const userId of Object.keys(normalized.perUser)) {
6301
+ const hint = hints[userId];
6302
+ if (hint === void 0) {
6303
+ throw new ValidationError(
6304
+ `writeNoydbBundle: \`sealedCredentials.perUser['${userId}']\` missing required \`hint\` for mode 'recipient-target'.`
6305
+ );
6306
+ }
6307
+ if (hint.v !== 1) {
6308
+ throw new ValidationError(
6309
+ `writeNoydbBundle: \`sealedCredentials.perUser['${userId}'].hint.v\` must be 1 (got ${String(hint.v)}).`
6310
+ );
6311
+ }
6312
+ if (typeof hint.pid !== "string" || hint.pid.length === 0) {
6313
+ throw new ValidationError(
6314
+ `writeNoydbBundle: \`sealedCredentials.perUser['${userId}'].hint.pid\` must be a non-empty string identifying the recipient.`
6315
+ );
6316
+ }
6317
+ if (hint.alg !== "rsa-oaep-sha256") {
6318
+ throw new ValidationError(
6319
+ `writeNoydbBundle: \`sealedCredentials.perUser['${userId}'].hint.alg\` must be 'rsa-oaep-sha256' in slice 1 (got '${String(hint.alg)}').`
6320
+ );
6321
+ }
6322
+ }
6323
+ const userCount2 = Object.keys(normalized.perUser).length;
6324
+ if (userCount2 === 0) {
6325
+ throw new ValidationError(
6326
+ "writeNoydbBundle: `sealedCredentials.perUser` must have at least one entry."
6327
+ );
6328
+ }
6329
+ return "sealed";
6330
+ }
6331
+ const selfTargetMode = opts.sealedCredentials?.mode ?? opts.sealedPassphrases?.mode;
6332
+ if (selfTargetMode !== "self-target") {
6050
6333
  throw new ValidationError(
6051
- `writeNoydbBundle: \`sealedCredentials.mode\` (or \`sealedPassphrases.mode\`) must be 'self-target' in slice 1 (got '${String(mode)}'). Recipient-target sealing via the RecipientSealer interface is deferred per foundation \xA711.4.`
6334
+ `writeNoydbBundle: \`sealedCredentials.mode\` (or \`sealedPassphrases.mode\`) must be 'self-target' or 'recipient-target' (got '${String(selfTargetMode)}').`
6052
6335
  );
6053
6336
  }
6054
6337
  if (normalized.provider === void 0) {
@@ -6081,14 +6364,35 @@ async function buildAutoUnlockWrapper(dumpJson, normalized) {
6081
6364
  }
6082
6365
  const sealedPerUser = {};
6083
6366
  const encoder = new TextEncoder();
6084
- for (const [userId, cred] of Object.entries(normalized.perUser)) {
6085
- const sealed = await provider.seal(encoder.encode(cred.value));
6086
- sealedPerUser[userId] = {
6087
- pid: provider.id,
6088
- sealed: bytesToBase64(sealed),
6089
- alg: "aes-256-gcm",
6090
- kind: cred.kind
6091
- };
6367
+ if (normalized.mode === "sealed-recipient") {
6368
+ const recipientSealer = provider;
6369
+ const hints = normalized.hints;
6370
+ if (hints === void 0) {
6371
+ throw new Error("unreachable \u2014 sealed-recipient normalization must populate hints");
6372
+ }
6373
+ for (const [userId, cred] of Object.entries(normalized.perUser)) {
6374
+ const hint = hints[userId];
6375
+ const sealed = await recipientSealer.sealForRecipient(encoder.encode(cred.value), hint);
6376
+ sealedPerUser[userId] = {
6377
+ pid: hint.pid,
6378
+ // use the recipient's pid, not the sender's
6379
+ sealed: bytesToBase64(sealed),
6380
+ alg: "aes-256-gcm",
6381
+ kind: cred.kind,
6382
+ hint
6383
+ };
6384
+ }
6385
+ } else {
6386
+ const selfSealer = provider;
6387
+ for (const [userId, cred] of Object.entries(normalized.perUser)) {
6388
+ const sealed = await selfSealer.seal(encoder.encode(cred.value));
6389
+ sealedPerUser[userId] = {
6390
+ pid: selfSealer.id,
6391
+ sealed: bytesToBase64(sealed),
6392
+ alg: "aes-256-gcm",
6393
+ kind: cred.kind
6394
+ };
6395
+ }
6092
6396
  }
6093
6397
  return {
6094
6398
  _noydb_bundle_body: 1,
@@ -6171,11 +6475,19 @@ async function resolveAutoUnlock(blob, opts) {
6171
6475
  }
6172
6476
  }
6173
6477
  if (opened === null) {
6478
+ if (entry.hint !== void 0) {
6479
+ unsealedMap[userId] = { kind: credKind, value: entry.sealed };
6480
+ continue;
6481
+ }
6174
6482
  throw new BundleSealMismatchError(userId, entry.pid);
6175
6483
  }
6176
6484
  unsealedMap[userId] = { kind: credKind, value: opened };
6177
6485
  continue;
6178
6486
  }
6487
+ if (entry.hint !== void 0) {
6488
+ unsealedMap[userId] = { kind: credKind, value: entry.sealed };
6489
+ continue;
6490
+ }
6179
6491
  throw new BundleSealMismatchError(userId, entry.pid);
6180
6492
  }
6181
6493
  const plaintextBytes = await provider.unseal(base64ToBytes(entry.sealed));
@@ -6343,6 +6655,29 @@ async function applyPlaintextFilters(vault, dumpJson, opts) {
6343
6655
  backup.collections = next;
6344
6656
  return JSON.stringify(backup);
6345
6657
  }
6658
+ async function assembleBundleContainer(opts) {
6659
+ const dumpBytes = new TextEncoder().encode(opts.bodyJsonStr);
6660
+ const { format, streamFormat } = selectCompression(opts.compression);
6661
+ const body = streamFormat === null ? dumpBytes : await pumpThroughStream(dumpBytes, new CompressionStream(streamFormat));
6662
+ const bodySha256 = await sha256Hex2(body);
6663
+ const header = {
6664
+ formatVersion: NOYDB_BUNDLE_FORMAT_VERSION,
6665
+ handle: opts.handle,
6666
+ bodyBytes: body.length,
6667
+ bodySha256,
6668
+ ...opts.headerExtras?.publicEnvelope !== void 0 ? { publicEnvelope: opts.headerExtras.publicEnvelope } : {},
6669
+ ...opts.headerExtras?.autoUnlock !== void 0 ? { autoUnlock: opts.headerExtras.autoUnlock } : {},
6670
+ ...opts.headerExtras?.bundleKind !== void 0 ? { bundleKind: opts.headerExtras.bundleKind } : {},
6671
+ ...opts.headerExtras?.transferSeal !== void 0 ? { transferSeal: opts.headerExtras.transferSeal } : {}
6672
+ };
6673
+ const headerBytes = encodeBundleHeader(header);
6674
+ const prefix = new Uint8Array(NOYDB_BUNDLE_PREFIX_BYTES);
6675
+ prefix.set(NOYDB_BUNDLE_MAGIC, 0);
6676
+ prefix[4] = (streamFormat === null ? 0 : FLAG_COMPRESSED) | FLAG_HAS_INTEGRITY_HASH;
6677
+ prefix[5] = format;
6678
+ writeUint32BE(prefix, 6, headerBytes.length);
6679
+ return concatBytes([prefix, headerBytes, body]);
6680
+ }
6346
6681
  async function writeNoydbBundle(vault, opts = {}) {
6347
6682
  if (opts.exportPassphrase !== void 0 && opts.recipients !== void 0) {
6348
6683
  throw new Error(
@@ -6357,26 +6692,16 @@ async function writeNoydbBundle(vault, opts = {}) {
6357
6692
  const plainFiltered = await applyPlaintextFilters(vault, rekeyed, opts);
6358
6693
  const filtered = applySliceFilters(plainFiltered, opts);
6359
6694
  const bodyJsonStr = normalizedAutoUnlock === null ? filtered : JSON.stringify(await buildAutoUnlockWrapper(filtered, normalizedAutoUnlock));
6360
- const dumpBytes = new TextEncoder().encode(bodyJsonStr);
6361
- const { format, streamFormat } = selectCompression(opts.compression);
6362
- const body = streamFormat === null ? dumpBytes : await pumpThroughStream(dumpBytes, new CompressionStream(streamFormat));
6363
- const bodySha256 = await sha256Hex2(body);
6364
6695
  const publicEnvelope = await vault.getPublicEnvelope();
6365
- const header = {
6366
- formatVersion: NOYDB_BUNDLE_FORMAT_VERSION,
6696
+ return assembleBundleContainer({
6367
6697
  handle,
6368
- bodyBytes: body.length,
6369
- bodySha256,
6370
- ...publicEnvelope !== void 0 ? { publicEnvelope } : {},
6371
- ...autoUnlockMode !== null ? { autoUnlock: autoUnlockMode } : {}
6372
- };
6373
- const headerBytes = encodeBundleHeader(header);
6374
- const prefix = new Uint8Array(NOYDB_BUNDLE_PREFIX_BYTES);
6375
- prefix.set(NOYDB_BUNDLE_MAGIC, 0);
6376
- prefix[4] = (streamFormat === null ? 0 : FLAG_COMPRESSED) | FLAG_HAS_INTEGRITY_HASH;
6377
- prefix[5] = format;
6378
- writeUint32BE(prefix, 6, headerBytes.length);
6379
- return concatBytes([prefix, headerBytes, body]);
6698
+ bodyJsonStr,
6699
+ compression: opts.compression,
6700
+ headerExtras: {
6701
+ ...publicEnvelope !== void 0 ? { publicEnvelope } : {},
6702
+ ...autoUnlockMode !== null ? { autoUnlock: autoUnlockMode } : {}
6703
+ }
6704
+ });
6380
6705
  }
6381
6706
  function parsePrefixAndHeader(bytes) {
6382
6707
  if (!hasNoydbBundleMagic(bytes)) {
@@ -6737,7 +7062,7 @@ var CollectionInstant = class {
6737
7062
  for (const e of entries) {
6738
7063
  if (e.collection !== this.name || e.id !== id) continue;
6739
7064
  if (e.ts > this.targetTs) break;
6740
- if (e.op === "amendment") continue;
7065
+ if (e.op === "amendment" || e.op === "lifecycle") continue;
6741
7066
  latest = { op: e.op, version: e.version };
6742
7067
  }
6743
7068
  if (!latest) return null;
@@ -8926,6 +9251,81 @@ var MemorySealingKeyProvider = class {
8926
9251
  return out;
8927
9252
  }
8928
9253
  };
9254
+ var MemoryRecipientSealer = class {
9255
+ id;
9256
+ keypair;
9257
+ constructor(opts) {
9258
+ this.id = opts.id;
9259
+ this.keypair = crypto.subtle.generateKey(
9260
+ { name: "RSA-OAEP", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },
9261
+ true,
9262
+ ["encrypt", "decrypt"]
9263
+ );
9264
+ }
9265
+ async publishRecipientHint() {
9266
+ const { publicKey } = await this.keypair;
9267
+ const spki = await crypto.subtle.exportKey("spki", publicKey);
9268
+ const pem = "-----BEGIN PUBLIC KEY-----\n" + bytesToBase644(new Uint8Array(spki)).match(/.{1,64}/g).join("\n") + "\n-----END PUBLIC KEY-----\n";
9269
+ return { v: 1, pid: this.id, alg: "rsa-oaep-sha256", material: { publicKeyPem: pem } };
9270
+ }
9271
+ async sealForRecipient(plaintext, hint) {
9272
+ if (hint.v !== 1) {
9273
+ throw new Error(`MemoryRecipientSealer.sealForRecipient: unsupported hint.v ${String(hint.v)} (expected 1)`);
9274
+ }
9275
+ if (hint.alg !== "rsa-oaep-sha256") {
9276
+ throw new Error(`MemoryRecipientSealer.sealForRecipient: unsupported hint.alg '${String(hint.alg)}' (expected 'rsa-oaep-sha256')`);
9277
+ }
9278
+ const pem = hint.material["publicKeyPem"];
9279
+ if (typeof pem !== "string") {
9280
+ throw new Error("MemoryRecipientSealer.sealForRecipient: hint.material.publicKeyPem missing or not a string");
9281
+ }
9282
+ const b64 = pem.replace(/-----BEGIN PUBLIC KEY-----/, "").replace(/-----END PUBLIC KEY-----/, "").replace(/\s+/g, "");
9283
+ const spki = base64ToBytes3(b64);
9284
+ const recipientPub = await crypto.subtle.importKey(
9285
+ "spki",
9286
+ spki,
9287
+ { name: "RSA-OAEP", hash: "SHA-256" },
9288
+ false,
9289
+ ["encrypt"]
9290
+ );
9291
+ const cekBytes = crypto.getRandomValues(new Uint8Array(32));
9292
+ const cek = await crypto.subtle.importKey("raw", cekBytes, "AES-GCM", false, ["encrypt"]);
9293
+ const iv = crypto.getRandomValues(new Uint8Array(12));
9294
+ const ct = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cek, plaintext));
9295
+ const wrapped = new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP" }, recipientPub, cekBytes));
9296
+ cekBytes.fill(0);
9297
+ if (wrapped.length !== 256) {
9298
+ throw new Error(`MemoryRecipientSealer.sealForRecipient: expected 256-byte RSA-OAEP wrap, got ${wrapped.length}`);
9299
+ }
9300
+ const out = new Uint8Array(1 + 256 + 12 + ct.length);
9301
+ out[0] = 1;
9302
+ out.set(wrapped, 1);
9303
+ out.set(iv, 1 + 256);
9304
+ out.set(ct, 1 + 256 + 12);
9305
+ return out;
9306
+ }
9307
+ async seal(plaintext) {
9308
+ const hint = await this.publishRecipientHint();
9309
+ return this.sealForRecipient(plaintext, hint);
9310
+ }
9311
+ async unseal(bytes) {
9312
+ if (bytes.length < 1 + 256 + 12 + 16) {
9313
+ throw new Error("MemoryRecipientSealer.unseal: sealed input too short");
9314
+ }
9315
+ if (bytes[0] !== 1) {
9316
+ throw new Error(`MemoryRecipientSealer.unseal: unknown TLV version ${bytes[0]}`);
9317
+ }
9318
+ const wrapped = bytes.subarray(1, 1 + 256);
9319
+ const iv = bytes.subarray(1 + 256, 1 + 256 + 12);
9320
+ const ct = bytes.subarray(1 + 256 + 12);
9321
+ const { privateKey } = await this.keypair;
9322
+ const cekBytes = new Uint8Array(await crypto.subtle.decrypt({ name: "RSA-OAEP" }, privateKey, wrapped));
9323
+ const cek = await crypto.subtle.importKey("raw", cekBytes, "AES-GCM", false, ["decrypt"]);
9324
+ const pt = new Uint8Array(await crypto.subtle.decrypt({ name: "AES-GCM", iv }, cek, ct));
9325
+ cekBytes.fill(0);
9326
+ return pt;
9327
+ }
9328
+ };
8929
9329
  var SEALED_PASSPHRASE_RECORD_ID = "sealed-passphrase";
8930
9330
  function bytesToBase644(bytes) {
8931
9331
  let binary = "";
@@ -15377,6 +15777,12 @@ var Vault = class {
15377
15777
  * `vault.compact()`. Indexed by collection name.
15378
15778
  */
15379
15779
  blobFieldsRegistry = /* @__PURE__ */ new Map();
15780
+ /**
15781
+ * Per-collection attestation field-schema (issue side). Populated on
15782
+ * `collection({ attestation })` and read by `issueAttestation()`.
15783
+ * Indexed by collection name.
15784
+ */
15785
+ attestationRegistry = /* @__PURE__ */ new Map();
15380
15786
  /**
15381
15787
  * Per-vault ledger store. Lazy-initialized on first
15382
15788
  * `collection()` call (which passes it through to the Collection)
@@ -15578,6 +15984,9 @@ var Vault = class {
15578
15984
  if (options?.blobFields) {
15579
15985
  this.blobFieldsRegistry.set(collectionName, options.blobFields);
15580
15986
  }
15987
+ if (options?.attestation !== void 0) {
15988
+ this.attestationRegistry.set(collectionName, options.attestation);
15989
+ }
15581
15990
  if (options?.dictKeyFields) {
15582
15991
  const dictFieldMap = {};
15583
15992
  for (const [field, desc] of Object.entries(options.dictKeyFields)) {
@@ -15636,7 +16045,6 @@ var Vault = class {
15636
16045
  } : {},
15637
16046
  ...this.materializedViewRegistry !== null ? {
15638
16047
  materializedViewSource: {
15639
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15640
16048
  registry: () => this.materializedViewRegistry,
15641
16049
  getCollection: (name) => this.collection(name),
15642
16050
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
@@ -16032,6 +16440,66 @@ var Vault = class {
16032
16440
  options
16033
16441
  );
16034
16442
  }
16443
+ async issueAttestation(collectionName, id) {
16444
+ const fieldSchema = this.attestationRegistry.get(collectionName);
16445
+ if (!fieldSchema) {
16446
+ throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
16447
+ }
16448
+ const { issueAttestationCore: issueAttestationCore2 } = await Promise.resolve().then(() => (init_issue(), issue_exports));
16449
+ const out = await issueAttestationCore2(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
16450
+ return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
16451
+ }
16452
+ async getDocumentSigningPublicKey() {
16453
+ const { loadSigner: loadSigner2, loadOrCreateSigner: loadOrCreateSigner2 } = await Promise.resolve().then(() => (init_signer(), signer_exports));
16454
+ const existing = await loadSigner2(this.adapter, this.name, this.getDEK);
16455
+ if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
16456
+ if (this.keyring.role !== "owner") {
16457
+ throw new AttestationError(`getDocumentSigningPublicKey: no document-signing key exists yet; only the 'owner' may mint it. Caller is '${this.keyring.role}'. Have the owner issue an attestation (or call this) first.`);
16458
+ }
16459
+ const signer = await loadOrCreateSigner2(this.adapter, this.name, this.getDEK);
16460
+ return { keyId: signer.keyId, publicKeyB64: signer.publicKeyB64 };
16461
+ }
16462
+ makeIssueContext() {
16463
+ const adapter = this.adapter, vaultName = this.name, getDEK = this.getDEK;
16464
+ return {
16465
+ store: adapter,
16466
+ vault: vaultName,
16467
+ role: this.keyring.role,
16468
+ getDEK: async () => getDEK("_attestations"),
16469
+ readRecord: async (collection, recId) => {
16470
+ const env = await adapter.get(vaultName, collection, recId);
16471
+ if (!env) return null;
16472
+ const record = await this.collection(collection).get(recId, { locale: "raw" });
16473
+ if (record === null) return null;
16474
+ return { record, version: env._v };
16475
+ }
16476
+ };
16477
+ }
16478
+ async revokeAttestation(docId) {
16479
+ const { revokeDocCore: revokeDocCore2 } = await Promise.resolve().then(() => (init_revoke(), revoke_exports));
16480
+ await revokeDocCore2(this.makeRevokeContext(), docId);
16481
+ }
16482
+ async unrevokeAttestation(docId) {
16483
+ const { unrevokeDocCore: unrevokeDocCore2 } = await Promise.resolve().then(() => (init_revoke(), revoke_exports));
16484
+ await unrevokeDocCore2(this.makeRevokeContext(), docId);
16485
+ }
16486
+ async getRevokedDocIds() {
16487
+ const { getRevokedDocIdsCore: getRevokedDocIdsCore2 } = await Promise.resolve().then(() => (init_revoke(), revoke_exports));
16488
+ return getRevokedDocIdsCore2(this.makeRevokeContext());
16489
+ }
16490
+ async publishRevocationList() {
16491
+ const { publishRevocationListCore: publishRevocationListCore2 } = await Promise.resolve().then(() => (init_revoke(), revoke_exports));
16492
+ return publishRevocationListCore2(this.makeRevokeContext());
16493
+ }
16494
+ makeRevokeContext() {
16495
+ const adapter = this.adapter, vaultName = this.name, getDEK = this.getDEK;
16496
+ return {
16497
+ store: adapter,
16498
+ vault: vaultName,
16499
+ role: this.keyring.role,
16500
+ getDEK: async () => getDEK("_attestations")
16501
+ };
16502
+ }
16035
16503
  async writeExportAudit(entry) {
16036
16504
  const json = JSON.stringify(entry);
16037
16505
  const envelope = this.encrypted ? await (async () => {
@@ -17355,7 +17823,7 @@ var Vault = class {
17355
17823
  for (let i = allEntries.length - 1; i >= 0; i--) {
17356
17824
  const entry = allEntries[i];
17357
17825
  if (!entry) continue;
17358
- if (entry.op === "amendment") continue;
17826
+ if (entry.op === "amendment" || entry.op === "lifecycle") continue;
17359
17827
  const key = `${entry.collection}/${entry.id}`;
17360
17828
  if (seen.has(key)) continue;
17361
17829
  seen.add(key);
@@ -21557,6 +22025,7 @@ function shortJSON(value) {
21557
22025
  Aggregation,
21558
22026
  AlreadyElevatedError,
21559
22027
  AmendmentForbiddenError,
22028
+ AttestationError,
21560
22029
  BLOB_CHUNKS_COLLECTION,
21561
22030
  BLOB_COLLECTION,
21562
22031
  BLOB_INDEX_COLLECTION,
@@ -21630,6 +22099,7 @@ function shortJSON(value) {
21630
22099
  MaterializedViewCycleError,
21631
22100
  MaterializedViewSourceUnknownError,
21632
22101
  MaterializedViewTooLargeError,
22102
+ MemoryRecipientSealer,
21633
22103
  MemorySealingKeyProvider,
21634
22104
  MissingTranslationError,
21635
22105
  NOYDB_BACKUP_VERSION,