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,13 +1,20 @@
1
1
  /**
2
- * Explicitly approved IPEX Unblind, following Python's local query/reply profile.
2
+ * IPEX Unblind, following Python's local query/reply profile.
3
3
  * Only event openings cross this boundary. Roots, application state vocabulary,
4
4
  * transport and final Admit remain with their existing owners.
5
+ *
6
+ * Consent: the disclosee explicitly approves (`approve`/`start`) the Grant it requests proofs for.
7
+ * The discloser has no separate approval step: it consented by signing the presentation Grant, so an
8
+ * authenticated query for a live Grant this identifier sent is answered automatically, bounded by that
9
+ * Grant's registry scope and original deadline. The rule is decided from stored state, so it survives a
10
+ * restart. KERIpy's `Unblind` keeps its own local approve gate; that is local policy and the wire is
11
+ * unchanged.
5
12
  */
6
13
  import { bytesEqual, concatBytes, Counter, Diger, Kinds, makeBlindUuid, NumberPrimitive, parseAttachmentGroup, parseBytes, SealSource, SerderACDC, unblindBlindState, Vrsn_2_0, } from "cesr-ts";
7
14
  import { Hab } from "../app/identity/habbing.js";
8
15
  import { IpexV2Handler } from "../app/ipex/ipex-v2.js";
9
16
  import { isLocalGroupHab, latestGroupContribution, localGroupMember } from "../app/multisig/group-members.js";
10
- import { copyAuxiliaryQuery, envelopeFromFrame, } from "../app/protocol/parsering.js";
17
+ import { auxiliaryQueryWire, envelopeFromFrame, restoreAuxiliaryQuery, } from "../app/protocol/parsering.js";
11
18
  import { abortable } from "../app/runtime/abortable.js";
12
19
  import { Deck } from "../core/deck.js";
13
20
  import { TransIdxSigGroup } from "../core/dispatch.js";
@@ -18,9 +25,10 @@ import { query, reply } from "../core/protocol-eventing.js";
18
25
  import { messagize } from "../core/protocol-serialization.js";
19
26
  import { fetchStoredTsgs, unverifiedReplyDecision } from "../core/routing.js";
20
27
  import { prepareNests, publishNests } from "../db/exchange/exchange-nests.js";
21
- import { timestampMicros } from "../time/mod.js";
22
28
  import { validateUpdate, verifyRegistryAnchor, vet, vetBlind, vetBound, } from "./regeventing.js";
23
29
  import { publicOpeningAttachment } from "./registering.js";
30
+ /** Ordinary registry states an Unblind operation may reveal unless its approval names others. */
31
+ export const DEFAULT_UNBLIND_STATES = Object.freeze(["issued", "revoked", ""]);
24
32
  /** Compare registry selections without treating JSON dictionary order as authority. */
