keri-ts 2.0.1 → 2.2.0

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 (450) hide show
  1. package/README.md +30 -2
  2. package/esm/keri/npm/src/acdc/authoring.js +195 -0
  3. package/esm/keri/npm/src/acdc/chaining.js +223 -89
  4. package/esm/keri/npm/src/acdc/custody.js +164 -0
  5. package/esm/keri/npm/src/acdc/dhking.js +244 -32
  6. package/esm/keri/npm/src/acdc/observing.js +2 -2
  7. package/esm/keri/npm/src/acdc/regbasing.js +30 -29
  8. package/esm/keri/npm/src/acdc/regengine.js +4 -6
  9. package/esm/keri/npm/src/acdc/registering.js +13 -10
  10. package/esm/keri/npm/src/acdc/registraring.js +4 -9
  11. package/esm/keri/npm/src/acdc/salting.js +143 -26
  12. package/esm/keri/npm/src/acdc/scheming.js +93 -54
  13. package/esm/keri/npm/src/acdc/unblinding.js +120 -99
  14. package/esm/keri/npm/src/app/bootstrap/authenticating.js +4 -6
  15. package/esm/keri/npm/src/app/bootstrap/oobi-resolving.js +41 -0
  16. package/esm/keri/npm/src/app/bootstrap/oobiery.js +5 -7
  17. package/esm/keri/npm/src/app/credentials/credential-revoking.js +1 -0
  18. package/esm/keri/npm/src/app/credentials/credential-workflows.js +2 -0
  19. package/esm/keri/npm/src/app/credentials/registry-settling.js +44 -0
  20. package/esm/keri/npm/src/app/credentials/root-replicating.js +131 -0
  21. package/esm/keri/npm/src/app/credentials/root-replicator.js +198 -0
  22. package/esm/keri/npm/src/app/credentials/tel-completion.js +36 -0
  23. package/esm/keri/npm/src/app/credentials/verifying.js +12 -3
  24. package/esm/keri/npm/src/app/delivery/forwarding.js +64 -9
  25. package/esm/keri/npm/src/app/exchanges/exchanging.js +24 -15
  26. package/esm/keri/npm/src/app/identity/challenging.js +50 -0
  27. package/esm/keri/npm/src/app/identity/configing.js +17 -43
  28. package/esm/keri/npm/src/app/identity/delegating.js +77 -77
  29. package/esm/keri/npm/src/app/identity/delegation-approval.js +333 -0
  30. package/esm/keri/npm/src/app/identity/event-completion.js +154 -0
  31. package/esm/keri/npm/src/app/identity/habbing.js +183 -41
  32. package/esm/keri/npm/src/app/identity/keeping.js +78 -5
  33. package/esm/keri/npm/src/app/identity/lmdb-habery.js +12 -0
  34. package/esm/keri/npm/src/app/ipex/group-ipex.js +327 -0
  35. package/esm/keri/npm/src/app/ipex/group-issuance.js +902 -0
  36. package/esm/keri/npm/src/app/ipex/ipex-admitting.js +120 -0
  37. package/esm/keri/npm/src/app/ipex/ipex-conversation.js +197 -0
  38. package/esm/keri/npm/src/app/ipex/ipex-discloser.js +591 -0
  39. package/esm/keri/npm/src/app/ipex/ipex-granting.js +93 -0
  40. package/esm/keri/npm/src/app/ipex/ipex-graph.js +7 -70
  41. package/esm/keri/npm/src/app/ipex/ipex-grouping.js +42 -16
  42. package/esm/keri/npm/src/app/ipex/ipex-v2.js +21 -5
  43. package/esm/keri/npm/src/app/ipex/ipexing.js +1 -1
  44. package/esm/keri/npm/src/app/ipex/issuance.js +888 -0
  45. package/esm/keri/npm/src/app/ipex/pending-presentations.js +46 -0
  46. package/esm/keri/npm/src/app/ipex/presentation-files.js +200 -0
  47. package/esm/keri/npm/src/app/ipex/presenting.js +401 -0
  48. package/esm/keri/npm/src/app/ipex/receive-issuance.js +86 -0
  49. package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +660 -0
  50. package/esm/keri/npm/src/app/mailbox/ipex-arrival.js +103 -0
  51. package/esm/keri/npm/src/app/mailbox/kel-publisher.js +322 -0
  52. package/esm/keri/npm/src/app/mailbox/kel-publishing.js +65 -0
  53. package/esm/keri/npm/src/app/mailbox/kel-submission.js +24 -0
  54. package/esm/keri/npm/src/app/mailbox/mailbox-admin.js +208 -0
  55. package/esm/keri/npm/src/app/mailbox/mailbox-poller.js +212 -47
  56. package/esm/keri/npm/src/app/mailbox/mailboxing.js +15 -14
  57. package/esm/keri/npm/src/app/multisig/counseling.js +482 -0
  58. package/esm/keri/npm/src/app/multisig/group-members.js +32 -0
  59. package/esm/keri/npm/src/app/multisig/grouping.js +4 -3
  60. package/esm/keri/npm/src/app/multisig/multisig-workflows.js +101 -141
  61. package/esm/keri/npm/src/app/multisig/proposals.js +281 -0
  62. package/esm/keri/npm/src/app/multisig/proposing.js +122 -0
  63. package/esm/keri/npm/src/app/notifications/notifying.js +5 -9
  64. package/esm/keri/npm/src/app/notifications/signaling.js +5 -5
  65. package/esm/keri/npm/src/app/protocol/parsering.js +26 -1
  66. package/esm/keri/npm/src/app/protocol/protocol-processing.js +44 -6
  67. package/esm/keri/npm/src/app/queries/query-workflows.js +98 -0
  68. package/esm/keri/npm/src/app/queries/witness-inquisitor.js +2 -2
  69. package/esm/keri/npm/src/app/runtime/agent-runtime.js +113 -65
  70. package/esm/keri/npm/src/app/runtime/cue-runtime.js +3 -6
  71. package/esm/keri/npm/src/app/runtime/delivery-outbox.js +87 -0
  72. package/esm/keri/npm/src/app/runtime/doing.js +17 -0
  73. package/esm/keri/npm/src/app/runtime/ipex-auxiliaries.js +207 -0
  74. package/esm/keri/npm/src/app/runtime/operation-owners.js +151 -0
  75. package/esm/keri/npm/src/app/runtime/retry-backoff.js +93 -0
  76. package/esm/keri/npm/src/app/runtime/workflow-contract.js +80 -0
  77. package/esm/keri/npm/src/app/transport/byte-source.js +6 -42
  78. package/esm/keri/npm/src/app/transport/cesr-egress.js +77 -13
  79. package/esm/keri/npm/src/app/transport/file-bytes.js +41 -0
  80. package/esm/keri/npm/src/app/transport/http-client.js +25 -6
  81. package/esm/keri/npm/src/app/transport/http-messenger.js +14 -9
  82. package/esm/keri/npm/src/app/transport/message-source.js +1 -1
  83. package/esm/keri/npm/src/app/transport/messengering.js +3 -4
  84. package/esm/keri/npm/src/app/transport/node-http-client.js +21 -0
  85. package/esm/keri/npm/src/app/transport/tcp-dialer.js +14 -0
  86. package/esm/keri/npm/src/app/witness/http-endpoints.js +4 -4
  87. package/esm/keri/npm/src/app/witness/receipt-client.js +2 -2
  88. package/esm/keri/npm/src/cli/common/context.js +2 -2
  89. package/esm/keri/npm/src/cli/common/event-completion.js +49 -0
  90. package/esm/keri/npm/src/cli/common/existing.js +3 -5
  91. package/esm/keri/npm/src/cli/common/runtime-workers.js +23 -0
  92. package/esm/keri/npm/src/cli/credentials/ipex.js +159 -191
  93. package/esm/keri/npm/src/cli/credentials/vc.js +53 -72
  94. package/esm/keri/npm/src/cli/endpoints/did.js +12 -3
  95. package/esm/keri/npm/src/cli/endpoints/oobi-clean.js +4 -3
  96. package/esm/keri/npm/src/cli/endpoints/oobi.js +12 -15
  97. package/esm/keri/npm/src/cli/identity/challenge.js +9 -35
  98. package/esm/keri/npm/src/cli/identity/delegate.js +81 -258
  99. package/esm/keri/npm/src/cli/identity/incept.js +17 -34
  100. package/esm/keri/npm/src/cli/identity/init.js +4 -3
  101. package/esm/keri/npm/src/cli/identity/interact.js +7 -19
  102. package/esm/keri/npm/src/cli/identity/rotate.js +10 -38
  103. package/esm/keri/npm/src/cli/index.js +3 -1
  104. package/esm/keri/npm/src/cli/messaging/exchange.js +2 -2
  105. package/esm/keri/npm/src/cli/messaging/group-join.js +79 -0
  106. package/esm/keri/npm/src/cli/messaging/group-wait.js +88 -0
  107. package/esm/keri/npm/src/cli/messaging/multisig.js +187 -250
  108. package/esm/keri/npm/src/cli/messaging/root-copy-lines.js +31 -0
  109. package/esm/keri/npm/src/cli/tools/annotate.js +2 -1
  110. package/esm/keri/npm/src/cli/tools/benchmark.js +2 -1
  111. package/esm/keri/npm/src/cli/tools/db-dump.js +1 -4
  112. package/esm/keri/npm/src/core/bytes.js +9 -0
  113. package/esm/keri/npm/src/core/kel/delegation-ancestry.js +92 -0
  114. package/esm/keri/npm/src/core/kel/eventing.js +67 -12
  115. package/esm/keri/npm/src/core/kel/kever.js +11 -9
  116. package/esm/keri/npm/src/core/mailbox/kram-policy.js +41 -9
  117. package/esm/keri/npm/src/core/mailbox/kram-pruning.js +15 -22
  118. package/esm/keri/npm/src/core/mailbox/kram-staging.js +2 -2
  119. package/esm/keri/npm/src/core/mailbox/kraming.js +2 -0
  120. package/esm/keri/npm/src/core/records.js +23 -0
  121. package/esm/keri/npm/src/core/routing.js +15 -2
  122. package/esm/keri/npm/src/db/basing.js +183 -205
  123. package/esm/keri/npm/src/db/core/dber.js +1062 -0
  124. package/esm/keri/npm/src/db/core/index.js +4 -2
  125. package/esm/keri/npm/src/db/core/indexeddb-persistence.js +221 -0
  126. package/esm/keri/npm/src/db/core/lmdb-opener.js +30 -0
  127. package/esm/keri/npm/src/db/core/lmdber.js +199 -1067
  128. package/esm/keri/npm/src/db/core/memstore.js +532 -0
  129. package/esm/keri/npm/src/db/core/path-manager.js +109 -223
  130. package/esm/keri/npm/src/db/core/store-owner.js +104 -0
  131. package/esm/keri/npm/src/db/core/webdber.js +252 -0
  132. package/esm/keri/npm/src/db/escrowing.js +2 -2
  133. package/esm/keri/npm/src/db/exchange/exchange-nests.js +3 -2
  134. package/esm/keri/npm/src/db/indexeddb.js +98 -0
  135. package/esm/keri/npm/src/db/keeping.js +38 -123
  136. package/esm/keri/npm/src/db/koming.js +1 -1
  137. package/esm/keri/npm/src/db/lmdb-stores.js +68 -0
  138. package/esm/keri/npm/src/db/lmdb.js +6 -0
  139. package/esm/keri/npm/src/db/mailbox/mailboxing.js +12 -65
  140. package/esm/keri/npm/src/db/noting.js +11 -55
  141. package/esm/keri/npm/src/db/reger.js +43 -105
  142. package/esm/keri/npm/src/db/replay/witness-replay.js +2 -20
  143. package/esm/keri/npm/src/db/store-lock.js +150 -0
  144. package/esm/keri/npm/src/db/subing.js +1 -1
  145. package/esm/keri/npm/src/npm/db-indexeddb.browser.js +2 -0
  146. package/esm/keri/npm/src/npm/db-indexeddb.js +3 -0
  147. package/esm/keri/npm/src/npm/db-lmdb.js +3 -0
  148. package/esm/keri/npm/src/npm/db.browser.js +2 -0
  149. package/esm/keri/npm/src/npm/index.browser.js +9 -0
  150. package/esm/keri/npm/src/npm/runtime-node.js +3 -0
  151. package/esm/keri/npm/src/npm/runtime-web.browser.js +2 -0
  152. package/esm/keri/npm/src/npm/runtime-web.js +3 -0
  153. package/esm/keri/npm/src/npm/runtime.browser.js +2 -0
  154. package/esm/keri/npm/src/runtime/index.js +58 -12
  155. package/esm/keri/npm/src/runtime/node.js +14 -0
  156. package/esm/keri/npm/src/runtime/web/output-barrier.js +47 -0
  157. package/esm/keri/npm/src/runtime/web/persistent-storage.js +37 -0
  158. package/esm/keri/npm/src/runtime/web.js +10 -0
  159. package/esm/keri/npm/src/vdr/eventing.js +1 -1
  160. package/esm/keri/npm/src/vdr/tel-publication.js +19 -3
  161. package/esm/keri/npm/src/version.js +2 -2
  162. package/package.json +24 -4
  163. package/types/acdc/authoring.d.ts +54 -0
  164. package/types/acdc/authoring.d.ts.map +1 -0
  165. package/types/acdc/chaining.d.ts +56 -6
  166. package/types/acdc/chaining.d.ts.map +1 -1
  167. package/types/acdc/custody.d.ts +77 -0
  168. package/types/acdc/custody.d.ts.map +1 -0
  169. package/types/acdc/dhking.d.ts +94 -3
  170. package/types/acdc/dhking.d.ts.map +1 -1
  171. package/types/acdc/regbasing.d.ts +11 -6
  172. package/types/acdc/regbasing.d.ts.map +1 -1
  173. package/types/acdc/regengine.d.ts.map +1 -1
  174. package/types/acdc/registering.d.ts +8 -4
  175. package/types/acdc/registering.d.ts.map +1 -1
  176. package/types/acdc/registraring.d.ts.map +1 -1
  177. package/types/acdc/salting.d.ts +59 -7
  178. package/types/acdc/salting.d.ts.map +1 -1
  179. package/types/acdc/scheming.d.ts +2 -0
  180. package/types/acdc/scheming.d.ts.map +1 -1
  181. package/types/acdc/unblinding.d.ts +58 -19
  182. package/types/acdc/unblinding.d.ts.map +1 -1
  183. package/types/app/bootstrap/authenticating.d.ts +3 -1
  184. package/types/app/bootstrap/authenticating.d.ts.map +1 -1
  185. package/types/app/bootstrap/oobi-resolving.d.ts +92 -0
  186. package/types/app/bootstrap/oobi-resolving.d.ts.map +1 -0
  187. package/types/app/bootstrap/oobiery.d.ts +3 -1
  188. package/types/app/bootstrap/oobiery.d.ts.map +1 -1
  189. package/types/app/credentials/credential-revoking.d.ts +3 -0
  190. package/types/app/credentials/credential-revoking.d.ts.map +1 -1
  191. package/types/app/credentials/credential-workflows.d.ts +5 -0
  192. package/types/app/credentials/credential-workflows.d.ts.map +1 -1
  193. package/types/app/credentials/registry-settling.d.ts +85 -0
  194. package/types/app/credentials/registry-settling.d.ts.map +1 -0
  195. package/types/app/credentials/root-replicating.d.ts +97 -0
  196. package/types/app/credentials/root-replicating.d.ts.map +1 -0
  197. package/types/app/credentials/root-replicator.d.ts +105 -0
  198. package/types/app/credentials/root-replicator.d.ts.map +1 -0
  199. package/types/app/credentials/tel-completion.d.ts +55 -0
  200. package/types/app/credentials/tel-completion.d.ts.map +1 -0
  201. package/types/app/credentials/verifying.d.ts +2 -1
  202. package/types/app/credentials/verifying.d.ts.map +1 -1
  203. package/types/app/delivery/forwarding.d.ts +16 -0
  204. package/types/app/delivery/forwarding.d.ts.map +1 -1
  205. package/types/app/exchanges/exchanging.d.ts +2 -0
  206. package/types/app/exchanges/exchanging.d.ts.map +1 -1
  207. package/types/app/identity/challenging.d.ts +54 -0
  208. package/types/app/identity/challenging.d.ts.map +1 -1
  209. package/types/app/identity/configing.d.ts +7 -5
  210. package/types/app/identity/configing.d.ts.map +1 -1
  211. package/types/app/identity/delegating.d.ts +21 -4
  212. package/types/app/identity/delegating.d.ts.map +1 -1
  213. package/types/app/identity/delegation-approval.d.ts +228 -0
  214. package/types/app/identity/delegation-approval.d.ts.map +1 -0
  215. package/types/app/identity/event-completion.d.ts +151 -0
  216. package/types/app/identity/event-completion.d.ts.map +1 -0
  217. package/types/app/identity/habbing.d.ts +90 -7
  218. package/types/app/identity/habbing.d.ts.map +1 -1
  219. package/types/app/identity/keeping.d.ts +50 -4
  220. package/types/app/identity/keeping.d.ts.map +1 -1
  221. package/types/app/identity/lmdb-habery.d.ts +6 -0
  222. package/types/app/identity/lmdb-habery.d.ts.map +1 -0
  223. package/types/app/ipex/group-ipex.d.ts +247 -0
  224. package/types/app/ipex/group-ipex.d.ts.map +1 -0
  225. package/types/app/ipex/group-issuance.d.ts +281 -0
  226. package/types/app/ipex/group-issuance.d.ts.map +1 -0
  227. package/types/app/ipex/ipex-admitting.d.ts +47 -0
  228. package/types/app/ipex/ipex-admitting.d.ts.map +1 -0
  229. package/types/app/ipex/ipex-conversation.d.ts +195 -0
  230. package/types/app/ipex/ipex-conversation.d.ts.map +1 -0
  231. package/types/app/ipex/ipex-discloser.d.ts +156 -0
  232. package/types/app/ipex/ipex-discloser.d.ts.map +1 -0
  233. package/types/app/ipex/ipex-granting.d.ts +145 -0
  234. package/types/app/ipex/ipex-granting.d.ts.map +1 -0
  235. package/types/app/ipex/ipex-graph.d.ts +4 -4
  236. package/types/app/ipex/ipex-graph.d.ts.map +1 -1
  237. package/types/app/ipex/ipex-grouping.d.ts +18 -0
  238. package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
  239. package/types/app/ipex/ipex-v2.d.ts +11 -2
  240. package/types/app/ipex/ipex-v2.d.ts.map +1 -1
  241. package/types/app/ipex/ipexing.d.ts +3 -0
  242. package/types/app/ipex/ipexing.d.ts.map +1 -1
  243. package/types/app/ipex/issuance.d.ts +443 -0
  244. package/types/app/ipex/issuance.d.ts.map +1 -0
  245. package/types/app/ipex/pending-presentations.d.ts +25 -0
  246. package/types/app/ipex/pending-presentations.d.ts.map +1 -0
  247. package/types/app/ipex/presentation-files.d.ts +47 -0
  248. package/types/app/ipex/presentation-files.d.ts.map +1 -0
  249. package/types/app/ipex/presenting.d.ts +298 -0
  250. package/types/app/ipex/presenting.d.ts.map +1 -0
  251. package/types/app/ipex/receive-issuance.d.ts +99 -0
  252. package/types/app/ipex/receive-issuance.d.ts.map +1 -0
  253. package/types/app/ipex/unblinding-workflow.d.ts +255 -0
  254. package/types/app/ipex/unblinding-workflow.d.ts.map +1 -0
  255. package/types/app/mailbox/ipex-arrival.d.ts +104 -0
  256. package/types/app/mailbox/ipex-arrival.d.ts.map +1 -0
  257. package/types/app/mailbox/kel-publisher.d.ts +141 -0
  258. package/types/app/mailbox/kel-publisher.d.ts.map +1 -0
  259. package/types/app/mailbox/kel-publishing.d.ts +70 -0
  260. package/types/app/mailbox/kel-publishing.d.ts.map +1 -0
  261. package/types/app/mailbox/kel-submission.d.ts +18 -0
  262. package/types/app/mailbox/kel-submission.d.ts.map +1 -0
  263. package/types/app/mailbox/mailbox-admin.d.ts +113 -0
  264. package/types/app/mailbox/mailbox-admin.d.ts.map +1 -0
  265. package/types/app/mailbox/mailbox-poller.d.ts +92 -3
  266. package/types/app/mailbox/mailbox-poller.d.ts.map +1 -1
  267. package/types/app/mailbox/mailboxing.d.ts +4 -1
  268. package/types/app/mailbox/mailboxing.d.ts.map +1 -1
  269. package/types/app/multisig/counseling.d.ts +196 -0
  270. package/types/app/multisig/counseling.d.ts.map +1 -0
  271. package/types/app/multisig/group-members.d.ts +20 -0
  272. package/types/app/multisig/group-members.d.ts.map +1 -1
  273. package/types/app/multisig/grouping.d.ts +39 -20
  274. package/types/app/multisig/grouping.d.ts.map +1 -1
  275. package/types/app/multisig/multisig-workflows.d.ts +93 -23
  276. package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
  277. package/types/app/multisig/proposals.d.ts +129 -0
  278. package/types/app/multisig/proposals.d.ts.map +1 -0
  279. package/types/app/multisig/proposing.d.ts +125 -0
  280. package/types/app/multisig/proposing.d.ts.map +1 -0
  281. package/types/app/notifications/notifying.d.ts +1 -1
  282. package/types/app/notifications/notifying.d.ts.map +1 -1
  283. package/types/app/notifications/signaling.d.ts +3 -1
  284. package/types/app/notifications/signaling.d.ts.map +1 -1
  285. package/types/app/protocol/parsering.d.ts +16 -1
  286. package/types/app/protocol/parsering.d.ts.map +1 -1
  287. package/types/app/protocol/protocol-processing.d.ts +9 -1
  288. package/types/app/protocol/protocol-processing.d.ts.map +1 -1
  289. package/types/app/queries/query-workflows.d.ts +98 -0
  290. package/types/app/queries/query-workflows.d.ts.map +1 -0
  291. package/types/app/runtime/agent-runtime.d.ts +79 -25
  292. package/types/app/runtime/agent-runtime.d.ts.map +1 -1
  293. package/types/app/runtime/cue-runtime.d.ts +2 -1
  294. package/types/app/runtime/cue-runtime.d.ts.map +1 -1
  295. package/types/app/runtime/delivery-outbox.d.ts +68 -0
  296. package/types/app/runtime/delivery-outbox.d.ts.map +1 -0
  297. package/types/app/runtime/doing.d.ts +27 -0
  298. package/types/app/runtime/doing.d.ts.map +1 -0
  299. package/types/app/runtime/ipex-auxiliaries.d.ts +74 -0
  300. package/types/app/runtime/ipex-auxiliaries.d.ts.map +1 -0
  301. package/types/app/runtime/operation-owners.d.ts +137 -0
  302. package/types/app/runtime/operation-owners.d.ts.map +1 -0
  303. package/types/app/runtime/retry-backoff.d.ts +49 -0
  304. package/types/app/runtime/retry-backoff.d.ts.map +1 -0
  305. package/types/app/runtime/workflow-contract.d.ts +79 -0
  306. package/types/app/runtime/workflow-contract.d.ts.map +1 -0
  307. package/types/app/transport/byte-source.d.ts +13 -10
  308. package/types/app/transport/byte-source.d.ts.map +1 -1
  309. package/types/app/transport/cesr-egress.d.ts +21 -7
  310. package/types/app/transport/cesr-egress.d.ts.map +1 -1
  311. package/types/app/transport/file-bytes.d.ts +11 -0
  312. package/types/app/transport/file-bytes.d.ts.map +1 -0
  313. package/types/app/transport/http-client.d.ts +3 -0
  314. package/types/app/transport/http-client.d.ts.map +1 -1
  315. package/types/app/transport/http-messenger.d.ts +15 -10
  316. package/types/app/transport/http-messenger.d.ts.map +1 -1
  317. package/types/app/transport/message-source.d.ts +1 -1
  318. package/types/app/transport/messengering.d.ts +2 -2
  319. package/types/app/transport/messengering.d.ts.map +1 -1
  320. package/types/app/transport/node-http-client.d.ts +10 -0
  321. package/types/app/transport/node-http-client.d.ts.map +1 -0
  322. package/types/app/transport/tcp-dialer.d.ts +21 -0
  323. package/types/app/transport/tcp-dialer.d.ts.map +1 -0
  324. package/types/cli/common/event-completion.d.ts +26 -0
  325. package/types/cli/common/event-completion.d.ts.map +1 -0
  326. package/types/cli/common/existing.d.ts.map +1 -1
  327. package/types/cli/common/runtime-workers.d.ts +23 -0
  328. package/types/cli/common/runtime-workers.d.ts.map +1 -0
  329. package/types/cli/credentials/ipex.d.ts.map +1 -1
  330. package/types/cli/credentials/vc.d.ts +1 -1
  331. package/types/cli/credentials/vc.d.ts.map +1 -1
  332. package/types/cli/endpoints/did.d.ts.map +1 -1
  333. package/types/cli/endpoints/oobi-clean.d.ts.map +1 -1
  334. package/types/cli/endpoints/oobi.d.ts +3 -1
  335. package/types/cli/endpoints/oobi.d.ts.map +1 -1
  336. package/types/cli/identity/challenge.d.ts +1 -1
  337. package/types/cli/identity/challenge.d.ts.map +1 -1
  338. package/types/cli/identity/delegate.d.ts +14 -1
  339. package/types/cli/identity/delegate.d.ts.map +1 -1
  340. package/types/cli/identity/incept.d.ts.map +1 -1
  341. package/types/cli/identity/init.d.ts.map +1 -1
  342. package/types/cli/identity/interact.d.ts.map +1 -1
  343. package/types/cli/identity/rotate.d.ts.map +1 -1
  344. package/types/cli/index.d.ts +4 -2
  345. package/types/cli/index.d.ts.map +1 -1
  346. package/types/cli/messaging/group-join.d.ts +53 -0
  347. package/types/cli/messaging/group-join.d.ts.map +1 -0
  348. package/types/cli/messaging/group-wait.d.ts +34 -0
  349. package/types/cli/messaging/group-wait.d.ts.map +1 -0
  350. package/types/cli/messaging/multisig.d.ts +36 -4
  351. package/types/cli/messaging/multisig.d.ts.map +1 -1
  352. package/types/cli/messaging/root-copy-lines.d.ts +39 -0
  353. package/types/cli/messaging/root-copy-lines.d.ts.map +1 -0
  354. package/types/cli/tools/annotate.d.ts.map +1 -1
  355. package/types/cli/tools/benchmark.d.ts.map +1 -1
  356. package/types/cli/tools/db-dump.d.ts.map +1 -1
  357. package/types/core/bytes.d.ts +2 -0
  358. package/types/core/bytes.d.ts.map +1 -1
  359. package/types/core/cues.d.ts +11 -0
  360. package/types/core/cues.d.ts.map +1 -1
  361. package/types/core/kel/delegation-ancestry.d.ts +41 -0
  362. package/types/core/kel/delegation-ancestry.d.ts.map +1 -0
  363. package/types/core/kel/eventing.d.ts.map +1 -1
  364. package/types/core/kel/kever.d.ts +5 -4
  365. package/types/core/kel/kever.d.ts.map +1 -1
  366. package/types/core/mailbox/kram-policy.d.ts +14 -0
  367. package/types/core/mailbox/kram-policy.d.ts.map +1 -1
  368. package/types/core/mailbox/kram-pruning.d.ts +1 -3
  369. package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
  370. package/types/core/mailbox/kraming.d.ts +1 -1
  371. package/types/core/mailbox/kraming.d.ts.map +1 -1
  372. package/types/core/records.d.ts +61 -0
  373. package/types/core/records.d.ts.map +1 -1
  374. package/types/core/routing.d.ts +6 -0
  375. package/types/core/routing.d.ts.map +1 -1
  376. package/types/db/basing.d.ts +22 -25
  377. package/types/db/basing.d.ts.map +1 -1
  378. package/types/db/core/dber.d.ts +505 -0
  379. package/types/db/core/dber.d.ts.map +1 -0
  380. package/types/db/core/index.d.ts +4 -2
  381. package/types/db/core/index.d.ts.map +1 -1
  382. package/types/db/core/indexeddb-persistence.d.ts +59 -0
  383. package/types/db/core/indexeddb-persistence.d.ts.map +1 -0
  384. package/types/db/core/lmdb-opener.d.ts +17 -0
  385. package/types/db/core/lmdb-opener.d.ts.map +1 -0
  386. package/types/db/core/lmdber.d.ts +60 -383
  387. package/types/db/core/lmdber.d.ts.map +1 -1
  388. package/types/db/core/memstore.d.ts +129 -0
  389. package/types/db/core/memstore.d.ts.map +1 -0
  390. package/types/db/core/path-manager.d.ts +22 -45
  391. package/types/db/core/path-manager.d.ts.map +1 -1
  392. package/types/db/core/store-owner.d.ts +59 -0
  393. package/types/db/core/store-owner.d.ts.map +1 -0
  394. package/types/db/core/webdber.d.ts +127 -0
  395. package/types/db/core/webdber.d.ts.map +1 -0
  396. package/types/db/escrowing.d.ts +3 -3
  397. package/types/db/escrowing.d.ts.map +1 -1
  398. package/types/db/exchange/exchange-nests.d.ts.map +1 -1
  399. package/types/db/indexeddb.d.ts +37 -0
  400. package/types/db/indexeddb.d.ts.map +1 -0
  401. package/types/db/keeping.d.ts +14 -25
  402. package/types/db/keeping.d.ts.map +1 -1
  403. package/types/db/koming.d.ts +7 -8
  404. package/types/db/koming.d.ts.map +1 -1
  405. package/types/db/lmdb-stores.d.ts +45 -0
  406. package/types/db/lmdb-stores.d.ts.map +1 -0
  407. package/types/db/lmdb.d.ts +7 -0
  408. package/types/db/lmdb.d.ts.map +1 -0
  409. package/types/db/mailbox/mailboxing.d.ts +7 -21
  410. package/types/db/mailbox/mailboxing.d.ts.map +1 -1
  411. package/types/db/noting.d.ts +7 -12
  412. package/types/db/noting.d.ts.map +1 -1
  413. package/types/db/reger.d.ts +7 -11
  414. package/types/db/reger.d.ts.map +1 -1
  415. package/types/db/replay/witness-replay.d.ts +0 -2
  416. package/types/db/replay/witness-replay.d.ts.map +1 -1
  417. package/types/db/store-lock.d.ts +72 -0
  418. package/types/db/store-lock.d.ts.map +1 -0
  419. package/types/db/subing.d.ts +24 -25
  420. package/types/db/subing.d.ts.map +1 -1
  421. package/types/npm/db-indexeddb.d.ts +4 -0
  422. package/types/npm/db-indexeddb.d.ts.map +1 -0
  423. package/types/npm/db-lmdb.d.ts +4 -0
  424. package/types/npm/db-lmdb.d.ts.map +1 -0
  425. package/types/npm/runtime-node.d.ts +4 -0
  426. package/types/npm/runtime-node.d.ts.map +1 -0
  427. package/types/npm/runtime-web.d.ts +4 -0
  428. package/types/npm/runtime-web.d.ts.map +1 -0
  429. package/types/runtime/index.d.ts +48 -14
  430. package/types/runtime/index.d.ts.map +1 -1
  431. package/types/runtime/node.d.ts +15 -0
  432. package/types/runtime/node.d.ts.map +1 -0
  433. package/types/runtime/web/output-barrier.d.ts +30 -0
  434. package/types/runtime/web/output-barrier.d.ts.map +1 -0
  435. package/types/runtime/web/persistent-storage.d.ts +36 -0
  436. package/types/runtime/web/persistent-storage.d.ts.map +1 -0
  437. package/types/runtime/web.d.ts +11 -0
  438. package/types/runtime/web.d.ts.map +1 -0
  439. package/types/vdr/tel-publication.d.ts +6 -0
  440. package/types/vdr/tel-publication.d.ts.map +1 -1
  441. package/types/version.d.ts +2 -2
  442. package/esm/keri/npm/src/acdc/relating.js +0 -59
  443. package/esm/keri/npm/src/cli/common/tel-completion.js +0 -24
  444. package/esm/keri/npm/src/db/baser-defaults.js +0 -11
  445. package/types/acdc/relating.d.ts +0 -21
  446. package/types/acdc/relating.d.ts.map +0 -1
  447. package/types/cli/common/tel-completion.d.ts +0 -8
  448. package/types/cli/common/tel-completion.d.ts.map +0 -1
  449. package/types/db/baser-defaults.d.ts +0 -5
  450. package/types/db/baser-defaults.d.ts.map +0 -1
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Registry blind derivation over the Keeper's registry root.
3
+ *
4
+ * Issuing a blinded (BUP) registry update needs a deterministic opening. The
5
+ * root salt stays in the Keeper; this core derives openings from it and keeps
6
+ * only the public, event-specific coordinates in a `DerivedUpdateStore`. A
7
+ * runtime defaults to {@link BaserDerivedUpdateStore}; a wallet backs the port
8
+ * with its own table. The core opens no database of its own.
9
+ */
10
+ import { bytesEqual, makeBlindState, makeBoundState, MtrDex, Salter } from "cesr-ts";
11
+ import { ValidationError } from "../core/errors.js";
12
+ import { DerivedUpdateRecord } from "../core/records.js";
13
+ import { vetBlind } from "./regeventing.js";
14
+ /** Process-local store for a CLI or tests; a wallet backs the port with its own durable table. */
15
+ export class MemoryDerivedUpdateStore {
16
+ constructor() {
17
+ Object.defineProperty(this, "rows", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: new Map()
22
+ });
23
+ }
24
+ get(event) {
25
+ return this.rows.get(event) ?? null;
26
+ }
27
+ pin(event, value) {
28
+ this.rows.set(event, structuredClone(value));
29
+ }
30
+ }
31
+ /**
32
+ * Derivation coordinates kept in a registry environment's own database (`RegBaser.dvus`). The default of a
33
+ * runtime that supplies no store, so a server agent keeps them durably beside the registry events they
34
+ * describe. A wallet with its own table still passes that instead.
35
+ */
36
+ export class BaserDerivedUpdateStore {
37
+ constructor(baser) {
38
+ Object.defineProperty(this, "baser", {
39
+ enumerable: true,
40
+ configurable: true,
41
+ writable: true,
42
+ value: baser
43
+ });
44
+ }
45
+ get(event) {
46
+ const row = this.baser.dvus.get([event]);
47
+ return row ? { credential: row.credential, state: row.state, bound: row.bound } : null;
48
+ }
49
+ pin(event, value) {
50
+ this.baser.dvus.pin([event], new DerivedUpdateRecord(structuredClone(value)));
51
+ }
52
+ }
53
+ /** Explicit capability over a local habitat's Keeper root and accepted public registry evidence. */
54
+ export class RegistryCustody {
55
+ /** Borrow owners only; construction loads no encrypted row. */
56
+ constructor(options) {
57
+ Object.defineProperty(this, "options", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: options
62
+ });
63
+ this.owner();
64
+ }
65
+ /** Bind the actual local habitat and its key owners, never an AID label alone. */
66
+ owner() {
67
+ const { hby, hab } = this.options;
68
+ if (hby.habs.get(hab.pre) !== hab || hab.ks !== hby.ks || hab.mgr !== hby.mgr || hab.db !== hby.db) {
69
+ throw new ValidationError("Custody requires the actual local habitat and Keeper owners");
70
+ }
71
+ }
72
+ /** Load only this habitat's Keeper root; possession confers no protocol authority. */
73
+ load(registry) {
74
+ this.owner();
75
+ const root = this.options.hby.mgr.getRegistryRoot(this.options.hab.pre, registry);
76
+ if (!root)
77
+ throw new ValidationError("Registry custody is not provisioned");
78
+ return root;
79
+ }
80
+ /** Provision an issuer-selected root once, refusing replacement behind opaque accepted history. */
81
+ createCustody(registry) {
82
+ this.owner();
83
+ const { hby, hab } = this.options;
84
+ if (!hby.mgr.aeid || !hby.mgr.seed) {
85
+ throw new ValidationError("Private credential custody requires an authenticated encrypted Keeper");
86
+ }
87
+ if (hby.mgr.getRegistryRoot(hab.pre, registry))
88
+ return { registry };
89
+ const rip = this.options.registry.seqEvent(registry, 0);
90
+ if (!rip || rip.issuer !== hab.pre) {
91
+ throw new ValidationError("New custody requires the accepted registry issuer's actual local habitat");
92
+ }
93
+ // Existing clone validation authenticates public openings without another parser or proof algorithm.
94
+ for (const _ of this.options.registry.cloneTelIter(registry)) { /* consume the accepted public prefix */ }
95
+ const head = this.options.registry.headEvent(registry);
96
+ const last = head ? Number(BigInt(`0x${head.sad.n}`)) : 0;
97
+ if (!Number.isSafeInteger(last))
98
+ throw new ValidationError("Accepted registry ordinal is not representable");
99
+ for (let ordinal = 1; ordinal <= last; ordinal++) {
100
+ const event = this.options.registry.seqEvent(registry, ordinal);
101
+ if (!event)
102
+ throw new ValidationError("Accepted registry history is incomplete");
103
+ if (event.ilk === "bup" && !this.options.registry.opening(event.said)) {
104
+ throw new ValidationError("Local custody is missing for blinded registry history; salt cannot be recreated");
105
+ }
106
+ }
107
+ hby.mgr.putRegistryRoot(hab.pre, registry, new Salter({ code: MtrDex.Salt_128, raw: crypto.getRandomValues(new Uint8Array(16)) }));
108
+ return { registry };
109
+ }
110
+ /** Derive a candidate only; consumers still authenticate its exact accepted event and bound KEL reference. */
111
+ derive(registry, ordinal, credential, state, options = {}) {
112
+ if ((typeof ordinal !== "bigint" && (typeof ordinal !== "number" || !Number.isSafeInteger(ordinal))) || ordinal < 1) {
113
+ throw new ValidationError("Update ordinal must be a positive integer");
114
+ }
115
+ const root = this.load(registry);
116
+ const values = { salt: root.qb64, sn: ordinal, tier: "low", acdc: credential, state };
117
+ return options.bound
118
+ ? makeBoundState({ ...values, bsn: options.bsn ?? 0, bd: options.bd ?? "" })
119
+ : makeBlindState(values);
120
+ }
121
+ /** Persist exact nonsecret coordinates before processing/anchoring a newly derived BUP. */
122
+ retainDerivedUpdate(event, opening) {
123
+ if (event.ilk !== "bup" || !event.verify() || !vetBlind(opening, event.sad.b)) {
124
+ throw new ValidationError("Derived update requires its exact authenticated BUP opening");
125
+ }
126
+ const value = {
127
+ credential: opening.td.nonce,
128
+ state: opening.ts.label,
129
+ bound: "bn" in opening ? { bn: opening.bn.num.toString(16), bd: opening.bd.nonce } : null,
130
+ };
131
+ const old = this.options.store.get(event.said);
132
+ if (old && JSON.stringify(canonical(old)) !== JSON.stringify(value)) {
133
+ throw new ValidationError("Different derivation coordinates are already retained for this event");
134
+ }
135
+ this.options.store.pin(event.said, value);
136
+ return value;
137
+ }
138
+ /** Reproduce only the exact accepted event, never today's head or a later credential's coordinates. */
139
+ derivedOpening(event) {
140
+ if (event.ilk !== "bup" || !event.verify())
141
+ throw new ValidationError("Exact accepted blinded update is required");
142
+ const ordinal = BigInt(`0x${event.sad.n}`);
143
+ if (!Number.isSafeInteger(Number(ordinal))) {
144
+ throw new ValidationError("Accepted registry ordinal is not representable");
145
+ }
146
+ const stored = event.regid ? this.options.registry.seqEvent(event.regid, Number(ordinal)) : null;
147
+ if (!stored || !bytesEqual(stored.raw, event.raw)) {
148
+ throw new ValidationError("Exact accepted registry event is required");
149
+ }
150
+ const value = this.options.store.get(event.said);
151
+ if (!value)
152
+ throw new ValidationError("Exact derived update coordinates are unavailable");
153
+ const opening = this.derive(event.regid, ordinal, value.credential, value.state, value.bound ? { bound: true, bsn: BigInt(`0x${value.bound.bn}`), bd: value.bound.bd } : {});
154
+ if (!vetBlind(opening, event.sad.b)) {
155
+ throw new ValidationError("Derived opening does not match the exact accepted event");
156
+ }
157
+ return opening;
158
+ }
159
+ }
160
+ /** Fix field order so equality does not depend on how a store hydrated the record. */
161
+ function canonical(value) {
162
+ const { credential, state, bound } = value;
163
+ return { credential, state, bound: bound ? { bn: bound.bn, bd: bound.bd } : null };
164
+ }
@@ -8,7 +8,7 @@ import { hkdf } from "@noble/hashes/hkdf";
8
8
  import { sha256 } from "@noble/hashes/sha2";
