keri-ts 2.1.0 → 2.2.1

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 (300) 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/custody.js +187 -0
  4. package/esm/keri/npm/src/acdc/dhking.js +244 -32
  5. package/esm/keri/npm/src/acdc/regbasing.js +10 -0
  6. package/esm/keri/npm/src/acdc/salting.js +16 -1
  7. package/esm/keri/npm/src/acdc/scheming.js +93 -54
  8. package/esm/keri/npm/src/acdc/unblinding.js +118 -95
  9. package/esm/keri/npm/src/app/bootstrap/authenticating.js +4 -6
  10. package/esm/keri/npm/src/app/bootstrap/oobi-resolving.js +41 -0
  11. package/esm/keri/npm/src/app/bootstrap/oobiery.js +4 -6
  12. package/esm/keri/npm/src/app/credentials/credential-revoking.js +1 -0
  13. package/esm/keri/npm/src/app/credentials/credential-workflows.js +2 -0
  14. package/esm/keri/npm/src/app/credentials/registry-settling.js +44 -0
  15. package/esm/keri/npm/src/app/credentials/root-replicating.js +68 -60
  16. package/esm/keri/npm/src/app/credentials/root-replicator.js +198 -0
  17. package/esm/keri/npm/src/app/credentials/tel-completion.js +36 -0
  18. package/esm/keri/npm/src/app/delivery/forwarding.js +16 -3
  19. package/esm/keri/npm/src/app/exchanges/exchanging.js +14 -4
  20. package/esm/keri/npm/src/app/identity/challenging.js +50 -0
  21. package/esm/keri/npm/src/app/identity/delegating.js +77 -77
  22. package/esm/keri/npm/src/app/identity/delegation-approval.js +333 -0
  23. package/esm/keri/npm/src/app/identity/event-completion.js +154 -0
  24. package/esm/keri/npm/src/app/identity/habbing.js +129 -6
  25. package/esm/keri/npm/src/app/identity/keeping.js +77 -4
  26. package/esm/keri/npm/src/app/ipex/group-ipex.js +341 -0
  27. package/esm/keri/npm/src/app/ipex/group-issuance.js +905 -0
  28. package/esm/keri/npm/src/app/ipex/ipex-admitting.js +120 -0
  29. package/esm/keri/npm/src/app/ipex/ipex-conversation.js +197 -0
  30. package/esm/keri/npm/src/app/ipex/ipex-discloser.js +591 -0
  31. package/esm/keri/npm/src/app/ipex/ipex-granting.js +93 -0
  32. package/esm/keri/npm/src/app/ipex/ipex-grouping.js +50 -19
  33. package/esm/keri/npm/src/app/ipex/ipex-node-authentication.js +42 -18
  34. package/esm/keri/npm/src/app/ipex/issuance.js +896 -0
  35. package/esm/keri/npm/src/app/ipex/pending-presentations.js +46 -0
  36. package/esm/keri/npm/src/app/ipex/presentation-files.js +200 -0
  37. package/esm/keri/npm/src/app/ipex/presenting.js +408 -0
  38. package/esm/keri/npm/src/app/ipex/receive-issuance.js +86 -0
  39. package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +667 -0
  40. package/esm/keri/npm/src/app/mailbox/ipex-arrival.js +103 -0
  41. package/esm/keri/npm/src/app/mailbox/kel-publisher.js +322 -0
  42. package/esm/keri/npm/src/app/mailbox/kel-publishing.js +65 -0
  43. package/esm/keri/npm/src/app/mailbox/kel-submission.js +24 -0
  44. package/esm/keri/npm/src/app/mailbox/mailbox-admin.js +208 -0
  45. package/esm/keri/npm/src/app/mailbox/mailbox-poller.js +212 -47
  46. package/esm/keri/npm/src/app/mailbox/mailboxing.js +10 -5
  47. package/esm/keri/npm/src/app/multisig/counseling.js +488 -0
  48. package/esm/keri/npm/src/app/multisig/group-members.js +18 -0
  49. package/esm/keri/npm/src/app/multisig/multisig-messaging.js +33 -6
  50. package/esm/keri/npm/src/app/multisig/multisig-workflows.js +98 -147
  51. package/esm/keri/npm/src/app/multisig/proposals.js +281 -0
  52. package/esm/keri/npm/src/app/multisig/proposing.js +122 -0
  53. package/esm/keri/npm/src/app/notifications/signaling.js +5 -5
  54. package/esm/keri/npm/src/app/protocol/parsering.js +26 -1
  55. package/esm/keri/npm/src/app/protocol/protocol-processing.js +9 -3
  56. package/esm/keri/npm/src/app/queries/query-workflows.js +98 -0
  57. package/esm/keri/npm/src/app/runtime/agent-runtime.js +106 -55
  58. package/esm/keri/npm/src/app/runtime/cue-runtime.js +3 -6
  59. package/esm/keri/npm/src/app/runtime/delivery-outbox.js +87 -0
  60. package/esm/keri/npm/src/app/runtime/doing.js +17 -0
  61. package/esm/keri/npm/src/app/runtime/ipex-auxiliaries.js +207 -0
  62. package/esm/keri/npm/src/app/runtime/operation-owners.js +151 -0
  63. package/esm/keri/npm/src/app/runtime/retry-backoff.js +93 -0
  64. package/esm/keri/npm/src/app/runtime/workflow-contract.js +80 -0
  65. package/esm/keri/npm/src/app/transport/http-client.js +25 -6
  66. package/esm/keri/npm/src/app/witness/http-endpoints.js +4 -4
  67. package/esm/keri/npm/src/cli/common/event-completion.js +49 -0
  68. package/esm/keri/npm/src/cli/common/runtime-workers.js +23 -0
  69. package/esm/keri/npm/src/cli/credentials/ipex.js +164 -191
  70. package/esm/keri/npm/src/cli/credentials/vc.js +53 -72
  71. package/esm/keri/npm/src/cli/endpoints/did.js +12 -3
  72. package/esm/keri/npm/src/cli/endpoints/oobi.js +10 -13
  73. package/esm/keri/npm/src/cli/identity/challenge.js +8 -34
  74. package/esm/keri/npm/src/cli/identity/delegate.js +81 -258
  75. package/esm/keri/npm/src/cli/identity/incept.js +15 -32
  76. package/esm/keri/npm/src/cli/identity/interact.js +5 -17
  77. package/esm/keri/npm/src/cli/identity/rotate.js +8 -36
  78. package/esm/keri/npm/src/cli/index.js +3 -1
  79. package/esm/keri/npm/src/cli/messaging/group-join.js +83 -0
  80. package/esm/keri/npm/src/cli/messaging/group-wait.js +88 -0
  81. package/esm/keri/npm/src/cli/messaging/multisig.js +190 -285
  82. package/esm/keri/npm/src/cli/messaging/root-copy-lines.js +31 -0
  83. package/esm/keri/npm/src/core/kel/eventing.js +66 -10
  84. package/esm/keri/npm/src/core/mailbox/kram-policy.js +39 -6
  85. package/esm/keri/npm/src/core/mailbox/kraming.js +2 -0
  86. package/esm/keri/npm/src/core/records.js +23 -0
  87. package/esm/keri/npm/src/core/routing.js +13 -0
  88. package/esm/keri/npm/src/db/basing.js +34 -2
  89. package/esm/keri/npm/src/db/core/indexeddb-persistence.js +221 -0
  90. package/esm/keri/npm/src/db/indexeddb.js +98 -0
  91. package/esm/keri/npm/src/db/keeping.js +11 -2
  92. package/esm/keri/npm/src/db/store-lock.js +150 -0
  93. package/esm/keri/npm/src/npm/db-indexeddb.browser.js +2 -0
  94. package/esm/keri/npm/src/npm/db-indexeddb.js +3 -0
  95. package/esm/keri/npm/src/npm/db.browser.js +2 -0
  96. package/esm/keri/npm/src/npm/index.browser.js +9 -0
  97. package/esm/keri/npm/src/npm/runtime-web.browser.js +2 -0
  98. package/esm/keri/npm/src/npm/runtime-web.js +3 -0
  99. package/esm/keri/npm/src/npm/runtime.browser.js +2 -0
  100. package/esm/keri/npm/src/runtime/index.js +51 -4
  101. package/esm/keri/npm/src/runtime/web/output-barrier.js +47 -0
  102. package/esm/keri/npm/src/runtime/web/persistent-storage.js +37 -0
  103. package/esm/keri/npm/src/runtime/web.js +10 -0
  104. package/esm/keri/npm/src/vdr/tel-publication.js +16 -0
  105. package/esm/keri/npm/src/version.js +2 -2
  106. package/package.json +15 -2
  107. package/types/acdc/authoring.d.ts +54 -0
  108. package/types/acdc/authoring.d.ts.map +1 -0
  109. package/types/acdc/custody.d.ts +84 -0
  110. package/types/acdc/custody.d.ts.map +1 -0
  111. package/types/acdc/dhking.d.ts +94 -3
  112. package/types/acdc/dhking.d.ts.map +1 -1
  113. package/types/acdc/regbasing.d.ts +4 -0
  114. package/types/acdc/regbasing.d.ts.map +1 -1
  115. package/types/acdc/salting.d.ts +6 -1
  116. package/types/acdc/salting.d.ts.map +1 -1
  117. package/types/acdc/scheming.d.ts +2 -0
  118. package/types/acdc/scheming.d.ts.map +1 -1
  119. package/types/acdc/unblinding.d.ts +58 -19
  120. package/types/acdc/unblinding.d.ts.map +1 -1
  121. package/types/app/bootstrap/authenticating.d.ts +3 -1
  122. package/types/app/bootstrap/authenticating.d.ts.map +1 -1
  123. package/types/app/bootstrap/oobi-resolving.d.ts +92 -0
  124. package/types/app/bootstrap/oobi-resolving.d.ts.map +1 -0
  125. package/types/app/bootstrap/oobiery.d.ts +3 -1
  126. package/types/app/bootstrap/oobiery.d.ts.map +1 -1
  127. package/types/app/credentials/credential-revoking.d.ts +3 -0
  128. package/types/app/credentials/credential-revoking.d.ts.map +1 -1
  129. package/types/app/credentials/credential-workflows.d.ts +5 -0
  130. package/types/app/credentials/credential-workflows.d.ts.map +1 -1
  131. package/types/app/credentials/registry-settling.d.ts +85 -0
  132. package/types/app/credentials/registry-settling.d.ts.map +1 -0
  133. package/types/app/credentials/root-replicating.d.ts +56 -44
  134. package/types/app/credentials/root-replicating.d.ts.map +1 -1
  135. package/types/app/credentials/root-replicator.d.ts +105 -0
  136. package/types/app/credentials/root-replicator.d.ts.map +1 -0
  137. package/types/app/credentials/tel-completion.d.ts +55 -0
  138. package/types/app/credentials/tel-completion.d.ts.map +1 -0
  139. package/types/app/delivery/forwarding.d.ts +6 -0
  140. package/types/app/delivery/forwarding.d.ts.map +1 -1
  141. package/types/app/exchanges/exchanging.d.ts.map +1 -1
  142. package/types/app/identity/challenging.d.ts +54 -0
  143. package/types/app/identity/challenging.d.ts.map +1 -1
  144. package/types/app/identity/delegating.d.ts +21 -4
  145. package/types/app/identity/delegating.d.ts.map +1 -1
  146. package/types/app/identity/delegation-approval.d.ts +228 -0
  147. package/types/app/identity/delegation-approval.d.ts.map +1 -0
  148. package/types/app/identity/event-completion.d.ts +151 -0
  149. package/types/app/identity/event-completion.d.ts.map +1 -0
  150. package/types/app/identity/habbing.d.ts +67 -2
  151. package/types/app/identity/habbing.d.ts.map +1 -1
  152. package/types/app/identity/keeping.d.ts +49 -3
  153. package/types/app/identity/keeping.d.ts.map +1 -1
  154. package/types/app/ipex/group-ipex.d.ts +254 -0
  155. package/types/app/ipex/group-ipex.d.ts.map +1 -0
  156. package/types/app/ipex/group-issuance.d.ts +281 -0
  157. package/types/app/ipex/group-issuance.d.ts.map +1 -0
  158. package/types/app/ipex/ipex-admitting.d.ts +47 -0
  159. package/types/app/ipex/ipex-admitting.d.ts.map +1 -0
  160. package/types/app/ipex/ipex-conversation.d.ts +195 -0
  161. package/types/app/ipex/ipex-conversation.d.ts.map +1 -0
  162. package/types/app/ipex/ipex-discloser.d.ts +156 -0
  163. package/types/app/ipex/ipex-discloser.d.ts.map +1 -0
  164. package/types/app/ipex/ipex-granting.d.ts +145 -0
  165. package/types/app/ipex/ipex-granting.d.ts.map +1 -0
  166. package/types/app/ipex/ipex-grouping.d.ts +18 -0
  167. package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
  168. package/types/app/ipex/ipex-node-authentication.d.ts +9 -1
  169. package/types/app/ipex/ipex-node-authentication.d.ts.map +1 -1
  170. package/types/app/ipex/issuance.d.ts +445 -0
  171. package/types/app/ipex/issuance.d.ts.map +1 -0
  172. package/types/app/ipex/pending-presentations.d.ts +25 -0
  173. package/types/app/ipex/pending-presentations.d.ts.map +1 -0
  174. package/types/app/ipex/presentation-files.d.ts +47 -0
  175. package/types/app/ipex/presentation-files.d.ts.map +1 -0
  176. package/types/app/ipex/presenting.d.ts +300 -0
  177. package/types/app/ipex/presenting.d.ts.map +1 -0
  178. package/types/app/ipex/receive-issuance.d.ts +99 -0
  179. package/types/app/ipex/receive-issuance.d.ts.map +1 -0
  180. package/types/app/ipex/unblinding-workflow.d.ts +257 -0
  181. package/types/app/ipex/unblinding-workflow.d.ts.map +1 -0
  182. package/types/app/mailbox/ipex-arrival.d.ts +104 -0
  183. package/types/app/mailbox/ipex-arrival.d.ts.map +1 -0
  184. package/types/app/mailbox/kel-publisher.d.ts +141 -0
  185. package/types/app/mailbox/kel-publisher.d.ts.map +1 -0
  186. package/types/app/mailbox/kel-publishing.d.ts +70 -0
  187. package/types/app/mailbox/kel-publishing.d.ts.map +1 -0
  188. package/types/app/mailbox/kel-submission.d.ts +18 -0
  189. package/types/app/mailbox/kel-submission.d.ts.map +1 -0
  190. package/types/app/mailbox/mailbox-admin.d.ts +113 -0
  191. package/types/app/mailbox/mailbox-admin.d.ts.map +1 -0
  192. package/types/app/mailbox/mailbox-poller.d.ts +92 -3
  193. package/types/app/mailbox/mailbox-poller.d.ts.map +1 -1
  194. package/types/app/mailbox/mailboxing.d.ts +3 -0
  195. package/types/app/mailbox/mailboxing.d.ts.map +1 -1
  196. package/types/app/multisig/counseling.d.ts +196 -0
  197. package/types/app/multisig/counseling.d.ts.map +1 -0
  198. package/types/app/multisig/group-members.d.ts +11 -0
  199. package/types/app/multisig/group-members.d.ts.map +1 -1
  200. package/types/app/multisig/grouping.d.ts +39 -20
  201. package/types/app/multisig/grouping.d.ts.map +1 -1
  202. package/types/app/multisig/multisig-messaging.d.ts +23 -6
  203. package/types/app/multisig/multisig-messaging.d.ts.map +1 -1
  204. package/types/app/multisig/multisig-workflows.d.ts +91 -22
  205. package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
  206. package/types/app/multisig/proposals.d.ts +129 -0
  207. package/types/app/multisig/proposals.d.ts.map +1 -0
  208. package/types/app/multisig/proposing.d.ts +125 -0
  209. package/types/app/multisig/proposing.d.ts.map +1 -0
  210. package/types/app/notifications/signaling.d.ts +3 -1
  211. package/types/app/notifications/signaling.d.ts.map +1 -1
  212. package/types/app/protocol/parsering.d.ts +13 -0
  213. package/types/app/protocol/parsering.d.ts.map +1 -1
  214. package/types/app/protocol/protocol-processing.d.ts +7 -1
  215. package/types/app/protocol/protocol-processing.d.ts.map +1 -1
  216. package/types/app/queries/query-workflows.d.ts +98 -0
  217. package/types/app/queries/query-workflows.d.ts.map +1 -0
  218. package/types/app/runtime/agent-runtime.d.ts +72 -25
  219. package/types/app/runtime/agent-runtime.d.ts.map +1 -1
  220. package/types/app/runtime/cue-runtime.d.ts +2 -1
  221. package/types/app/runtime/cue-runtime.d.ts.map +1 -1
  222. package/types/app/runtime/delivery-outbox.d.ts +68 -0
  223. package/types/app/runtime/delivery-outbox.d.ts.map +1 -0
  224. package/types/app/runtime/doing.d.ts +27 -0
  225. package/types/app/runtime/doing.d.ts.map +1 -0
  226. package/types/app/runtime/ipex-auxiliaries.d.ts +74 -0
  227. package/types/app/runtime/ipex-auxiliaries.d.ts.map +1 -0
  228. package/types/app/runtime/operation-owners.d.ts +137 -0
  229. package/types/app/runtime/operation-owners.d.ts.map +1 -0
  230. package/types/app/runtime/retry-backoff.d.ts +49 -0
  231. package/types/app/runtime/retry-backoff.d.ts.map +1 -0
  232. package/types/app/runtime/workflow-contract.d.ts +79 -0
  233. package/types/app/runtime/workflow-contract.d.ts.map +1 -0
  234. package/types/app/transport/http-client.d.ts.map +1 -1
  235. package/types/cli/common/event-completion.d.ts +26 -0
  236. package/types/cli/common/event-completion.d.ts.map +1 -0
  237. package/types/cli/common/runtime-workers.d.ts +23 -0
  238. package/types/cli/common/runtime-workers.d.ts.map +1 -0
  239. package/types/cli/credentials/ipex.d.ts.map +1 -1
  240. package/types/cli/credentials/vc.d.ts +1 -1
  241. package/types/cli/credentials/vc.d.ts.map +1 -1
  242. package/types/cli/endpoints/did.d.ts.map +1 -1
  243. package/types/cli/endpoints/oobi.d.ts +3 -1
  244. package/types/cli/endpoints/oobi.d.ts.map +1 -1
  245. package/types/cli/identity/challenge.d.ts +1 -1
  246. package/types/cli/identity/challenge.d.ts.map +1 -1
  247. package/types/cli/identity/delegate.d.ts +14 -1
  248. package/types/cli/identity/delegate.d.ts.map +1 -1
  249. package/types/cli/identity/incept.d.ts.map +1 -1
  250. package/types/cli/identity/interact.d.ts.map +1 -1
  251. package/types/cli/identity/rotate.d.ts.map +1 -1
  252. package/types/cli/index.d.ts +3 -1
  253. package/types/cli/index.d.ts.map +1 -1
  254. package/types/cli/messaging/group-join.d.ts +56 -0
  255. package/types/cli/messaging/group-join.d.ts.map +1 -0
  256. package/types/cli/messaging/group-wait.d.ts +34 -0
  257. package/types/cli/messaging/group-wait.d.ts.map +1 -0
  258. package/types/cli/messaging/multisig.d.ts +29 -5
  259. package/types/cli/messaging/multisig.d.ts.map +1 -1
  260. package/types/cli/messaging/root-copy-lines.d.ts +39 -0
  261. package/types/cli/messaging/root-copy-lines.d.ts.map +1 -0
  262. package/types/core/cues.d.ts +11 -0
  263. package/types/core/cues.d.ts.map +1 -1
  264. package/types/core/kel/eventing.d.ts.map +1 -1
  265. package/types/core/mailbox/kram-policy.d.ts +14 -0
  266. package/types/core/mailbox/kram-policy.d.ts.map +1 -1
  267. package/types/core/mailbox/kraming.d.ts +1 -1
  268. package/types/core/mailbox/kraming.d.ts.map +1 -1
  269. package/types/core/records.d.ts +61 -0
  270. package/types/core/records.d.ts.map +1 -1
  271. package/types/core/routing.d.ts +6 -0
  272. package/types/core/routing.d.ts.map +1 -1
  273. package/types/db/basing.d.ts +8 -2
  274. package/types/db/basing.d.ts.map +1 -1
  275. package/types/db/core/indexeddb-persistence.d.ts +59 -0
  276. package/types/db/core/indexeddb-persistence.d.ts.map +1 -0
  277. package/types/db/indexeddb.d.ts +37 -0
  278. package/types/db/indexeddb.d.ts.map +1 -0
  279. package/types/db/keeping.d.ts +5 -2
  280. package/types/db/keeping.d.ts.map +1 -1
  281. package/types/db/store-lock.d.ts +72 -0
  282. package/types/db/store-lock.d.ts.map +1 -0
  283. package/types/npm/db-indexeddb.d.ts +4 -0
  284. package/types/npm/db-indexeddb.d.ts.map +1 -0
  285. package/types/npm/runtime-web.d.ts +4 -0
  286. package/types/npm/runtime-web.d.ts.map +1 -0
  287. package/types/runtime/index.d.ts +42 -7
  288. package/types/runtime/index.d.ts.map +1 -1
  289. package/types/runtime/web/output-barrier.d.ts +30 -0
  290. package/types/runtime/web/output-barrier.d.ts.map +1 -0
  291. package/types/runtime/web/persistent-storage.d.ts +36 -0
  292. package/types/runtime/web/persistent-storage.d.ts.map +1 -0
  293. package/types/runtime/web.d.ts +11 -0
  294. package/types/runtime/web.d.ts.map +1 -0
  295. package/types/vdr/tel-publication.d.ts +6 -0
  296. package/types/vdr/tel-publication.d.ts.map +1 -1
  297. package/types/version.d.ts +2 -2
  298. package/esm/keri/npm/src/cli/common/tel-completion.js +0 -24
  299. package/types/cli/common/tel-completion.d.ts +0 -8
  300. package/types/cli/common/tel-completion.d.ts.map +0 -1