25
33
  function sameSelection(left, right) {
26
34
  return Object.keys(left).length === Object.keys(right).length
@@ -48,8 +56,8 @@ function ordinal(event) {
48
56
  * from the completed aggregate; neither contribution nor delivery requires a root.
49
57
  */
50
58
  export class Unblind {
51
- /** Bind the exact Grant verifier's store and an explicit ordinary-state vocabulary. */
52
- constructor({ hab, exc, registry, states, rvy = hab.rvy, now = Date.now }) {
59
+ /** Bind the exact Grant verifier's store; the state vocabulary is chosen per approved operation. */
60
+ constructor({ hab, exc, registry, rvy = hab.rvy, kram = true }) {
53
61
  Object.defineProperty(this, "resource", {
54
62
  enumerable: true,
55
63
  configurable: true,
@@ -62,23 +70,18 @@ export class Unblind {
62
70
  writable: true,
63
71
  value: new Deck()
64
72
  });
65
- Object.defineProperty(this, "pendingQueries", {
73
+ Object.defineProperty(this, "operations", {
66
74
  enumerable: true,
67
75
  configurable: true,
68
76
  writable: true,
69
77
  value: new Map()
70
78
  });
71
- Object.defineProperty(this, "now", {
72
- enumerable: true,
73
- configurable: true,
74
- writable: true,
75
- value: void 0
76
- });
77
- Object.defineProperty(this, "operations", {
79
+ /** Whether the persisted requests this identifier owes replies to were taken up by this owner. */
80
+ Object.defineProperty(this, "restored", {
78
81
  enumerable: true,
79
82
  configurable: true,
80
83
  writable: true,
81
- value: new Map()
84
+ value: false
82
85
  });
83
86
  Object.defineProperty(this, "hab", {
84
87
  enumerable: true,
@@ -104,18 +107,19 @@ export class Unblind {
104
107
  writable: true,
105
108
  value: void 0
106
109
  });
107
- Object.defineProperty(this, "states", {
110
+ Object.defineProperty(this, "group", {
108
111
  enumerable: true,
109
112
  configurable: true,
110
113
  writable: true,
111
114
  value: void 0
112
115
  });
113
- Object.defineProperty(this, "group", {
116
+ Object.defineProperty(this, "kram", {
114
117
  enumerable: true,
115
118
  configurable: true,
116
119
  writable: true,
117
120
  value: void 0
118
121
  });
122
+ this.kram = kram;
119
123
  if (!(hab instanceof Hab) || hab.db !== exc.hby.db || registry.db !== hab.db || rvy.db !== hab.db
120
124
  || exc.hby.habs.get(hab.pre) !== hab) {
121
125
  throw new ValidationError("Unblind requires a local signing habitat");
@@ -123,19 +127,24 @@ export class Unblind {
123
127
  this.group = isLocalGroupHab(exc.hby, hab);
124
128
  if (this.group)
125
129
  localGroupMember(exc.hby, hab.pre);
126
- if (!Array.isArray(states) || states.some((state) => typeof state !== "string")) {
127
- throw new ValidationError("Unblind requires an explicit sequence of state strings");
128
- }
129
- this.now = now;
130
130
  this.hab = hab;
131
131
  this.exc = exc;
132
132
  this.rvy = rvy;
133
133
  this.registry = registry;
134
- this.states = [...states];
135
134
  }
136
- /** Freeze one authenticated live Grant's exact bodies, parties and authorized registry scope. */
137
- approve(grant) {
138
- this.pruneQueries();
135
+ /**
136
+ * Freeze one authenticated live Grant's exact bodies, parties, authorized registry scope and
137
+ * ordinary-state vocabulary. `states` defaults to the registry-root triple and applies to this
138
+ * operation only; approving the same Grant again with different explicit states is refused,
139
+ * while omitting `states` on a repeat approval keeps the frozen vocabulary.
140
+ */
141
+ approve(grant, options = {}) {
142
+ if (!this.kram)
143
+ throw new ValidationError("Unblind requires KRAM: enable it with the runtime's kram option");
144
+ const states = options.states ?? DEFAULT_UNBLIND_STATES;
145
+ if (!Array.isArray(states) || states.some((state) => typeof state !== "string")) {
146
+ throw new ValidationError("Unblind requires an explicit sequence of state strings");
147
+ }
139
148
  const input = this.exc.retainedInput(grant);
140
149
  if (!input)
141
150
  throw new ValidationError("Unblind requires an authenticated retained Grant");
@@ -152,6 +161,10 @@ export class Unblind {
152
161
  if (existing) {
153
162
  if (existing.grant !== grant)
154
163
  throw new ValidationError("Another Grant is selected for this transaction");
164
+ if (options.states
165
+ && (existing.states.length !== states.length || existing.states.some((state, i) => state !== states[i]))) {
166
+ throw new ValidationError("Unblind operation already approved with different states");
167
+ }
155
168
  this.live(existing);
156
169
  return xid;
157
170
  }
@@ -171,18 +184,18 @@ export class Unblind {
171
184
  requested: null,
172
185
  selected: null,
173
186
  openings: new Map(),
187
+ states: [...states],
174
188
  requestedByPeer: false,
175
189
  received: false,
176
190
  abandoned: false,
177
191
  proposal: null,
178
192
  contribution: null,
179
193
  });
180
- this.replayQuery(xid);
181
194
  return xid;
182
195
  }
183
196
  /** Freeze a signed disclosee query over the missing accepted public suffix. */
184
- start(grant) {
185
- const op = this.operation(this.approve(grant));
197
+ start(grant, options = {}) {
198
+ const op = this.operation(this.approve(grant, options));
186
199
  if (this.hab.pre !== op.recipient)
187
200
  throw new ValidationError("Only the disclosee starts Unblind");
188
201
  if (!op.query && !op.contribution) {
@@ -312,7 +325,6 @@ export class Unblind {
312
325
  }
313
326
  /** Authenticate the full peer threshold before public evidence intake or proof release. */
314
327
  processQuery(envelope) {
315
- this.pruneQueries();
316
328
  try {
317
329
  const { serder } = envelope;
318
330
  if (serder.ilk !== "qry" || serder.sad.rr !== Unblind.Route)
@@ -321,8 +333,10 @@ export class Unblind {
321
333
  const own = this.group && serder.pre === this.hab.pre;
322
334
  const xid = serder.sad?.q?.x;
323
335
  if (!own && typeof xid === "string" && !this.operations.has(xid)) {
324
- this.retainQuery(envelope);
325
- return { kind: "accept" };
336
+ // The discloser consented by signing the Grant: answer an authenticated query for a live one it sent.
337
+ if (!verifyQueryAttachments(this.hab.db, envelope))
338
+ return { kind: "drop", reason: "missingAuthentication" };
339
+ this.approve(this.sentGrant(serder.pre, xid));
326
340
  }
327
341
  const { op, selected } = this.preflight(serder, "q", own ? "recipient" : "sender", own);
328
342
  if (own && (!op.proposal || !bytesEqual(op.proposal, serder.raw))) {
@@ -354,6 +368,9 @@ export class Unblind {
354
368
  this.live(op);
355
369
  op.requested = selected;
356
370
  op.requestedByPeer = true;
371
+ // KRAM now holds this query as seen, so a resend of it is a replay and a group cannot re-date it: the
372
+ // owed reply must outlive this owner. The accepted request is the durable record; the operation is a cache.
373
+ this.hab.db.heldu.pin([this.hab.pre, op.xid], auxiliaryQueryWire(envelope, this.publicEvents(envelope.nests)));
357
374
  if (!this.group)
358
375
  this.respond(op.xid);
359
376
  return { kind: "accept" };
@@ -364,6 +381,30 @@ export class Unblind {
364
381
  throw error;
365
382
  }
366
383
  }
384
+ /**
385
+ * Take up the requests this identifier owes a reply to after its owner was lost: each persisted request is
386
+ * processed again as when first accepted, and one that no longer holds (the Grant ended, its evidence changed)
387
+ * is dropped. Done once per owner, before the first look at what is owed.
388
+ */
389
+ restoreHeld() {
390
+ if (this.restored)
391
+ return;
392
+ this.restored = true;
393
+ for (const [[, xid], wire] of [...this.hab.db.heldu.getTopItemIter([this.hab.pre])]) {
394
+ if (this.operations.has(xid))
395
+ continue;
396
+ let decision;
397
+ try {
398
+ decision = this.processQuery(restoreAuxiliaryQuery(wire));
399
+ }
400
+ catch (error) {
401
+ if (!(error instanceof ValidationError))
402
+ throw error;
403
+ }
404
+ if (decision?.kind !== "accept")
405
+ this.hab.db.heldu.rem([this.hab.pre, xid]);
406
+ }
407
+ }
367
408
  /** Schedule responder work only after the selected live operation authenticates its peer query. */
368
409
  hasPeerQuery(xid) {
369
410
  const op = this.operation(xid);
@@ -558,9 +599,11 @@ export class Unblind {
558
599
  }
559
600
  /** Discard approved work and unsent replies; delivered bytes remain caller-owned. */
560
601
  abandon(xid) {
561
- const retained = this.pendingQueries.delete(xid);
562
- if (retained && !this.operations.has(xid))
563
- return;
602
+ this.forget(xid);
603
+ this.hab.db.heldu.rem([this.hab.pre, xid]);
604
+ }
605
+ /** Drop an operation's process-local approval, messages and openings; a persisted request stays. */
606
+ forget(xid) {
564
607
  const op = this.operation(xid);
565
608
  const keep = [...this.outgoing].filter(item => ![op.query, op.reply, op.contribution]
566
609
  .some(wire => wire && bytesEqual(item.msg, wire)));
@@ -608,75 +651,55 @@ export class Unblind {
608
651
  throw new ValidationError("Grant already carries the current openings");
609
652
  return { requested, children };
610
653
  }
654
+ /**
655
+ * Whether this local habitat is the party of Unblind transaction `xid` with `sender`.
656
+ *
657
+ * Messages carry no recipient, so a per-identifier registry selects the owner by transaction:
658
+ * an approved operation here, a stored Grant from this habitat addressed to `sender`, or, for a
659
+ * group, its own members' contributions, which KRAM must pool before this owner consents.
660
+ */
661
+ inTransaction(sender, xid) {
662
+ return this.operations.has(xid) || (this.group && sender === this.hab.pre)
663
+ || Unblind.recipients(this.hab.db, this.hab.pre, xid).includes(sender);
664
+ }
665
+ /** Recipients of the Grants `pre` sent in transaction `xid`, from KRAM-accepted store rows. */
666
+ static recipients(db, pre, xid) {
667
+ const recipients = [];
668
+ for (const [key] of db.tmsc.getTopItemIter([pre, xid])) {
669
+ const grant = db.exns.get([key[2]]) ?? db.epse.get([key[2]]);
670
+ if (grant?.pre === pre && typeof grant.sad?.ri === "string")
671
+ recipients.push(grant.sad.ri);
672
+ }
673
+ return recipients;
674
+ }
611
675
  /** Release all process-local approvals, opening references and retry bytes without changing stores. */
612
676
  close() {
613
677
  for (const xid of this.operations.keys())
614
- this.abandon(xid);
678
+ this.forget(xid);
615
679
  this.operations.clear();
616
- this.pendingQueries.clear();
617
680
  this.outgoing.clear();
618
681
  }
619
- /** Hold one authenticated public suffix for explicit release consent; never import events here. */
620
- retainQuery(envelope) {
621
- const query = envelope.serder, data = this.parameters(query, "q");
622
- if (!verifyQueryAttachments(this.hab.db, envelope))
623
- throw new ValidationError("Unauthenticated Unblind query");
624
- const candidates = [...this.hab.db.tmsc.getTopItemIter([this.hab.pre, data.x])]
682
+ /** The one live Grant this identifier sent to `recipient` in exchange `xid`, from KRAM-accepted store rows. */
683
+ sentGrant(recipient, xid) {
684
+ const said = [...this.hab.db.tmsc.getTopItemIter([this.hab.pre, xid])]
625
685
  .map(([key]) => this.hab.db.exns.get([key[2]]) ?? this.hab.db.epse.get([key[2]]))
626
- .filter(grant => grant && grant.pre === this.hab.pre && grant.sad.ri === query.pre
627
- && this.exc.presentationContext(grant.said, { xid: data.x, sender: this.hab.pre, recipient: query.pre }));
628
- if (candidates.length !== 1)
629
- throw new ValidationError("Unblind query has no unique authenticated Grant");
630
- const grant = candidates[0];
631
- const context = this.exc.presentationContext(grant.said, {
632
- xid: data.x,
633
- sender: this.hab.pre,
634
- recipient: query.pre,
635
- });
636
- const selected = this.selection(data.re, context.registries, "q");
637
- this.validateEvents(selected, envelope.nests);
638
- const expires = this.retainUntil(envelope, grant);
639
- const prior = this.pendingQueries.get(data.x);
640
- if (prior && !bytesEqual(prior.envelope.serder.raw, query.raw)) {
641
- throw new ValidationError("Conflicting Unblind query");
642
- }
643
- if (!prior) {
644
- this.pendingQueries.set(data.x, { envelope: copyAuxiliaryQuery(envelope), expires, grant: grant.said });
645
- }
646
- }
647
- /** Expired evidence cannot survive another owner interaction. */
648
- pruneQueries() {
649
- const now = BigInt(this.now()) * 1000n;
650
- for (const [xid, query] of this.pendingQueries)
651
- if (now >= query.expires)
652
- this.pendingQueries.delete(xid);
653
- return now;
686
+ .filter((grant) => grant && grant.pre === this.hab.pre && grant.sad.ri === recipient
687
+ && this.exc.presentationContext(grant.said, { xid, sender: this.hab.pre, recipient }));
688
+ if (said.length !== 1)
689
+ throw new ValidationError("Unblind query has no unique live Grant sent by this identifier");
690
+ return said[0].said;
654
691
  }
655
- /** Consume the first authenticated request only after explicit approval; never renew either clock. */
656
- replayQuery(xid) {
657
- const pending = this.pendingQueries.get(xid);
658
- this.pendingQueries.delete(xid);
659
- if (pending && pending.grant === this.operations.get(xid)?.grant
660
- && BigInt(this.now()) * 1000n < pending.expires)
661
- this.processQuery(pending.envelope);
662
- }
663
- /** Bound process-local public evidence by the original query and accepted Grant lifetimes. */
664
- retainUntil(envelope, grant) {
665
- const now = this.pruneQueries();
666
- const cache = this.hab.db.msgc.get([envelope.serder.pre, envelope.serder.said]);
667
- const messageTime = cache && timestampMicros(cache.mdt);
668
- const grantTime = timestampMicros(this.exc.exchangeDeadline(grant) ?? undefined);
669
- if (!cache || this.hab.db.pmkm.get([envelope.serder.pre, envelope.serder.said]) || messageTime === null
670
- || messageTime === undefined || grantTime === null
671
- || !Number.isSafeInteger(cache.d) || !Number.isSafeInteger(cache.ml)
672
- || cache.d < 0 || cache.ml < 0 || !Number.isSafeInteger(cache.d + cache.ml)) {
673
- throw new ValidationError("Query has no accepted original lifetime");
674
- }
675
- const queryTime = messageTime + BigInt(cache.d + cache.ml) * 1000n;
676
- const expires = queryTime < grantTime ? queryTime : grantTime;
677
- if (now >= expires)
678
- throw new ValidationError("Query or Grant has expired");
679
- return expires;
692
+ /**
693
+ * Individual discloser operations whose authenticated peer query is waiting for a delivered reply.
694
+ * Hosts adopt these to deliver the reply; a group discloser's replies need member contributions instead.
695
+ */
696
+ awaitingReply() {
697
+ this.restoreHeld();
698
+ if (this.group)
699
+ return [];
700
+ return [...this.operations.values()]
701
+ .filter((op) => op.sender === this.hab.pre && op.requestedByPeer && !op.abandoned)
702
+ .map(({ xid, grant }) => ({ xid, grant }));
680
703
  }
681
704
  operation(xid) {
682
705
  const op = this.operations.get(xid);
@@ -965,7 +988,7 @@ export class Unblind {
965
988
  said: String(event.sad.b),
966
989
  uuid: makeBlindUuid({ salt: root.qb64, sn: BigInt(ordinal(event)) }),
967
990
  acdc: target,
968
- states: this.states,
991
+ states: op.states,
969
992
  });
970
993
  if (opening)
971
994
  break;
@@ -1,6 +1,7 @@
1
1
  import { call, scoped } from "effection";
2
2
  import { persistResolvedContact } from "../identity/organizing.js";
3
- import { runtimeTurn } from "../runtime/runtime-turn.js";
3
+ import { doEvery, PROTOCOL_PACING } from "../runtime/doing.js";
4
+ import { systemClock } from "../runtime/runtime-clock.js";
4
5
  import { isWellKnownOobiUrl, parseOobiUrl } from "./oobiery.js";
5
6
  /**
6
7
  * Return true when a well-known URL has been authorized into `wkas.`.
@@ -68,11 +69,8 @@ export class Authenticator {
68
69
  yield* call(() => this.processPendingAuth(url, record));
69
70
  }
70
71
  /** Continuous auth doer for long-lived runtime hosts. */
71
- *authDo() {
72
- while (true) {
73
- yield* this.processOnce();
74
- yield* runtimeTurn();
75
- }
72
+ *authDo(clock = systemClock, pacing = PROTOCOL_PACING) {
73
+ return yield* doEvery(clock, pacing.tockMs, () => this.processOnce());
76
74
  }
77
75
  /** Promote one eligible `woobi.` record into the fetchable `mfa.` queue. */
78
76
  promoteQueuedWellKnown() {
@@ -0,0 +1,41 @@
1
+ import { observeUntil } from "../runtime/workflow-contract.js";
2
+ import { oobiTerminalState } from "./oobiery.js";
3
+ /** Default wall-clock budget for one blocking resolution. */
4
+ export const OOBI_RESOLVE_TIMEOUT_MS = 30_000;
5
+ /**
6
+ * Queue one URL with the durable Oobiery. Returns after the job is queued.
7
+ *
8
+ * @param url Exact OOBI or well-known URL; it is also the key of the status record.
9
+ */
10
+ export function beginOobi(deps, url, options = {}) {
11
+ deps.oobiery.resolve(url, options.alias);
12
+ deps.changes?.push({ kind: "oobi", id: url });
13
+ }
14
+ /** Read the durable status of one requested URL. Pure: no worker, no I/O beyond the Baser. */
15
+ export function oobiStatus(deps, url) {
16
+ const terminal = oobiTerminalState(deps.db, url);
17
+ if (terminal.status === "pending" || !terminal.record)
18
+ return { state: "pending" };
19
+ if (terminal.status === "resolved")
20
+ return { state: "resolved", record: terminal.record };
21
+ return { state: "failed", reason: terminal.record.state ?? "failed", record: terminal.record };
22
+ }
23
+ /**
24
+ * Observe a queued URL until it is terminal (and `deps.settled`, when given) or
25
+ * the budget expires. Starts no worker.
26
+ *
27
+ * @returns `settled` with a `resolved` or `failed` status (reason recorded), or `timed-out`.
28
+ */
29
+ export function* waitForOobi(deps, url, { timeoutMs = OOBI_RESOLVE_TIMEOUT_MS } = {}) {
30
+ const done = yield* observeUntil(() => oobiStatus(deps, url).state !== "pending" && (deps.settled?.() ?? true), { timeoutMs });
31
+ const status = oobiStatus(deps, url);
32
+ if (!done || status.state === "pending")
33
+ return { outcome: "timed-out", status, timeoutMs };
34
+ deps.changes?.push({ kind: "oobi", id: url });
35
+ return { outcome: "settled", status };
36
+ }
37
+ /** `beginOobi` then `waitForOobi`. The host must be running the Oobiery for the wait to end in a terminal state. */
38
+ export function* resolveOobi(deps, url, options = {}) {
39
+ beginOobi(deps, url, options);
40
+ return yield* waitForOobi(deps, url, options);
41
+ }
@@ -8,7 +8,8 @@ import { acceptReplyDecision, unverifiedReplyDecision } from "../../core/routing
8
8
  import { Schemer } from "../../core/scheming.js";
9
9
  import { persistResolvedContact } from "../identity/organizing.js";
10
10
  import { abortable } from "../runtime/abortable.js";
11
- import { runtimeTurn } from "../runtime/runtime-turn.js";
11
+ import { doEvery, PROTOCOL_PACING } from "../runtime/doing.js";
12
+ import { systemClock } from "../runtime/runtime-clock.js";
12
13
  import { collectBytes } from "../transport/byte-source.js";
13
14
  import { processMessages } from "../transport/message-source.js";
14
15
  export const OOBI_REQUEST_ROUTE = "/oobis";
@@ -205,11 +206,8 @@ export class Oobiery {
205
206
  * This mirrors the KERIpy model where OOBI resolution is its own long-running
206
207
  * doer rather than root-owned queue plumbing.
207
208
  */
208
- *oobiDo() {
209
- while (true) {
210
- yield* this.processOnce();
211
- yield* runtimeTurn();
212
- }
209
+ *oobiDo(clock = systemClock, pacing = PROTOCOL_PACING) {
210
+ return yield* doEvery(clock, pacing.tockMs, () => this.processOnce());
213
211
  }
214
212
  /** Select queued work, including a surviving in-flight row whose former process is gone. */
215
213
  nextQueued() {
@@ -47,6 +47,7 @@ export function* revokeCredential(rgy, input, postman, options) {
47
47
  rgy.publication.track(event, anchor.serder);
48
48
  group = {
49
49
  route: MULTISIG_REV_ROUTE,
50
+ event: { pre: anchor.serder.pre, sn: anchor.serder.sn, said: anchor.serder.said },
50
51
  ...(yield* publishGroupVcProposal(hby, input, postman, registry.hab, {
51
52
  route: MULTISIG_REV_ROUTE,
52
53
  attrs: { gid: registry.hab.pre, said: options.credentialSaid },
@@ -193,6 +193,7 @@ function* proposeGroupRegistryIncept(rgy, input, postman, hab, options) {
193
193
  issuer: hab.pre,
194
194
  group: {
195
195
  route: MULTISIG_VCP_ROUTE,
196
+ event: { pre: anchor.serder.pre, sn: anchor.serder.sn, said: anchor.serder.said },
196
197
  status: decision.kind,
197
198
  accepted: telAccepted(reger, regk, 0, requireSerderSaid(vcp, "registry inception")),
198
199
  ...publication,
@@ -257,6 +258,7 @@ function* proposeGroupCredentialIssue(rgy, input, postman, registry, creder, rec
257
258
  status: verifierDecision.kind,
258
259
  group: {
259
260
  route: MULTISIG_ISS_ROUTE,
261
+ event: { pre: anchor.serder.pre, sn: anchor.serder.sn, said: anchor.serder.said },
260
262
  telStatus: telDecision.kind,
261
263
  saved: credentialSaved(reger, creder),
262
264
  ...publication,
@@ -0,0 +1,44 @@
1
+ import { systemClock } from "../runtime/runtime-clock.js";
2
+ import { observeUntil } from "../runtime/workflow-contract.js";
3
+ /** Elapsed milliseconds between reads of a registry wait. */
4
+ export const REGISTRY_WAIT_POLL_MS = 50;
5
+ /** Reference for a TEL event sealed by a known anchor. */
6
+ export function registryEventRef(tel, anchor) {
7
+ return {
8
+ regid: tel.ilk === "rip" ? tel.said : tel.regid,
9
+ sn: Number(BigInt(`0x${tel.sad.n}`)),
10
+ said: tel.said,
11
+ anchor,
12
+ };
13
+ }
14
+ /** Read the status of one registry event; mutates nothing. */
15
+ export function registryEventStatus(deps, ref) {
16
+ if (deps.store.seqEvent(ref.regid, ref.sn)?.said === ref.said)
17
+ return { state: "accepted" };
18
+ const { pre, said } = ref.anchor;
19
+ const anchor = deps.db.getEvtSerder(pre, said);
20
+ if (!anchor || deps.db.kels.getLast(pre, anchor.sn) !== said)
21
+ return { state: "awaiting-anchor" };
22
+ return deps.db.fullyWitnessed(anchor) ? { state: "awaiting-tel" } : { state: "awaiting-receipts" };
23
+ }
24
+ /**
25
+ * Local settle step: reprocess the escrows once. That accepts the anchor when
26
+ * the last member signature has arrived and, once the anchor is complete, the
27
+ * sealed TEL event. Does nothing for an event already accepted.
28
+ */
29
+ export function* settleRegistryEvent(deps, ref) {
30
+ if (registryEventStatus(deps, ref).state === "accepted")
31
+ return { state: "accepted" };
32
+ yield* deps.protocol.processEscrowsOnce();
33
+ return registryEventStatus(deps, ref);
34
+ }
35
+ /** Observe the event until `accepted` or the deadline passes. Starts no worker; the host settles. */
36
+ export function* waitForRegistryEvent(deps, ref, { deadline, clock = systemClock }) {
37
+ const done = yield* observeUntil(() => registryEventStatus(deps, ref).state === "accepted", {
38
+ timeoutMs: Math.max(0, deadline - clock.now()),
39
+ clock,
40
+ pollMs: REGISTRY_WAIT_POLL_MS,
41
+ });
42
+ const status = registryEventStatus(deps, ref);
43
+ return done ? { outcome: "settled", status } : { outcome: "timed-out", status, deadline };
44
+ }