9
9
  import { Hab } from "../app/identity/habbing.js";
10
10
  import { groupWitnesserSelection, isLocalGroupHab, latestGroupContribution, localGroupMember, } from "../app/multisig/group-members.js";
11
- import { copyAuxiliaryQuery, envelopeFromFrame, } from "../app/protocol/parsering.js";
11
+ import { auxiliaryQueryWire, copyAuxiliaryQuery, envelopeFromFrame, restoreAuxiliaryQuery, } from "../app/protocol/parsering.js";
12
12
  import { Deck } from "../core/deck.js";
13
13
  import { ValidationError } from "../core/errors.js";
14
14
  import { verifyQueryAttachments } from "../core/exchange/exchange-proofing.js";
@@ -85,6 +85,72 @@ export function deriveRoot(privateKey, context) {
85
85
  shared.fill(0);
86
86
  }
87
87
  }
88
+ /**
89
+ * The DH transaction id of a Grant: its own SAID when it opens the exchange (`xip`), and otherwise the exchange it
90
+ * continues (`x`). The one definition, so the owner and any workflow that names the transaction agree.
91
+ */
92
+ export function grantTransactionId(grant) {
93
+ return grant.ilk === "xip" ? grant.said : grant.sad.x;
94
+ }
95
+ /** The parties and transaction of a Grant `hab` takes part in, or null when it is not a DH party of it. */
96
+ function grantParties(hab, input) {
97
+ const message = input.serder, issuer = message.pre, issuee = message.sad.ri;
98
+ const xid = grantTransactionId(message);
99
+ return typeof xid === "string" && typeof issuee === "string" && issuer !== issuee
100
+ && [issuer, issuee].includes(hab.pre)
101
+ ? { issuer, issuee, xid }
102
+ : null;
103
+ }
104
+ /** Resolve the pending Grant `hab` may start DH for, or the reason it cannot. Reads only; creates no approval. */
105
+ function freshScope(hab, exc, grant) {
106
+ const input = exc.retainedInput(grant, { pending: true });
107
+ if (!input)
108
+ return "DH requires an authenticated pending Grant";
109
+ const parties = grantParties(hab, input);
110
+ if (!parties)
111
+ return "Local habitat is not a DH party";
112
+ const context = exc.pendingGrant(grant, { ...parties, sender: parties.issuer, recipient: parties.issuee });
113
+ if (!context)
114
+ return "DH requires authenticated fresh registry scope";
115
+ return { input, ...parties, registries: [...context.registries] };
116
+ }
117
+ /**
118
+ * The scope of a completed exchange that can finish without new key exchange: the Grant is still pending
119
+ * inside its original deadline and `hab` holds a root for the registries it discloses. The scope is those
120
+ * registries; a registry that is still fresh must hold one. No fresh registry is required, because the
121
+ * issuer's update may already be accepted: {@link Dhke.finish} proves the held root against that update, so
122
+ * a root from any other exchange is rejected there. Pure read of stores. Null when nothing can resume.
123
+ */
124
+ export function resumableExchange({ hab, exc }, grant) {
125
+ const input = exc.retainedInput(grant, { pending: true });
126
+ const parties = input && grantParties(hab, input);
127
+ if (!input || !parties)
128
+ return null;
129
+ const disclosed = (input.nests ?? []).map((nest) => nest.body.ked?.rd);
130
+ const held = [...new Set(disclosed)].filter((registry) => typeof registry === "string" && hab.mgr.hasRegistryRoot(hab.pre, registry));
131
+ const fresh = exc.pendingGrant(grant, { ...parties, sender: parties.issuer, recipient: parties.issuee });
132
+ if (!held.length || fresh?.registries.some((registry) => !held.includes(registry)))
133
+ return null;
134
+ return { input, ...parties, registries: held };
135
+ }
136
+ /**
137
+ * Whether `registry` has no committed state: its head is still the inception and no update is escrowed.
138
+ * A staged update waits in the missing-anchor or out-of-order escrow under its registry until the issuer's
139
+ * anchor is accepted, and an accepted one moves the head, so two keyed reads bounded by this registry
140
+ * decide it. Only then can a retained root be unused, because every derivation from a root, and every copy
141
+ * of it to another member (which `RegistryRoot` authorizes only for an accepted, issuer-anchored update),
142
+ * starts from a staged or accepted update. A remote update escrowed for this registry also counts, which
143
+ * is the conservative side.
144
+ */
145
+ export function registryUncommitted(registryStore, registry) {
146
+ if (registryStore.headEvent(registry)?.ilk !== "rip")
147
+ return false;
148
+ for (const table of [registryStore.baser.maes, registryStore.baser.ooes]) {
149
+ for (const _ of table.getTopItemIter(registry))
150
+ return false;
151
+ }
152
+ return true;
153
+ }
88
154
  /**
89
155
  * Issuer/issuee DH for an explicitly approved pending Grant. Wire
90
156
  * intake cannot approve work. Inject as ProtocolProcessor.qvy and register on
@@ -95,7 +161,7 @@ export function deriveRoot(privateKey, context) {
95
161
  */