@@ -1,158 +1,16 @@
1
- /**
2
- * Delegator-side CLI approval for pending delegated events.
3
- *
4
- * KERIpy correspondence:
5
- * - this is the bounded command analogue of KLI's delegation approval flow
6
- * - pending work is discovered from durable `delegables.` escrow, not from
7
- * controller notifications
8
- *
9
- * Maintainer rule:
10
- * - `/delegate/request` notifications are UI hints only
11
- * - approval ordering and event selection come from the delegated-event escrows
12
- * and the delegator's own KEL state
13
- */
14
- import { Diger } from "cesr-ts";
15
- import { call, race, sleep, spawn } from "effection";
16
- import { runAgentRuntime } from "../../app/runtime/agent-runtime.js";
17
1
  import { ValidationError } from "../../core/errors.js";
18
- import { dgKey } from "../../db/core/keys.js";
19
- import { parseBooleanOption, parseStringListOption, parseStringOption } from "../common/parsing.js";
20
- import { createExchangeMessage } from "../../app/exchanges/exchange-messaging.js";
21
- import { groupSigningMembers, isLocalGroupHab, localGroupMember } from "../../app/identity/endpoint-roleing.js";
2
+ import { parseBooleanOption, parseNumberOption, parseStringListOption, parseStringOption, } from "../common/parsing.js";
3
+ import { approveDelegation, DELEGATION_APPROVAL_TIMEOUT_MS, proposeGroupDelegationApproval, requestDelegatedEvent, settleDelegationApproval, waitForDelegationAnchor, waitForDelegationApproval, waitForPendingDelegation, } from "../../app/identity/delegation-approval.js";
4
+ import { isLocalGroupHab, localGroupMember } from "../../app/identity/endpoint-roleing.js";
22
5
  import { MULTISIG_IXN_ROUTE } from "../../app/multisig/grouping.js";
23
- import { SeqNoQuerier } from "../../app/queries/querying.js";
24
- import { runtimeTurn } from "../../app/runtime/runtime-turn.js";
25
- import { WitnessReceiptor } from "../../app/witness/receipting.js";
26
6
  import { withHabAndAgentRuntime } from "../common/context.js";
7
+ import { withRuntimeWorkers } from "../common/runtime-workers.js";
27
8
  import { resolveWitnessAuths } from "../common/witness-auth.js";
28
- /** Return pending delegated events for one local delegator, oldest first. */
29
- function pendingDelegations(hby, delegatorPre) {
30
- const pending = [];
31
- for (const [keys, said] of hby.db.delegables.getTopItemIter()) {
32
- const pre = keys[0];
33
- if (!pre) {
34
- continue;
35
- }
36
- const serder = hby.db.getEvtSerder(pre, said);
37
- if (!serder) {
38
- continue;
39
- }
40
- const sourcePrefix = delegationSourcePrefix(hby, serder, pre);
41
- if (sourcePrefix !== delegatorPre) {
42
- continue;
43
- }
44
- pending.push(serder);
45
- }
46
- return pending.sort((left, right) => (left.sn ?? 0) - (right.sn ?? 0));
47
- }
48
- /** Determine the delegator prefix for `dip` or `drt` escrow material. */
49
- function delegationSourcePrefix(hby, serder, pre) {
50
- if (serder.delpre) {
51
- return serder.delpre;
52
- }
53
- if (serder.ilk !== "drt") {
54
- return undefined;
55
- }
56
- const delegatedPre = serder.pre ?? pre;
57
- return hby.db.getKever(delegatedPre)?.delpre
58
- ?? hby.db.getState(delegatedPre)?.di;
59
- }
60
- /** Project a delegated event into the seal embedded by the approving event. */
61
- function anchorData(serder) {
62
- if (!serder.pre || !serder.snh || !serder.said) {
63
- throw new ValidationError("Delegated event is missing pre, sn, or said.");
64
- }
65
- return { i: serder.pre, s: serder.snh, d: serder.said };
66
- }
67
- function approvingEvent(hby, serder, delegator) {
68
- return hby.db.fetchLastSealingEventByEventSeal(delegator.pre, anchorData(serder));
69
- }
70
- /** Resolve delegate witnesses for either delegated inception or rotation. */
71
- function delegateWitnesses(hby, serder) {
72
- if ((serder.sn ?? 0) === 0) {
73
- return [...serder.backs];
74
- }
75
- if (!serder.pre) {
76
- return [];
77
- }
78
- return [...(hby.db.getKever(serder.pre)?.wits ?? [])];
79
- }
80
- /** Return true once the delegated event has left escrow and reached local state. */
81
- function delegateCommitted(hby, serder) {
82
- if (!serder.pre) {
83
- return false;
84
- }
85
- const kever = hby.db.getKever(serder.pre);
86
- return kever !== undefined && kever !== null && kever.sn >= (serder.sn ?? 0);
87
- }
88
- /** Build a witness log query used to pull delegate-side completion material. */
89
- function delegateWitnessLogsQuery(hab, serder, witness) {
90
- if (!serder.pre || !serder.snh) {
91
- throw new ValidationError("Delegated event is missing pre or sn for query.");
92
- }
93
- return {
94
- pre: serder.pre,
95
- signer: hab.pre,
96
- src: witness,
97
- route: "logs",
98
- q: { fn: "0", s: serder.snh },
99
- wits: [witness],
100
- };
101
- }
102
- /**
103
- * Publish group delegation approval to remote signing members before advancing the workflow.
104
- *
105
- * @param runtime Borrowed composed runtime; caller owns its worker and store lifetime.
106
- * @param hby Borrowed local identities and accepted-state stores.
107
- * @param groupHab Group approving habitat.
108
- * @param message Signed approving interaction to embed for remote members.
109
- * @returns Successful delivery URLs after each concrete Poster outcome.
110
- */
111
- function* publishGroupDelegationApproval(runtime, hby, groupHab, message) {
112
- const member = localGroupMember(hby, groupHab.pre);
113
- const smids = groupSigningMembers(hby, groupHab.pre);
114
- const deliveries = [];
115
- for (const recipient of smids) {
116
- if (recipient === member.pre || hby.habs.has(recipient)) {
117
- continue;
118
- }
119
- const { msg } = createExchangeMessage(member, {
120
- dest: recipient,
121
- route: MULTISIG_IXN_ROUTE,
122
- payload: { gid: groupHab.pre, smids },
123
- embeds: { ixn: message },
124
- });
125
- const postman = runtime.postman;
126
- const evt = postman.send({ src: member.pre, dest: recipient, topic: "multisig", msg }, { notify: true });
127
- const result = yield* postman.wait(evt);
128
- if (result.kin === "failed")
129
- throw result.error;
130
- deliveries.push(...result.deliveries);
131
- }
132
- return deliveries;
133
- }
134
- function eventAccepted(hby, serder) {
135
- return !!serder.pre && serder.said !== undefined
136
- && hby.db.kels.getLast(serder.pre, serder.sn ?? 0) === serder.said;
137
- }
138
- function pinApprovalSeal(hby, hab, delegated, approving) {
139
- if (!approving.sner || !approving.said || !delegated.pre || !delegated.said) {
140
- throw new ValidationError("Approving event material is incomplete.");
141
- }
142
- hby.db.aess.pin(dgKey(delegated.pre, delegated.said), [
143
- approving.sner,
144
- new Diger({ qb64: approving.said }),
145
- ]);
146
- hab.kvy.processEscrowDelegables();
147
- }
148
- /** Observe approval state while the command's host workers own background progress. */
149
- function* waitForDelegation(done, timeoutMs) {
150
- const deadline = Date.now() + timeoutMs;
151
- while (!done()) {
152
- if (Date.now() >= deadline)
153
- throw new Error(`Runtime did not converge within ${timeoutMs}ms.`);
154
- yield* runtimeTurn();
155
- }
9
+ /** Wall-clock budget for the request and anchor waits; `--timeout` seconds, else the library default. */
10
+ function waitBudgetMs(confirmArgs) {
11
+ return confirmArgs.timeoutSeconds === undefined
12
+ ? DELEGATION_APPROVAL_TIMEOUT_MS
13
+ : confirmArgs.timeoutSeconds * 1000;
156
14
  }
157
15
  /**
158
16
  * Approve pending events without starting or serially driving background workers.
@@ -164,11 +22,12 @@ function* waitForDelegation(done, timeoutMs) {
164
22
  */
165
23
  function* performDelegationApproval(hby, hab, runtime, confirmArgs) {
166
24
  const interactionApproval = confirmArgs.interact ?? false;
167
- yield* waitForDelegation(() => pendingDelegations(hby, hab.pre).length > 0, 15_000);
168
- const pending = pendingDelegations(hby, hab.pre);
169
- if (pending.length === 0) {
170
- throw new ValidationError(`No delegated events are awaiting approval for ${hab.pre}.`);
25
+ const timeoutMs = waitBudgetMs(confirmArgs);
26
+ const waited = yield* waitForPendingDelegation(hby, { delegator: hab.pre }, { timeoutMs });
27
+ if (waited.outcome === "timed-out") {
28
+ throw new ValidationError(`No delegated events are awaiting approval for ${hab.pre} after ${timeoutMs}ms.`);
171
29
  }
30
+ const pending = waited.status;
172
31
  if (pending.length > 1 && !confirmArgs.auto) {
173
32
  throw new ValidationError(`Multiple delegated events are awaiting approval for ${hab.pre}. Re-run with --auto to approve them in order.`);
174
33
  }
@@ -177,109 +36,75 @@ function* performDelegationApproval(hby, hab, runtime, confirmArgs) {
177
36
  promptMissing: confirmArgs.authenticate ?? false,
178
37
  });
179
38
  const selected = confirmArgs.auto ? pending : [pending[0]];
180
- for (const serder of selected) {
181
- const anchor = anchorData(serder);
39
+ const deps = {
40
+ hby,
41
+ protocol: runtime.protocol,
42
+ http: runtime.http,
43
+ clock: runtime.clock,
44
+ querying: runtime.querying,
45
+ };
46
+ for (const request of selected) {
182
47
  if (isLocalGroupHab(hby, hab)) {
183
- if (!interactionApproval) {
184
- throw new ValidationError("Multisig delegated approval currently requires --interact.");
185
- }
186
- const approving = approvingEvent(hby, serder, hab);
187
- if (!approving) {
188
- const created = hby.interactGroupHab(confirmArgs.alias, undefined, { data: [anchor] });
189
- const deliveries = yield* publishGroupDelegationApproval(runtime, hby, created.hab, created.message);
190
- console.log(JSON.stringify({
191
- status: eventAccepted(hby, created.serder) ? "accepted" : "multisig-pending",
192
- route: MULTISIG_IXN_ROUTE,
193
- group: created.hab.pre,
194
- delegated: serder.pre,
195
- said: serder.said,
196
- anchor: created.serder.said,
197
- deliveries,
198
- }));
199
- continue;
200
- }
201
- const witnesses = delegateWitnesses(hby, serder).sort();
202
- const selectedWitness = witnesses[0];
203
- const member = localGroupMember(hby, hab.pre);
204
- pinApprovalSeal(hby, hab, serder, approving);
205
- if (!delegateCommitted(hby, serder) && selectedWitness) {
206
- runtime.querying.enqueue(delegateWitnessLogsQuery(member, serder, selectedWitness));
207
- yield* waitForDelegation(() => delegateCommitted(hby, serder), 30_000);
208
- }
209
- pinApprovalSeal(hby, hab, serder, approving);
210
- if (serder.pre && serder.said) {
211
- const stillPending = hby.db.delegables.get([serder.pre]).includes(serder.said);
212
- if (stillPending) {
213
- throw new ValidationError(`Delegated event ${serder.said} remained in delegables escrow after approval.`);
214
- }
215
- }
216
- console.log(`Approved delegated ${serder.ilk} ${serder.said ?? ""} for ${serder.pre ?? ""} using multisig ixn.`);
48
+ yield* approveGroupDelegation(hby, hab, runtime, confirmArgs, request, auths);
217
49
  continue;
218
50
  }
219
- // KERIpy permits either interaction or rotation approval. Keep this
220
- // explicit because the chosen approving event type affects later
221
- // replay, but the embedded anchor seal is the same.
222
- if (interactionApproval) {
223
- hab.interact({ data: [anchor] });
224
- }
225
- else {
226
- hab.rotate({ data: [anchor] });
227
- }
228
- if (hab.kever?.wits.length) {
229
- const witDoer = new WitnessReceiptor(hby, runtime.protocol, runtime.http, runtime.clock);
230
- yield* witDoer.submit(hab.pre, {
231
- sn: hab.kever.sn,
232
- auths,
233
- });
234
- }
235
- const approving = hby.db.getEvtSerder(hab.pre, hab.kever.said);
236
- if (!approving) {
237
- throw new ValidationError("Approving event material is incomplete.");
238
- }
239
- const witnesses = delegateWitnesses(hby, serder).sort();
240
- const selectedWitness = witnesses[0];
241
- if (selectedWitness) {
242
- // Witnessed delegates must prove the delegated event is committed
243
- // locally before we pin `aess.` and retry delegated unescrow. Doing
244
- // it earlier can make local state look approved but incomplete.
245
- runtime.querying.enqueue(delegateWitnessLogsQuery(hab, serder, selectedWitness));
246
- yield* waitForDelegation(() => delegateCommitted(hby, serder), 30_000);
247
- }
248
- else {
249
- // No delegate witness exists to query. Process the local delegable
250
- // after the delegator has anchored approval; the delegate still
251
- // discovers approval through its own delegator-KEL query path.
252
- pinApprovalSeal(hby, hab, serder, approving);
253
- const observed = yield* race([
254
- call(function* () {
255
- yield* new SeqNoQuerier(hby.db, runtime.querying, serder.pre, serder.sn ?? 0, {
256
- signer: hab.pre,
257
- }).queryDo();
258
- return true;
259
- }),
260
- call(function* () {
261
- yield* sleep(30_000);
262
- return false;
263
- }),
264
- ]);
265
- if (!observed)
266
- throw new Error("Runtime did not converge within 30000ms.");
267
- }
268
- // Match KERIpy sequencing: only record the approving seal and retry
269
- // delegated unescrow after the delegate event has been observed as
270
- // locally committed through the witness-backed query/replay path.
271
- if (selectedWitness) {
272
- pinApprovalSeal(hby, hab, serder, approving);
51
+ yield* approveDelegation(deps, request, {
52
+ event: interactionApproval ? "ixn" : "rot",
53
+ auths,
54
+ });
55
+ const result = yield* waitForDelegationApproval({ db: hby.db, settle: () => settleDelegationApproval(deps, request) }, request, { timeoutMs: 30_000 });
56
+ if (result.outcome === "timed-out") {
57
+ throw new Error(`Runtime did not converge within ${result.timeoutMs}ms.`);
273
58
  }
274
- if (serder.pre && serder.said) {
275
- const stillPending = hby.db.delegables.get([serder.pre]).includes(serder.said);
276
- if (stillPending) {
277
- throw new ValidationError(`Delegated event ${serder.said} remained in delegables escrow after approval.`);
278
- }
59
+ if (hby.db.delegables.get([request.delegate]).includes(request.said)) {
60
+ throw new ValidationError(`Delegated event ${request.said} remained in delegables escrow after approval.`);
279
61
  }
280
- console.log(`Approved delegated ${serder.ilk} ${serder.said ?? ""} for ${serder.pre ?? ""} using ${interactionApproval ? "ixn" : "rot"}.`);
62
+ console.log(`Approved delegated ${request.ilk} ${request.said} for ${request.delegate} using ${interactionApproval ? "ixn" : "rot"}.`);
281
63
  }
282
64
  }
65
+ /**
66
+ * Group delegator approval: propose the anchoring interaction the first time; once the
67
+ * group's KEL holds the anchor (the other members approved it), ask for the delegate's event.
68
+ */
69
+ function* approveGroupDelegation(hby, hab, runtime, confirmArgs, request, auths) {
70
+ if (!confirmArgs.interact) {
71
+ throw new ValidationError("Multisig delegated approval currently requires --interact.");
72
+ }
73
+ const deps = {
74
+ hby,
75
+ protocol: runtime.protocol,
76
+ http: runtime.http,
77
+ clock: runtime.clock,
78
+ querying: runtime.querying,
79
+ };
80
+ const timeoutMs = waitBudgetMs(confirmArgs);
81
+ const sent = yield* proposeGroupDelegationApproval({ hby, protocol: runtime.protocol, postman: runtime.postman, counselor: runtime.counselor }, request, { auths, fallbackAfterMs: 0 });
82
+ if (sent) {
83
+ console.log(JSON.stringify({
84
+ status: hby.db.kels.getLast(sent.group, sent.event.sn) === sent.event.said ? "accepted" : "multisig-pending",
85
+ route: MULTISIG_IXN_ROUTE,
86
+ group: sent.group,
87
+ delegated: request.delegate,
88
+ said: request.said,
89
+ anchor: sent.event.said,
90
+ deliveries: sent.deliveries,
91
+ }));
92
+ return;
93
+ }
94
+ const anchored = yield* waitForDelegationAnchor({ db: hby.db }, request, { timeoutMs });
95
+ if (anchored.outcome === "timed-out") {
96
+ throw new ValidationError(`The anchor for delegated ${request.ilk} ${request.said} was not accepted and receipted by ${hab.pre} within ${timeoutMs}ms. `
97
+ + "The other members must approve the proposal first.");
98
+ }
99
+ requestDelegatedEvent(deps, request, localGroupMember(hby, hab.pre).pre);
100
+ const result = yield* waitForDelegationApproval({ db: hby.db, settle: () => settleDelegationApproval(deps, request) }, request, { timeoutMs: 30_000 });
101
+ if (result.outcome === "timed-out")
102
+ throw new Error(`Runtime did not converge within ${result.timeoutMs}ms.`);
103
+ if (hby.db.delegables.get([request.delegate]).includes(request.said)) {
104
+ throw new ValidationError(`Delegated event ${request.said} remained in delegables escrow after approval.`);
105
+ }
106
+ console.log(`Approved delegated ${request.ilk} ${request.said} for ${request.delegate} using multisig ixn.`);
107
+ }
283
108
  /** Approve pending delegated events for the selected local delegator habitat. */
284
109
  export function* delegateConfirmCommand(args) {
285
110
  const confirmArgs = {
@@ -294,7 +119,11 @@ export function* delegateConfirmCommand(args) {
294
119
  authenticate: parseBooleanOption(args.authenticate, "authenticate"),
295
120
  code: parseStringListOption(args.code, "code"),
296
121
  codeTime: parseStringOption(args.codeTime, "codeTime"),
122
+ timeoutSeconds: parseNumberOption(args.timeout, "timeout"),
297
123
  };
124
+ if (confirmArgs.timeoutSeconds !== undefined && !(confirmArgs.timeoutSeconds >= 0)) {
125
+ throw new ValidationError("timeout must not be negative");
126
+ }
298
127
  if (!confirmArgs.name) {
299
128
  throw new ValidationError("Name is required and cannot be empty");
300
129
  }
@@ -311,12 +140,6 @@ export function* delegateConfirmCommand(args) {
311
140
  throw new ValidationError(`Missing accepted key state for ${hab.pre}.`);
312
141
  }
313
142
  const signer = isLocalGroupHab(hby, hab) ? localGroupMember(hby, hab.pre) : hab;
314
- const worker = yield* spawn(() => runAgentRuntime(runtime, { hab: signer }));
315
- try {
316
- yield* performDelegationApproval(hby, hab, runtime, confirmArgs);
317
- }
318
- finally {
319
- yield* worker.halt();
320
- }
143
+ yield* withRuntimeWorkers(runtime, { hab: signer }, () => performDelegationApproval(hby, hab, runtime, confirmArgs));
321
144
  });
322
145
  }
@@ -1,14 +1,11 @@
1
1
  import { call } from "effection";
2
2
  import { resolveBootstrap } from "../../app/bootstrap/bootstrapping.js";
3
- import { createProtocolProcessor } from "../../app/protocol/protocol-processing.js";
4
- import { createAgentRuntime, runAgentRuntimeUntil, } from "../../app/runtime/agent-runtime.js";
5
- import { systemClock } from "../../app/runtime/runtime-clock.js";
6
3
  import { NodeHttpClient } from "../../app/transport/node-http-client.js";
7
4
  import { ValidationError } from "../../core/errors.js";
8
5
  import { assertBootstrapComplete } from "../common/bootstrap.js";
9
6
  import { createConfiger } from "../../app/identity/configing.js";
10
7
  import { resolveDelegationCommunicationHab } from "../../app/identity/delegating.js";
11
- import { Receiptor, WitnessReceiptor } from "../../app/witness/receipting.js";
8
+ import { cliEventCompletionDeps, completeEventOrThrow } from "../common/event-completion.js";
12
9
  import { setupHby } from "../common/existing.js";
13
10
  import { loadInceptFileOptions, parseBooleanOption, parseCountOption, parseDataItems, parseKeriVersionOption, parseStringListOption, parseStringOption, parseThresholdOption, } from "../common/parsing.js";
14
11
  /**
@@ -121,34 +118,20 @@ export function* inceptCommand(args) {
121
118
  delpre: opts.delpre,
122
119
  version: inceptArgs.version,
123
120
  });
124
- if (hab.kever?.wits.length) {
125
- if (inceptArgs.endpoint) {
126
- const receiptor = new Receiptor(hby, createProtocolProcessor(hby), http, systemClock);
127
- yield* receiptor.receipt(hab.pre, { sn: 0 });
128
- }
129
- else {
130
- const witDoer = new WitnessReceiptor(hby, createProtocolProcessor(hby), http, systemClock);
131
- yield* witDoer.submit(hab.pre, { sn: 0 });
132
- }
133
- }
134
- let delegationPhase = null;
135
- if (opts.delpre) {
136
- const communicationHab = resolveDelegationCommunicationHab(hby, inceptArgs.proxy);
137
- if (!communicationHab) {
138
- throw new ValidationError(`Delegated inception for ${hab.pre} requires --proxy <alias>.`);
139
- }
140
- const runtime = yield* createAgentRuntime(hby, http, systemClock);
141
- try {
142
- runtime.delegating.beginLatest(hab.pre, 0, {
143
- communicationHab,
144
- });
145
- yield* runAgentRuntimeUntil(runtime, () => runtime.delegating.complete(hab.pre, 0), { hab, timeoutMs: 120_000, pollMailbox: true });
146
- delegationPhase = runtime.delegating.workflowStatus(hab.pre, "0").phase;
147
- }
148
- finally {
149
- yield* runtime.close();
150
- }
151
- }
121
+ const { delegationPhase } = yield* completeEventOrThrow(cliEventCompletionDeps(hby, http), hab, 0, {
122
+ endpoint: inceptArgs.endpoint,
123
+ delegation: opts.delpre
124
+ ? {
125
+ communicationHab: () => {
126
+ const communicationHab = resolveDelegationCommunicationHab(hby, inceptArgs.proxy);
127
+ if (!communicationHab) {
128
+ throw new ValidationError(`Delegated inception for ${hab.pre} requires --proxy <alias>.`);
129
+ }
130
+ return communicationHab;
131
+ },
132
+ }
133
+ : undefined,
134
+ });
152
135
  const state = hby.db.getState(hab.pre);
153
136
  return { prefix: hab.pre, keys: state?.k ?? [], delegationPhase };
154
137
  }
@@ -1,10 +1,8 @@
1
- import { createProtocolProcessor } from "../../app/protocol/protocol-processing.js";
2
- import { systemClock } from "../../app/runtime/runtime-clock.js";
3
1
  import { NodeHttpClient } from "../../app/transport/node-http-client.js";
4
2
  import { isLocalGroupHab } from "../../app/multisig/group-members.js";
5
- import { Receiptor, WitnessReceiptor } from "../../app/witness/receipting.js";
6
3
  import { ValidationError } from "../../core/errors.js";
7
4
  import { withExistingHab } from "../common/context.js";
5
+ import { cliEventCompletionDeps, completeEventOrThrow } from "../common/event-completion.js";
8
6
  import { parseBooleanOption, parseDataItems, parseKeriVersionOption, parseStringListOption, parseStringOption, } from "../common/parsing.js";
9
7
  import { resolveWitnessAuths } from "../common/witness-auth.js";
10
8
  /**
@@ -59,20 +57,10 @@ export function* interactCommand(args) {
59
57
  codeTime: interactArgs.codeTime,
60
58
  promptMissing: interactArgs.authenticate ?? false,
61
59
  });
62
- if (interactArgs.endpoint) {
63
- const receiptor = new Receiptor(hby, createProtocolProcessor(hby), http, systemClock);
64
- yield* receiptor.receipt(hab.pre, {
65
- sn: hab.kever.sn,
66
- auths,
67
- });
68
- }
69
- else {
70
- const witDoer = new WitnessReceiptor(hby, createProtocolProcessor(hby), http, systemClock);
71
- yield* witDoer.submit(hab.pre, {
72
- sn: hab.kever.sn,
73
- auths,
74
- });
75
- }
60
+ yield* completeEventOrThrow(cliEventCompletionDeps(hby, http), hab, hab.kever.sn, {
61
+ auths,
62
+ endpoint: interactArgs.endpoint,
63
+ });
76
64
  }
77
65
  const state = hby.db.getState(hab.pre);
78
66
  console.log(`Prefix ${hab.pre}`);
@@ -1,12 +1,9 @@
1
- import { createProtocolProcessor } from "../../app/protocol/protocol-processing.js";
2
- import { systemClock } from "../../app/runtime/runtime-clock.js";
3
1
  import { NodeHttpClient } from "../../app/transport/node-http-client.js";
4
- import { createAgentRuntime, runAgentRuntimeUntil, } from "../../app/runtime/agent-runtime.js";
5
2
  import { ValidationError } from "../../core/errors.js";
6
3
  import { resolveDelegationCommunicationHab } from "../../app/identity/delegating.js";
7
4
  import { isLocalGroupHab } from "../../app/multisig/group-members.js";
8
- import { Receiptor, WitnessReceiptor } from "../../app/witness/receipting.js";
9
5
  import { withExistingHab } from "../common/context.js";
6
+ import { cliEventCompletionDeps, completeEventOrThrow } from "../common/event-completion.js";
10
7
  import { loadRotateFileOptions, parseBooleanOption, parseCountOption, parseDataItems, parseKeriVersionOption, parseStringListOption, parseStringOption, parseThresholdOption, } from "../common/parsing.js";
11
8
  import { resolveWitnessAuths } from "../common/witness-auth.js";
12
9
  /** Empty baseline used before CLI/file precedence is applied. */
@@ -127,38 +124,13 @@ export function* rotateCommand(args, { witnessAuths } = {}) {
127
124
  data: options.data ?? [],
128
125
  version: rotateArgs.version,
129
126
  });
130
- if (hab.kever?.wits.length) {
131
- if (rotateArgs.endpoint) {
132
- const receiptor = new Receiptor(hby, createProtocolProcessor(hby), http, systemClock);
133
- yield* receiptor.receipt(hab.pre, {
134
- sn: hab.kever.sn,
135
- auths,
136
- });
137
- }
138
- else {
139
- const witDoer = new WitnessReceiptor(hby, createProtocolProcessor(hby), http, systemClock);
140
- yield* witDoer.submit(hab.pre, {
141
- sn: hab.kever.sn,
142
- auths,
143
- });
144
- }
145
- }
146
- let delegationPhase = null;
147
- if (kever.delpre !== null && hab.kever) {
148
- const communicationHab = resolveDelegationCommunicationHab(hby, rotateArgs.proxy);
149
- const runtime = yield* createAgentRuntime(hby, http, systemClock);
150
- try {
151
- runtime.delegating.beginLatest(hab.pre, hab.kever.sn, {
152
- communicationHab,
153
- });
154
- const snh = hab.kever.sn.toString(16);
155
- yield* runAgentRuntimeUntil(runtime, () => runtime.delegating.complete(hab.pre, hab.kever.sn), { hab, timeoutMs: 120_000, pollMailbox: true });
156
- delegationPhase = runtime.delegating.workflowStatus(hab.pre, snh).phase;
157
- }
158
- finally {
159
- yield* runtime.close();
160
- }
161
- }
127
+ const { delegationPhase } = yield* completeEventOrThrow(cliEventCompletionDeps(hby, http), hab, hab.kever.sn, {
128
+ auths,
129
+ endpoint: rotateArgs.endpoint,
130
+ delegation: kever.delpre !== null && hab.kever
131
+ ? { communicationHab: () => resolveDelegationCommunicationHab(hby, rotateArgs.proxy) }
132
+ : undefined,
133
+ });
162
134
  const state = hby.db.getState(hab.pre);
163
135
  console.log(`Prefix ${hab.pre}`);
164
136
  console.log(`New Sequence No. ${hab.kever?.sn ?? state?.s ?? ""}`);
@@ -8,8 +8,9 @@
8
8
  export { parseGvrsn } from "../core/attachment-countering.js";
9
9
  export { withAgentRuntime, withExistingHab, withExistingHabery, withHabAndAgentRuntime, } from "./common/context.js";
10
10
  export { ensureHby, setupHby } from "./common/existing.js";
11
- export { parseBooleanOption, parseCountOption, parseIntegerOption, parseNumberOption, parseStringListOption, parseStringOption, } from "./common/parsing.js";
11
+ export { parseBooleanOption, parseCountOption, parseIntegerOption, parseKeriVersionOption, parseNumberOption, parseStringListOption, parseStringOption, } from "./common/parsing.js";
12
12
  export { writeJsonLine, writeTextLines } from "./common/rendering.js";
13
+ export { withRuntimeWorkers } from "./common/runtime-workers.js";
13
14
  export { resolveWitnessAuths } from "./common/witness-auth.js";
14
15
  export { ipexAdmitCommand, ipexAgreeCommand, ipexApplyCommand, ipexGrantCommand, ipexJoinCommand, ipexListCommand, ipexOfferCommand, ipexPollCommand, ipexSpurnCommand, joinIpexProposal, } from "./credentials/ipex.js";
15
16
  export { vcCreateCommand, vcExportCommand, vcImportCommand, vcListCommand, vcRegistryInceptCommand, vcRegistryListCommand, vcRegistryStatusCommand, vcRevokeCommand, vcSchemaImportCommand, } from "./credentials/vc.js";
@@ -30,6 +31,7 @@ export { rotateCommand } from "./identity/rotate.js";
30
31
  export { exchangeSendCommand } from "./messaging/exchange.js";
31
32
  export { multisigInceptCommand, multisigInteractCommand, multisigJoinCommand, multisigRotateCommand, multisigRpyCommand, } from "./messaging/multisig.js";
32
33
  export { notificationsListCommand, notificationsMarkReadCommand, notificationsRemoveCommand, } from "./messaging/notifications.js";
34
+ export { rootCopyLine, RootCopyRecoveryCommand, rootResealLine, } from "./messaging/root-copy-lines.js";
33
35
  export { annotateCommand } from "./tools/annotate.js";
34
36
  export { benchmarkCommand } from "./tools/benchmark.js";
35
37
  export { dumpEvts } from "./tools/db-dump.js";
@@ -0,0 +1,83 @@
1
+ /**
2
+ * `tufa multisig join` proposal selection, as KERIpy `kli multisig join`.
3
+ *
4
+ * Join approves exactly one stored proposal, the first the user consents to:
5
+ * - an explicit `--said` names the proposal, otherwise the unapproved proposals
6
+ * the notice store announces are offered in notice order; `--kind` restricts the
7
+ * offer (and a `--said`) to one proposal kind, so a join never signs another kind;
8
+ * - without `--auto` every offered proposal is shown and approved only on a yes;
9
+ * - with `--auto` the first offered proposal is approved without a prompt. This is
10
+ * the whole of auto consent: it exists only inside the `join` the user ran for
11
+ * that purpose, and no other command signs a proposal it was not asked to sign.
12
+ *
13
+ * Signing, publication and the Counselor hand-off belong to `approveGroupProposal`.
14
+ */
15
+ import { sleep } from "effection";
16
+ import { approveGroupProposal, dismissGroupProposal, findGroupProposal, listGroupProposals, } from "../../app/multisig/proposals.js";
17
+ import { ValidationError } from "../../core/errors.js";
18
+ /** Group prefix for a joined group's prefix or alias; undefined for a name not yet used. */
19
+ function joinedGroup(hby, group) {
20
+ return group === undefined ? undefined : (hby.habByName(group) ?? hby.habs.get(group))?.pre ?? undefined;
21
+ }
22
+ /** Candidates for one pass, oldest first. */
23
+ function candidates(deps, { said, group, kind }) {
24
+ const wanted = joinedGroup(deps.hby, group);
25
+ if (said !== undefined) {
26
+ const proposal = findGroupProposal(deps, said);
27
+ if (proposal && kind !== undefined && proposal.kind !== kind) {
28
+ throw new ValidationError(`Multisig exchange ${said} is a ${proposal.kind} proposal, not ${kind}.`);
29
+ }
30
+ if (proposal && wanted !== undefined && proposal.group !== wanted) {
31
+ throw new ValidationError(`Multisig exchange ${said} belongs to group ${proposal.group}, not ${wanted}.`);
32
+ }
33
+ return proposal ? [proposal] : [];
34
+ }
35
+ return listGroupProposals(deps, wanted === undefined ? {} : { group: wanted })
36
+ .filter(proposal => proposal.local === "unapproved" && (kind === undefined || proposal.kind === kind));
37
+ }
38
+ /**
39
+ * Approve the first proposal the user consents to, polling stored proposals until
40
+ * the deadline. A declined proposal is not offered again by this call. Returns
41
+ * null when nothing was approved; the host owns the runtime that delivers new
42
+ * proposals while this waits.
43
+ */
44
+ export function* joinProposal(deps, options) {
45
+ if (!deps.notifier && options.said === undefined) {
46
+ throw new ValidationError("Multisig join requires notification storage or an explicit exchange SAID.");
47
+ }
48
+ const skipped = new Set();
49
+ while (true) {
50
+ for (const proposal of candidates(deps, options)) {
51
+ if (skipped.has(proposal.said))
52
+ continue;
53
+ // An explicit proposal already approved here is replayed without asking again.
54
+ if (proposal.local !== "approved" && !options.confirm(proposal)) {
55
+ skipped.add(proposal.said);
56
+ continue;
57
+ }
58
+ const choices = { ...options.inputs(proposal) };
59
+ if (proposal.needs.groupAlias)
60
+ choices.groupAlias = options.groupAlias(proposal);
61
+ if (proposal.needs.registryName)
62
+ choices.registryName = options.registryName(proposal);
63
+ let result;
64
+ try {
65
+ result = yield* approveGroupProposal(deps, proposal.said, choices);
66
+ }
67
+ catch (error) {
68
+ // A proposal that cannot be approved never hides a later one; an explicit SAID reports why.
69
+ if (options.said === undefined && error instanceof ValidationError) {
70
+ skipped.add(proposal.said);
71
+ continue;
72
+ }
73
+ throw error;
74
+ }
75
+ dismissGroupProposal(deps, proposal.said);
76
+ return { proposal, result };
77
+ }
78
+ const remaining = options.deadline - Date.now();
79
+ if (remaining <= 0)
80
+ return null;
81
+ yield* sleep(Math.min(250, remaining));
82
+ }
83
+ }