96
162
  export class Dhke {
97
163
  /** Bind concrete local owners; construction grants no consent and writes nothing. */
98
- constructor({ hab, exc, registryStore, rvy = hab.rvy, now = Date.now }) {
164
+ constructor({ hab, exc, registryStore, rvy = hab.rvy, now = Date.now, kram = true }) {
99
165
  Object.defineProperty(this, "resource", {
100
166
  enumerable: true,
101
167
  configurable: true,
@@ -108,6 +174,13 @@ export class Dhke {
108
174
  writable: true,
109
175
  value: new Deck()
110
176
  });
177
+ /** Completion cues for roots just retained by this group's custodian; feed `RootReplicator.replicate`. */
178
+ Object.defineProperty(this, "replicated", {
179
+ enumerable: true,
180
+ configurable: true,
181
+ writable: true,
182
+ value: new Deck()
183
+ });
111
184
  Object.defineProperty(this, "pendingQueries", {
112
185
  enumerable: true,
113
186
  configurable: true,
@@ -156,6 +229,13 @@ export class Dhke {
156
229
  writable: true,
157
230
  value: void 0
158
231
  });
232
+ Object.defineProperty(this, "kram", {
233
+ enumerable: true,
234
+ configurable: true,
235
+ writable: true,
236
+ value: void 0
237
+ });
238
+ this.kram = kram;
159
239
  if (!(hab instanceof Hab) || hab.db !== exc.hby.db || rvy.db !== hab.db
160
240
  || exc.hby.habs.get(hab.pre) !== hab)
161
241
  throw new ValidationError("DH requires a local signing habitat");
@@ -169,8 +249,20 @@ export class Dhke {
169
249
  throw new ValidationError("DH requires a local signing member");
170
250
  }
171
251
  }
172
- /** Select one live fresh issuance and freeze its exact bodies, parties and registry order. */
252
+ /**
253
+ * Select one live fresh issuance and freeze its exact bodies, parties and registry order.
254
+ *
255
+ * A registry that already holds a root refuses (`Registry root conflicts with this live DH operation`)
256
+ * unless it has no committed state ({@link registryUncommitted}): then the held root was never used and
257
+ * this exchange, whose Grant is from the registry's issuer, overwrites it when it retains its own root,
258
+ * never at approval, so an interruption before retention leaves the old root. Once any update is staged
259
+ * or accepted the refusal is unchanged. A KERIpy peer keeps the old rule and refuses such a second
260
+ * exchange: with a KERIpy holder the issuer needs a fresh registry. One process also refuses a second
261
+ * live operation on a registry, so two pending Grants cannot clobber each other's root.
262
+ */
173
263
  approve(grant, { coordinator, custodian } = {}) {
264
+ if (!this.kram)
265
+ throw new ValidationError("DH requires KRAM: enable it with the runtime's kram option");
174
266
  this.pruneQueries();
175
267
  this.hab.mgr.requireRegistryRootAccess();
176
268
  for (const op of this.operations.values()) {
@@ -184,27 +276,68 @@ export class Dhke {
184
276
  return op.xid;
185
277
  }
186
278
  }
187
- const input = this.exc.retainedInput(grant, { pending: true });
188
- if (!input)
189
- throw new ValidationError("DH requires an authenticated pending Grant");
190
- const message = input.serder, issuer = message.pre, issuee = message.sad.ri;
191
- const xid = message.ilk === "xip" ? message.said : message.sad.x;
192
- if (typeof xid !== "string" || typeof issuee !== "string" || issuer === issuee
193
- || ![issuer, issuee].includes(this.hab.pre))
194
- throw new ValidationError("Local habitat is not a DH party");
279
+ const scope = freshScope(this.hab, this.exc, grant);
280
+ if (typeof scope === "string")
281
+ throw new ValidationError(scope);
282
+ const op = this.frozen(scope, grant, { coordinator, custodian }, false);
283
+ for (const other of this.operations.values()) {
284
+ if (!other.abandoned && other.registries.some((registry) => op.registries.includes(registry))) {
285
+ throw new ValidationError("Another live DH operation uses this registry");
286
+ }
287
+ }
288
+ for (const registry of op.registries) {
289
+ if (this.hab.mgr.hasRegistryRoot(this.hab.pre, registry) && registryUncommitted(this.registryStore, registry)) {
290
+ op.replaces.add(registry);
291
+ }
292
+ }
293
+ this.roots(op);
294
+ this.operations.set(op.xid, op);
295
+ this.replayQuery(op.xid);
296
+ return op.xid;
297
+ }
298
+ /**
299
+ * Resume a completed exchange after a process restart, without new key exchange: rebuild the operation as
300
+ * completed from the roots held for the Grant's registries ({@link resumableExchange}). It holds no
301
+ * ephemeral key, so it cannot start, answer or renew a query; it can only {@link complete} and
302
+ * {@link finish}, which signs nothing and verifies the issuer's update against the held root. Needs an
303
+ * unlocked Keeper; wire intake never calls it. Repeating it returns the same transaction.
304
+ *
305
+ * @throws ValidationError unless the Grant is pending and holds a root for each registry in its scope.
306
+ */
307
+ resume(grant, { coordinator, custodian } = {}) {
308
+ this.pruneQueries();
309
+ this.hab.mgr.requireRegistryRootAccess();
310
+ for (const op of this.operations.values()) {
311
+ if (op.grant !== grant)
312
+ continue;
313
+ if (!op.completed)
314
+ throw new ValidationError("DH is still exchanging keys for this Grant; nothing to resume");
315
+ this.pending(op);
316
+ return op.xid;
317
+ }
318
+ const scope = resumableExchange(this, grant);
319
+ if (!scope)
320
+ throw new ValidationError("No root is held for this pending Grant's registries");
321
+ const op = this.frozen(scope, grant, { coordinator, custodian }, true);
322
+ this.roots(op);
323
+ this.operations.set(op.xid, op);
324
+ this.pendingQueries.delete(op.xid);
325
+ this.dropHeld(op.xid);
326
+ return op.xid;
327
+ }
328
+ /** Freeze the exact pending Grant, parties and registry order into an operation; registers nothing. */
329
+ frozen(scope, grant, { coordinator, custodian }, completed) {
330
+ const { input, issuer, issuee, xid, registries } = scope;
195
331
  if (this.operations.has(xid))
196
332
  throw new ValidationError("Another Grant is selected for this transaction");
197
- const context = this.exc.pendingGrant(grant, { xid, sender: issuer, recipient: issuee });
198
- if (!context)
199
- throw new ValidationError("DH requires authenticated fresh registry scope");
200
333
  const op = {
201
334
  xid,
202
335
  grant,
203
336
  issuer,
204
337
  issuee,
205
- raw: message.raw.slice(),
338
+ raw: input.serder.raw.slice(),
206
339
  bodies: (input.nests ?? []).map((nest) => nest.body.raw.slice()),
207
- registries: [...context.registries],
340
+ registries,
208
341
  privateKeys: new Map(),
209
342
  publicKeys: {},
210
343
  peer: null,
@@ -213,7 +346,8 @@ export class Dhke {
213
346
  proposal: null,
214
347
  contribution: null,
215
348
  custody: null,
216
- completed: false,
349
+ replaces: new Set(),
350
+ completed,
217
351
  abandoned: false,
218
352
  };
219
353
  if (this.group) {
@@ -235,10 +369,17 @@ export class Dhke {
235
369
  else if (coordinator !== undefined || custodian !== undefined) {
236
370
  throw new ValidationError("Individual DH has no group coordinator");
237
371
  }
238
- this.roots(op);
239
- this.operations.set(xid, op);
240
- this.replayQuery(xid);
241
- return xid;
372
+ return op;
373
+ }
374
+ /**
375
+ * Whether this owner already holds a live operation for `grant`. Two operation tables over one runtime
376
+ * (the host's and a command's own) use it so only the first to reach a Grant drives it.
377
+ */
378
+ holds(grant) {
379
+ for (const op of this.operations.values())
380
+ if (op.grant === grant && !op.abandoned)
381
+ return true;
382
+ return false;
242
383
  }
243
384
  /** Return the stable issuer proposal until own threshold intake supplies the complete query. */
244
385
  start(grant) {
@@ -506,12 +647,34 @@ export class Dhke {
506
647
  /** Drop local ephemeral key references and permanently refuse this operation. */
507
648
  abandon(xid) {
508
649
  const retained = this.pendingQueries.delete(xid);
650
+ this.dropHeld(xid);
509
651
  if (retained && !this.operations.has(xid))
510
652
  return;
511
653
  const op = this.operation(xid);
512
654
  this.clearPrivate(op);
513
655
  op.abandoned = true;
514
656
  }
657
+ /**
658
+ * Whether this local habitat is the party of DH transaction `xid` with `sender`.
659
+ *
660
+ * Messages carry no recipient, so a per-identifier registry selects the owner by transaction:
661
+ * an approved operation here, a stored Grant from `sender` addressed to this habitat, or, for a
662
+ * group, its own members' contributions, which KRAM must pool before this owner consents.
663
+ */
664
+ inTransaction(sender, xid) {
665
+ return this.operations.has(xid) || (this.group && sender === this.hab.pre)
666
+ || Dhke.recipients(this.hab.db, sender, xid).includes(this.hab.pre);
667
+ }
668
+ /** Recipients of the pending Grants `sender` opened in DH transaction `xid`, from KRAM-accepted store rows. */
669
+ static recipients(db, sender, xid) {
670
+ const recipients = [];
671
+ for (const [key] of db.tmsc.getTopItemIter([sender, xid])) {
672
+ const recipient = db.epse.get([key[2]])?.sad?.ri;
673
+ if (typeof recipient === "string")
674
+ recipients.push(recipient);
675
+ }
676
+ return recipients;
677
+ }
515
678
  /** Release all process-local approvals and retry bytes; zero owned ephemeral scalar arrays. */
516
679
  close() {
517
680
  for (const op of this.operations.values())
@@ -519,6 +682,7 @@ export class Dhke {
519
682
  this.operations.clear();
520
683
  this.pendingQueries.clear();
521
684
  this.outgoing.clear();
685
+ this.replicated.clear();
522
686
  }
523
687
  /** Retain public query evidence against one exact pending Grant, without creating keys or consent. */
524
688
  retainQuery(envelope) {
@@ -540,11 +704,22 @@ export class Dhke {
540
704
  for (const [, key] of entries)
541
705
  decodePublicKey(key);
542
706
  const expires = this.retainUntil(envelope, grant);
543
- const prior = this.pendingQueries.get(data.x);
544
- if (prior && !bytesEqual(prior.envelope.serder.raw, query.raw))
545
- throw new ValidationError("Conflicting DH query");
546
- if (!prior) {
707
+ // After a restart the persisted copy is the prior one, so a successor is judged as it is before one.
708
+ const prior = this.pendingQueries.get(data.x) ?? this.loadHeld(data.x, grant.said);
709
+ if (prior && !bytesEqual(prior.envelope.serder.raw, query.raw)) {
710
+ // The issuer re-dates a query that aged before this side consented (`requery`): same sender, keys and
711
+ // Grant under a new date. It replaces the held one; any other difference is a conflict.
712
+ const held = this.parameters(prior.envelope.serder, "q");
713
+ const same = prior.envelope.serder.pre === query.pre && prior.grant === grant.said
714
+ && JSON.stringify(Object.entries(held.pk).sort()) === JSON.stringify(entries.sort());
715
+ if (!same)
716
+ throw new ValidationError("Conflicting DH query");
717
+ }
718
+ if (!prior || !bytesEqual(prior.envelope.serder.raw, query.raw)) {
547
719
  this.pendingQueries.set(data.x, { envelope: copyAuxiliaryQuery(envelope), expires, grant: grant.said });
720
+ // KRAM now holds this query as seen, so a resend of it is a replay: the held copy must outlive this process.
721
+ if (!envelope.nests.length)
722
+ this.hab.db.heldq.pin([data.x], auxiliaryQueryWire(envelope));
548
723
  }
549
724
  }
550
725
  /** Expired evidence cannot survive another owner interaction. */
@@ -557,11 +732,32 @@ export class Dhke {
557
732
  }
558
733
  /** Consume the first authenticated request only after explicit approval; never renew either clock. */
559
734
  replayQuery(xid) {
560
- const pending = this.pendingQueries.get(xid);
735
+ const grant = this.operations.get(xid)?.grant;
736
+ const pending = this.pendingQueries.get(xid) ?? (grant ? this.loadHeld(xid, grant) : undefined);
561
737
  this.pendingQueries.delete(xid);
562
- if (pending && pending.grant === this.operations.get(xid)?.grant
563
- && BigInt(this.now()) * 1000n < pending.expires)
738
+ this.dropHeld(xid);
739
+ if (pending && pending.grant === grant && BigInt(this.now()) * 1000n < pending.expires) {
564
740
  this.processQuery(pending.envelope);
741
+ }
742
+ }
743
+ /** The persisted query for `xid` after a restart, with its lifetime recomputed from KRAM's durable records. */
744
+ loadHeld(xid, grant) {
745
+ const wire = this.hab.db.heldq.get([xid]);
746
+ const input = this.exc.retainedInput(grant, { pending: true });
747
+ if (!wire || !input)
748
+ return undefined;
749
+ try {
750
+ const envelope = restoreAuxiliaryQuery(wire);
751
+ return { envelope, expires: this.retainUntil(envelope, input.serder), grant };
752
+ }
753
+ catch (error) {
754
+ if (error instanceof ValidationError)
755
+ return undefined;
756
+ throw error;
757
+ }
758
+ }
759
+ dropHeld(xid) {
760
+ this.hab.db.heldq.rem([xid]);
565
761
  }
566
762
  /** Bound process-local public evidence by the original query and accepted Grant lifetimes. */
567
763
  retainUntil(envelope, grant) {
@@ -610,8 +806,12 @@ export class Dhke {
610
806
  }
611
807
  roots(op) {
612
808
  for (const registry of op.registries) {
613
- if ((this.hab.mgr.getRegistryRoot(this.hab.pre, registry) !== null) !== op.completed) {
614
- throw new ValidationError("Registry root conflicts with this live DH operation");
809
+ const held = this.hab.mgr.hasRegistryRoot(this.hab.pre, registry);
810
+ if (held !== op.completed && !(held && op.replaces.has(registry))) {
811
+ throw new ValidationError(held
812
+ ? "Registry root conflicts with this live DH operation: a DH-issued registry must not have a custody root, "
813
+ + "so do not call createCustody for it before issuance (use a registry without custody)"
814
+ : "Registry root conflicts with this live DH operation");
615
815
  }
616
816
  }
617
817
  }
@@ -648,6 +848,9 @@ export class Dhke {
648
848
  return { op, peer };
649
849
  }
650
850
  generate(op) {
851
+ // A completed operation, including a resumed one, never holds or makes ephemeral keys again.
852
+ if (op.completed)
853
+ throw new ValidationError("DH operation has already completed");
651
854
  this.custody(op, true);
652
855
  if (op.privateKeys.size)
653
856
  return;
@@ -675,11 +878,20 @@ export class Dhke {
675
878
  ]));
676
879
  }
677
880
  retain(op, peer, roots) {
678
- for (const [registry, root] of roots)
679
- this.hab.mgr.putRegistryRoot(this.hab.pre, registry, root);
881
+ for (const [registry, root] of roots) {
882
+ const replacing = op.replaces.has(registry);
883
+ // Recheck at commit time, from stores: the held root must still be unused.
884
+ if (replacing && !registryUncommitted(this.registryStore, registry)) {
885
+ throw new ValidationError("Registry root conflicts with this live DH operation");
886
+ }
887
+ this.hab.mgr.putRegistryRoot(this.hab.pre, registry, root, replacing);
888
+ }
680
889
  op.peer = { ...peer };
681
890
  op.completed = true;
682
891
  this.clearPrivate(op);
892
+ // Every current member must hold every root; the custodian replicates.
893
+ if (this.group)
894
+ this.replicated.push({ gid: this.hab.pre, registries: [...roots.keys()] });
683
895
  }
684
896
  clearPrivate(op) {
685
897
  for (const key of op.privateKeys.values())
@@ -76,7 +76,7 @@ export class RegistryObserver {
76
76
  const baser = this.store.baser;
77
77
  if (baser.readonly)
78
78
  throw new DatabaseOperationError("Cannot write readonly registry storage.");
79
- return baser.env.transactionSync(() => {
79
+ return baser.transaction(() => {
80
80
  this.store.putEvent(serder);
81
81
  this.store.escrowMissingAnchor(event.regid, Number(event.sn), event.said);
82
82
  if (opening)
@@ -106,7 +106,7 @@ export class RegistryObserver {
106
106
  }
107
107
  /** Stored inception is durable issuer identity, including while its anchor is still absent. */
108
108
  engine(regid) {
109
- if (!this.store.baser.env)
109
+ if (!this.store.baser.opened)
110
110
  throw new DatabaseNotOpenError("Registry observer store is closed.");
111
111
  const rip = this.store.event(regid);
112
112
  if (!rip) {