keri-ts 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) 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 +164 -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 +327 -0
  27. package/esm/keri/npm/src/app/ipex/group-issuance.js +902 -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 +34 -11
  33. package/esm/keri/npm/src/app/ipex/issuance.js +888 -0
  34. package/esm/keri/npm/src/app/ipex/pending-presentations.js +46 -0
  35. package/esm/keri/npm/src/app/ipex/presentation-files.js +200 -0
  36. package/esm/keri/npm/src/app/ipex/presenting.js +401 -0
  37. package/esm/keri/npm/src/app/ipex/receive-issuance.js +86 -0
  38. package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +660 -0
  39. package/esm/keri/npm/src/app/mailbox/ipex-arrival.js +103 -0
  40. package/esm/keri/npm/src/app/mailbox/kel-publisher.js +322 -0
  41. package/esm/keri/npm/src/app/mailbox/kel-publishing.js +65 -0
  42. package/esm/keri/npm/src/app/mailbox/kel-submission.js +24 -0
  43. package/esm/keri/npm/src/app/mailbox/mailbox-admin.js +208 -0
  44. package/esm/keri/npm/src/app/mailbox/mailbox-poller.js +212 -47
  45. package/esm/keri/npm/src/app/mailbox/mailboxing.js +10 -5
  46. package/esm/keri/npm/src/app/multisig/counseling.js +482 -0
  47. package/esm/keri/npm/src/app/multisig/group-members.js +18 -0
  48. package/esm/keri/npm/src/app/multisig/multisig-workflows.js +94 -139
  49. package/esm/keri/npm/src/app/multisig/proposals.js +281 -0
  50. package/esm/keri/npm/src/app/multisig/proposing.js +122 -0
  51. package/esm/keri/npm/src/app/notifications/signaling.js +5 -5
  52. package/esm/keri/npm/src/app/protocol/parsering.js +26 -1
  53. package/esm/keri/npm/src/app/protocol/protocol-processing.js +9 -3
  54. package/esm/keri/npm/src/app/queries/query-workflows.js +98 -0
  55. package/esm/keri/npm/src/app/runtime/agent-runtime.js +106 -55
  56. package/esm/keri/npm/src/app/runtime/cue-runtime.js +3 -6
  57. package/esm/keri/npm/src/app/runtime/delivery-outbox.js +87 -0
  58. package/esm/keri/npm/src/app/runtime/doing.js +17 -0
  59. package/esm/keri/npm/src/app/runtime/ipex-auxiliaries.js +207 -0
  60. package/esm/keri/npm/src/app/runtime/operation-owners.js +151 -0
  61. package/esm/keri/npm/src/app/runtime/retry-backoff.js +93 -0
  62. package/esm/keri/npm/src/app/runtime/workflow-contract.js +80 -0
  63. package/esm/keri/npm/src/app/transport/http-client.js +25 -6
  64. package/esm/keri/npm/src/app/witness/http-endpoints.js +4 -4
  65. package/esm/keri/npm/src/cli/common/event-completion.js +49 -0
  66. package/esm/keri/npm/src/cli/common/runtime-workers.js +23 -0
  67. package/esm/keri/npm/src/cli/credentials/ipex.js +157 -190
  68. package/esm/keri/npm/src/cli/credentials/vc.js +53 -72
  69. package/esm/keri/npm/src/cli/endpoints/did.js +12 -3
  70. package/esm/keri/npm/src/cli/endpoints/oobi.js +10 -13
  71. package/esm/keri/npm/src/cli/identity/challenge.js +8 -34
  72. package/esm/keri/npm/src/cli/identity/delegate.js +81 -258
  73. package/esm/keri/npm/src/cli/identity/incept.js +15 -32
  74. package/esm/keri/npm/src/cli/identity/interact.js +5 -17
  75. package/esm/keri/npm/src/cli/identity/rotate.js +8 -36
  76. package/esm/keri/npm/src/cli/index.js +3 -1
  77. package/esm/keri/npm/src/cli/messaging/group-join.js +79 -0
  78. package/esm/keri/npm/src/cli/messaging/group-wait.js +88 -0
  79. package/esm/keri/npm/src/cli/messaging/multisig.js +163 -284
  80. package/esm/keri/npm/src/cli/messaging/root-copy-lines.js +31 -0
  81. package/esm/keri/npm/src/core/kel/eventing.js +66 -10
  82. package/esm/keri/npm/src/core/mailbox/kram-policy.js +39 -6
  83. package/esm/keri/npm/src/core/mailbox/kraming.js +2 -0
  84. package/esm/keri/npm/src/core/records.js +23 -0
  85. package/esm/keri/npm/src/core/routing.js +13 -0
  86. package/esm/keri/npm/src/db/basing.js +34 -2
  87. package/esm/keri/npm/src/db/core/indexeddb-persistence.js +221 -0
  88. package/esm/keri/npm/src/db/indexeddb.js +98 -0
  89. package/esm/keri/npm/src/db/keeping.js +11 -2
  90. package/esm/keri/npm/src/db/store-lock.js +150 -0
  91. package/esm/keri/npm/src/npm/db-indexeddb.browser.js +2 -0
  92. package/esm/keri/npm/src/npm/db-indexeddb.js +3 -0
  93. package/esm/keri/npm/src/npm/db.browser.js +2 -0
  94. package/esm/keri/npm/src/npm/index.browser.js +9 -0
  95. package/esm/keri/npm/src/npm/runtime-web.browser.js +2 -0
  96. package/esm/keri/npm/src/npm/runtime-web.js +3 -0
  97. package/esm/keri/npm/src/npm/runtime.browser.js +2 -0
  98. package/esm/keri/npm/src/runtime/index.js +51 -4
  99. package/esm/keri/npm/src/runtime/web/output-barrier.js +47 -0
  100. package/esm/keri/npm/src/runtime/web/persistent-storage.js +37 -0
  101. package/esm/keri/npm/src/runtime/web.js +10 -0
  102. package/esm/keri/npm/src/vdr/tel-publication.js +16 -0
  103. package/esm/keri/npm/src/version.js +2 -2
  104. package/package.json +15 -2
  105. package/types/acdc/authoring.d.ts +54 -0
  106. package/types/acdc/authoring.d.ts.map +1 -0
  107. package/types/acdc/custody.d.ts +77 -0
  108. package/types/acdc/custody.d.ts.map +1 -0
  109. package/types/acdc/dhking.d.ts +94 -3
  110. package/types/acdc/dhking.d.ts.map +1 -1
  111. package/types/acdc/regbasing.d.ts +4 -0
  112. package/types/acdc/regbasing.d.ts.map +1 -1
  113. package/types/acdc/salting.d.ts +6 -1
  114. package/types/acdc/salting.d.ts.map +1 -1
  115. package/types/acdc/scheming.d.ts +2 -0
  116. package/types/acdc/scheming.d.ts.map +1 -1
  117. package/types/acdc/unblinding.d.ts +58 -19
  118. package/types/acdc/unblinding.d.ts.map +1 -1
  119. package/types/app/bootstrap/authenticating.d.ts +3 -1
  120. package/types/app/bootstrap/authenticating.d.ts.map +1 -1
  121. package/types/app/bootstrap/oobi-resolving.d.ts +92 -0
  122. package/types/app/bootstrap/oobi-resolving.d.ts.map +1 -0
  123. package/types/app/bootstrap/oobiery.d.ts +3 -1
  124. package/types/app/bootstrap/oobiery.d.ts.map +1 -1
  125. package/types/app/credentials/credential-revoking.d.ts +3 -0
  126. package/types/app/credentials/credential-revoking.d.ts.map +1 -1
  127. package/types/app/credentials/credential-workflows.d.ts +5 -0
  128. package/types/app/credentials/credential-workflows.d.ts.map +1 -1
  129. package/types/app/credentials/registry-settling.d.ts +85 -0
  130. package/types/app/credentials/registry-settling.d.ts.map +1 -0
  131. package/types/app/credentials/root-replicating.d.ts +56 -44
  132. package/types/app/credentials/root-replicating.d.ts.map +1 -1
  133. package/types/app/credentials/root-replicator.d.ts +105 -0
  134. package/types/app/credentials/root-replicator.d.ts.map +1 -0
  135. package/types/app/credentials/tel-completion.d.ts +55 -0
  136. package/types/app/credentials/tel-completion.d.ts.map +1 -0
  137. package/types/app/delivery/forwarding.d.ts +6 -0
  138. package/types/app/delivery/forwarding.d.ts.map +1 -1
  139. package/types/app/exchanges/exchanging.d.ts.map +1 -1
  140. package/types/app/identity/challenging.d.ts +54 -0
  141. package/types/app/identity/challenging.d.ts.map +1 -1
  142. package/types/app/identity/delegating.d.ts +21 -4
  143. package/types/app/identity/delegating.d.ts.map +1 -1
  144. package/types/app/identity/delegation-approval.d.ts +228 -0
  145. package/types/app/identity/delegation-approval.d.ts.map +1 -0
  146. package/types/app/identity/event-completion.d.ts +151 -0
  147. package/types/app/identity/event-completion.d.ts.map +1 -0
  148. package/types/app/identity/habbing.d.ts +67 -2
  149. package/types/app/identity/habbing.d.ts.map +1 -1
  150. package/types/app/identity/keeping.d.ts +49 -3
  151. package/types/app/identity/keeping.d.ts.map +1 -1
  152. package/types/app/ipex/group-ipex.d.ts +247 -0
  153. package/types/app/ipex/group-ipex.d.ts.map +1 -0
  154. package/types/app/ipex/group-issuance.d.ts +281 -0
  155. package/types/app/ipex/group-issuance.d.ts.map +1 -0
  156. package/types/app/ipex/ipex-admitting.d.ts +47 -0
  157. package/types/app/ipex/ipex-admitting.d.ts.map +1 -0
  158. package/types/app/ipex/ipex-conversation.d.ts +195 -0
  159. package/types/app/ipex/ipex-conversation.d.ts.map +1 -0
  160. package/types/app/ipex/ipex-discloser.d.ts +156 -0
  161. package/types/app/ipex/ipex-discloser.d.ts.map +1 -0
  162. package/types/app/ipex/ipex-granting.d.ts +145 -0
  163. package/types/app/ipex/ipex-granting.d.ts.map +1 -0
  164. package/types/app/ipex/ipex-grouping.d.ts +18 -0
  165. package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
  166. package/types/app/ipex/issuance.d.ts +443 -0
  167. package/types/app/ipex/issuance.d.ts.map +1 -0
  168. package/types/app/ipex/pending-presentations.d.ts +25 -0
  169. package/types/app/ipex/pending-presentations.d.ts.map +1 -0
  170. package/types/app/ipex/presentation-files.d.ts +47 -0
  171. package/types/app/ipex/presentation-files.d.ts.map +1 -0
  172. package/types/app/ipex/presenting.d.ts +298 -0
  173. package/types/app/ipex/presenting.d.ts.map +1 -0
  174. package/types/app/ipex/receive-issuance.d.ts +99 -0
  175. package/types/app/ipex/receive-issuance.d.ts.map +1 -0
  176. package/types/app/ipex/unblinding-workflow.d.ts +255 -0
  177. package/types/app/ipex/unblinding-workflow.d.ts.map +1 -0
  178. package/types/app/mailbox/ipex-arrival.d.ts +104 -0
  179. package/types/app/mailbox/ipex-arrival.d.ts.map +1 -0
  180. package/types/app/mailbox/kel-publisher.d.ts +141 -0
  181. package/types/app/mailbox/kel-publisher.d.ts.map +1 -0
  182. package/types/app/mailbox/kel-publishing.d.ts +70 -0
  183. package/types/app/mailbox/kel-publishing.d.ts.map +1 -0
  184. package/types/app/mailbox/kel-submission.d.ts +18 -0
  185. package/types/app/mailbox/kel-submission.d.ts.map +1 -0
  186. package/types/app/mailbox/mailbox-admin.d.ts +113 -0
  187. package/types/app/mailbox/mailbox-admin.d.ts.map +1 -0
  188. package/types/app/mailbox/mailbox-poller.d.ts +92 -3
  189. package/types/app/mailbox/mailbox-poller.d.ts.map +1 -1
  190. package/types/app/mailbox/mailboxing.d.ts +3 -0
  191. package/types/app/mailbox/mailboxing.d.ts.map +1 -1
  192. package/types/app/multisig/counseling.d.ts +196 -0
  193. package/types/app/multisig/counseling.d.ts.map +1 -0
  194. package/types/app/multisig/group-members.d.ts +11 -0
  195. package/types/app/multisig/group-members.d.ts.map +1 -1
  196. package/types/app/multisig/grouping.d.ts +39 -20
  197. package/types/app/multisig/grouping.d.ts.map +1 -1
  198. package/types/app/multisig/multisig-workflows.d.ts +91 -22
  199. package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
  200. package/types/app/multisig/proposals.d.ts +129 -0
  201. package/types/app/multisig/proposals.d.ts.map +1 -0
  202. package/types/app/multisig/proposing.d.ts +125 -0
  203. package/types/app/multisig/proposing.d.ts.map +1 -0
  204. package/types/app/notifications/signaling.d.ts +3 -1
  205. package/types/app/notifications/signaling.d.ts.map +1 -1
  206. package/types/app/protocol/parsering.d.ts +13 -0
  207. package/types/app/protocol/parsering.d.ts.map +1 -1
  208. package/types/app/protocol/protocol-processing.d.ts +7 -1
  209. package/types/app/protocol/protocol-processing.d.ts.map +1 -1
  210. package/types/app/queries/query-workflows.d.ts +98 -0
  211. package/types/app/queries/query-workflows.d.ts.map +1 -0
  212. package/types/app/runtime/agent-runtime.d.ts +72 -25
  213. package/types/app/runtime/agent-runtime.d.ts.map +1 -1
  214. package/types/app/runtime/cue-runtime.d.ts +2 -1
  215. package/types/app/runtime/cue-runtime.d.ts.map +1 -1
  216. package/types/app/runtime/delivery-outbox.d.ts +68 -0
  217. package/types/app/runtime/delivery-outbox.d.ts.map +1 -0
  218. package/types/app/runtime/doing.d.ts +27 -0
  219. package/types/app/runtime/doing.d.ts.map +1 -0
  220. package/types/app/runtime/ipex-auxiliaries.d.ts +74 -0
  221. package/types/app/runtime/ipex-auxiliaries.d.ts.map +1 -0
  222. package/types/app/runtime/operation-owners.d.ts +137 -0
  223. package/types/app/runtime/operation-owners.d.ts.map +1 -0
  224. package/types/app/runtime/retry-backoff.d.ts +49 -0
  225. package/types/app/runtime/retry-backoff.d.ts.map +1 -0
  226. package/types/app/runtime/workflow-contract.d.ts +79 -0
  227. package/types/app/runtime/workflow-contract.d.ts.map +1 -0
  228. package/types/app/transport/http-client.d.ts.map +1 -1
  229. package/types/cli/common/event-completion.d.ts +26 -0
  230. package/types/cli/common/event-completion.d.ts.map +1 -0
  231. package/types/cli/common/runtime-workers.d.ts +23 -0
  232. package/types/cli/common/runtime-workers.d.ts.map +1 -0
  233. package/types/cli/credentials/ipex.d.ts.map +1 -1
  234. package/types/cli/credentials/vc.d.ts +1 -1
  235. package/types/cli/credentials/vc.d.ts.map +1 -1
  236. package/types/cli/endpoints/did.d.ts.map +1 -1
  237. package/types/cli/endpoints/oobi.d.ts +3 -1
  238. package/types/cli/endpoints/oobi.d.ts.map +1 -1
  239. package/types/cli/identity/challenge.d.ts +1 -1
  240. package/types/cli/identity/challenge.d.ts.map +1 -1
  241. package/types/cli/identity/delegate.d.ts +14 -1
  242. package/types/cli/identity/delegate.d.ts.map +1 -1
  243. package/types/cli/identity/incept.d.ts.map +1 -1
  244. package/types/cli/identity/interact.d.ts.map +1 -1
  245. package/types/cli/identity/rotate.d.ts.map +1 -1
  246. package/types/cli/index.d.ts +3 -1
  247. package/types/cli/index.d.ts.map +1 -1
  248. package/types/cli/messaging/group-join.d.ts +53 -0
  249. package/types/cli/messaging/group-join.d.ts.map +1 -0
  250. package/types/cli/messaging/group-wait.d.ts +34 -0
  251. package/types/cli/messaging/group-wait.d.ts.map +1 -0
  252. package/types/cli/messaging/multisig.d.ts +28 -5
  253. package/types/cli/messaging/multisig.d.ts.map +1 -1
  254. package/types/cli/messaging/root-copy-lines.d.ts +39 -0
  255. package/types/cli/messaging/root-copy-lines.d.ts.map +1 -0
  256. package/types/core/cues.d.ts +11 -0
  257. package/types/core/cues.d.ts.map +1 -1
  258. package/types/core/kel/eventing.d.ts.map +1 -1
  259. package/types/core/mailbox/kram-policy.d.ts +14 -0
  260. package/types/core/mailbox/kram-policy.d.ts.map +1 -1
  261. package/types/core/mailbox/kraming.d.ts +1 -1
  262. package/types/core/mailbox/kraming.d.ts.map +1 -1
  263. package/types/core/records.d.ts +61 -0
  264. package/types/core/records.d.ts.map +1 -1
  265. package/types/core/routing.d.ts +6 -0
  266. package/types/core/routing.d.ts.map +1 -1
  267. package/types/db/basing.d.ts +8 -2
  268. package/types/db/basing.d.ts.map +1 -1
  269. package/types/db/core/indexeddb-persistence.d.ts +59 -0
  270. package/types/db/core/indexeddb-persistence.d.ts.map +1 -0
  271. package/types/db/indexeddb.d.ts +37 -0
  272. package/types/db/indexeddb.d.ts.map +1 -0
  273. package/types/db/keeping.d.ts +5 -2
  274. package/types/db/keeping.d.ts.map +1 -1
  275. package/types/db/store-lock.d.ts +72 -0
  276. package/types/db/store-lock.d.ts.map +1 -0
  277. package/types/npm/db-indexeddb.d.ts +4 -0
  278. package/types/npm/db-indexeddb.d.ts.map +1 -0
  279. package/types/npm/runtime-web.d.ts +4 -0
  280. package/types/npm/runtime-web.d.ts.map +1 -0
  281. package/types/runtime/index.d.ts +41 -6
  282. package/types/runtime/index.d.ts.map +1 -1
  283. package/types/runtime/web/output-barrier.d.ts +30 -0
  284. package/types/runtime/web/output-barrier.d.ts.map +1 -0
  285. package/types/runtime/web/persistent-storage.d.ts +36 -0
  286. package/types/runtime/web/persistent-storage.d.ts.map +1 -0
  287. package/types/runtime/web.d.ts +11 -0
  288. package/types/runtime/web.d.ts.map +1 -0
  289. package/types/vdr/tel-publication.d.ts +6 -0
  290. package/types/vdr/tel-publication.d.ts.map +1 -1
  291. package/types/version.d.ts +2 -2
  292. package/esm/keri/npm/src/cli/common/tel-completion.js +0 -24
  293. package/types/cli/common/tel-completion.d.ts +0 -8
  294. package/types/cli/common/tel-completion.d.ts.map +0 -1
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Single-signature event completion: the steps that follow authoring a local
3
+ * event, owned by the library so that every host (CLI, wallet, service) runs
4
+ * one implementation.
5
+ *
6
+ * Completion is two independent steps. `receiptEvent` obtains witness receipts
7
+ * for the accepted event. For delegated events, `beginDelegation` places the
8
+ * event in the durable delegating workflow and `waitForDelegation` drives the
9
+ * host's runtime has learned the delegator's anchor. Begin is separate from
10
+ * wait so that a host without a blocking caller can begin, return to its user
11
+ * interface and read `delegationStatus` later. `completeEvent` is the
12
+ * convenience that runs both steps in order. A completed rotation (`rot` or `drt`) is then announced with a
13
+ * {@link RotatedCue} to the host's `KelPublisher`, which tells the identifier's mailboxes (a mailbox
14
+ * authenticates the identifier's polls against the key state it holds). The announcement is a prompt:
15
+ * the publisher derives what is owed from state, so a host without one loses nothing durable. An interaction
16
+ * event changes no keys, so it announces nothing.
17
+ *
18
+ * Boundaries:
19
+ * - Dependencies are narrow collaborators, not an AgentRuntime (ADR-0013). The
20
+ * host owns the runtime and its lifetime; `withDelegation` lends the
21
+ * collaborator for one scope and, for a one-shot host, runs workers in it.
22
+ * - Waits only observe. They never start runtime workers, and an expired wait is
23
+ * a returned `timed-out` value, not an exception.
24
+ * - Witness authorization codes arrive resolved. Prompting is a host concern.
25
+ * - Delegation state is the Anchorer's durable escrow membership; this module
26
+ * adds none.
27
+ */
28
+ import { Ilks } from "cesr-ts";
29
+ import { dgKey } from "../../db/core/keys.js";
30
+ import { observeUntil } from "../runtime/workflow-contract.js";
31
+ import { Receiptor, WitnessReceiptor } from "../witness/receipting.js";
32
+ /** How long the CLI-compatible wait for a delegator's anchor lasts. */
33
+ export const DELEGATION_WAIT_TIMEOUT_MS = 120_000;
34
+ /**
35
+ * Obtain witness receipts for an accepted local event. No-op when the
36
+ * identifier has no accepted key state yet (a delegated inception awaiting
37
+ * approval) or its current key state has no witnesses.
38
+ *
39
+ * @throws Receipt failures from the witness receiptor propagate.
40
+ */
41
+ export function* receiptEvent(deps, pre, { sn, auths, endpoint = false, force = false } = {}) {
42
+ const kever = deps.hby.habs.get(pre)?.kever;
43
+ if (!kever?.wits.length)
44
+ return;
45
+ if (endpoint) {
46
+ yield* new Receiptor(deps.hby, deps.protocol, deps.http, deps.clock).receipt(pre, { sn, auths });
47
+ }
48
+ else {
49
+ yield* new WitnessReceiptor(deps.hby, deps.protocol, deps.http, deps.clock, { force })
50
+ .submit(pre, { sn, auths });
51
+ }
52
+ deps.changes?.push({ kind: "event", id: `${pre}:${sn ?? kever.sn}` });
53
+ }
54
+ /** Hex sequence key the delegating workflow uses. */
55
+ function snKey(sn) {
56
+ return sn.toString(16);
57
+ }
58
+ /**
59
+ * Put one delegated event into the durable delegating workflow. Returns at once;
60
+ * progress needs the host's runtime workers, and `delegationStatus` reports it.
61
+ *
62
+ * @param communicationHab Optional local proxy that signs delegation traffic.
63
+ */
64
+ export function beginDelegation(delegation, pre, sn, communicationHab) {
65
+ delegation.anchorer.beginLatest(pre, sn, { communicationHab });
66
+ delegation.changes?.push({ kind: "delegation", id: `${pre}:${sn}` });
67
+ }
68
+ /** Read the durable workflow state for one delegated event; mutates nothing. */
69
+ export function delegationStatus(delegation, pre, sn) {
70
+ return delegation.anchorer.workflowStatus(pre, snKey(sn));
71
+ }
72
+ /**
73
+ * Observe the delegated event until the delegator's anchor is learned or the
74
+ * deadline passes. Starts no worker.
75
+ */
76
+ export function* waitForDelegation(delegation, hab, sn, { timeoutMs = DELEGATION_WAIT_TIMEOUT_MS } = {}) {
77
+ const done = yield* observeUntil(() => delegation.anchorer.complete(hab.pre, sn), { timeoutMs });
78
+ const status = delegationStatus(delegation, hab.pre, sn);
79
+ if (!done)
80
+ return { outcome: "timed-out", status, timeoutMs };
81
+ delegation.changes?.push({ kind: "delegation", id: `${hab.pre}:${sn}` });
82
+ return { outcome: "settled", status };
83
+ }
84
+ /** Announce a completed rotation so its mailboxes are told; any other event announces nothing. */
85
+ function announceRotation(deps, pre, sn, status) {
86
+ if (status.state !== "complete" || !deps.rotated)
87
+ return;
88
+ const said = deps.hby.db.kels.getLast(pre, sn);
89
+ const ilk = said ? deps.hby.db.getEvtSerder(pre, said)?.ilk : null;
90
+ if (said && (ilk === Ilks.rot || ilk === Ilks.drt))
91
+ deps.rotated.push({ kin: "rotated", pre, sn, said });
92
+ }
93
+ /**
94
+ * Complete a freshly authored event: witness receipts, then, for delegated
95
+ * events, delegation begin and wait.
96
+ *
97
+ * @param sn Sequence number of the event just authored.
98
+ */
99
+ export function* completeEvent(deps, hab, sn, { delegation, ...receipt } = {}) {
100
+ yield* receiptEvent(deps, hab.pre, { ...receipt, sn });
101
+ if (!delegation) {
102
+ const status = eventStatus(deps.hby, hab.pre, sn);
103
+ announceRotation(deps, hab.pre, sn, status);
104
+ return { outcome: "settled", status, delegationPhase: null };
105
+ }
106
+ const communicationHab = delegation.communicationHab?.();
107
+ return yield* deps.withDelegation(hab, function* (collaborator) {
108
+ beginDelegation(collaborator, hab.pre, sn, communicationHab);
109
+ const result = yield* waitForDelegation(collaborator, hab, sn, { timeoutMs: delegation.timeoutMs });
110
+ const status = eventStatus({ db: deps.hby.db, anchorer: collaborator.anchorer }, hab.pre, sn);
111
+ if (result.outcome === "timed-out") {
112
+ return {
113
+ outcome: "timed-out",
114
+ status,
115
+ timeoutMs: result.timeoutMs,
116
+ delegationPhase: result.status.phase,
117
+ };
118
+ }
119
+ announceRotation(deps, hab.pre, sn, status);
120
+ return { outcome: "settled", status, delegationPhase: result.status.phase };
121
+ });
122
+ }
123
+ /**
124
+ * Pure synchronous status of the event `pre` at `sn`, derived from durable state.
125
+ *
126
+ * Receipts are judged against the witness set of THAT event (not the current
127
+ * key state) via stored `wigs`. A delegating-workflow escrow phase takes
128
+ * precedence; a delegated event with no escrow and no anchor yet reads as
129
+ * waiting for the delegator's anchor. Group events are not covered.
130
+ */
131
+ export function eventStatus(deps, pre, sn) {
132
+ const workflow = deps.anchorer?.workflowStatus(pre, snKey(sn));
133
+ if (workflow?.phase)
134
+ return { state: "active", phase: workflow.phase };
135
+ const said = deps.db.kels.getLast(pre, sn);
136
+ const serder = said ? deps.db.getEvtSerder(pre, said) : null;
137
+ if (!said || !serder)
138
+ return { state: "unknown", reason: "no-accepted-event" };
139
+ if (!deps.db.fullyWitnessed(serder)) {
140
+ return {
141
+ state: "active",
142
+ phase: "waitingWitnessReceipts",
143
+ blocked: {
144
+ missing: "witnessReceipts",
145
+ have: deps.db.wigs.get(dgKey(pre, said)).length,
146
+ of: deps.db.acceptedEventWitnesses(serder)?.length ?? 0,
147
+ },
148
+ };
149
+ }
150
+ if (deps.anchorer && deps.db.getKever(pre)?.delegated && !deps.anchorer.complete(pre, sn)) {
151
+ return { state: "active", phase: "waitingDelegatorAnchor" };
152
+ }
153
+ return { state: "complete" };
154
+ }
@@ -17,6 +17,7 @@ import { Deck } from "../../core/deck.js";
17
17
  import { TransIdxSigGroup } from "../../core/dispatch.js";
18
18
  import { ValidationError } from "../../core/errors.js";
19
19
  import { Kevery } from "../../core/kel/eventing.js";
20
+ import { Kever } from "../../core/kel/kever.js";
20
21
  import { incept as inceptEvent, interact as interactEvent, query as queryEvent, receipt as receiptEvent, reply as replyEvent, rotate as rotateEvent, } from "../../core/protocol-eventing.js";
21
22
  import { messagize } from "../../core/protocol-serialization.js";
22
23
  import { HabitatRecord } from "../../core/records.js";
@@ -275,6 +276,23 @@ export class Hab {
275
276
  get accepted() {
276
277
  return !!this.pre && this.db.getKever(this.pre) !== null;
277
278
  }
279
+ /**
280
+ * Whether the held or stored signing keys currently allow this habitat to sign.
281
+ * False for a keyless habitat (`makeSignedHab`) until the host holds its signer.
282
+ */
283
+ canSign() {
284
+ try {
285
+ const probe = new Uint8Array(1);
286
+ if (this.kever?.transferable === false)
287
+ this.sign(probe, false);
288
+ else
289
+ this.sign(probe, true);
290
+ return true;
291
+ }
292
+ catch {
293
+ return false;
294
+ }
295
+ }
278
296
  /** Return the live accepted-state `Kever` for this habitat when available. */
279
297
  get kever() {
280
298
  return this.pre ? this.db.getKever(this.pre) : null;
@@ -436,8 +454,24 @@ export class Hab {
436
454
  if (!pre || !serder.said) {
437
455
  throw new Error("Expected inception serder to provide string pre and said.");
438
456
  }
439
- const opre = verfers[0].qb64;
440
- this.mgr.move(opre, pre);
457
+ const sigs = this.mgr.sign(serder.raw, keys, true);
458
+ this.mgr.move(verfers[0].qb64, pre);
459
+ this.admitInception(serder, sigs, hidden);
460
+ }
461
+ /**
462
+ * Admit one signed inception as this habitat's first event: bind `pre`,
463
+ * register the name and habitat records unless `hidden`, and accept the event
464
+ * into the local KEL.
465
+ *
466
+ * Shared tail of `make()` and `makeSigned()`. It writes no keeper state and
467
+ * never signs. On rejection the `prefixes` entry is withdrawn and the error
468
+ * propagates; callers decide what else to undo.
469
+ */
470
+ admitInception(serder, sigers, hidden) {
471
+ const pre = serder.pre;
472
+ if (!pre || !serder.said) {
473
+ throw new Error("Expected inception serder to provide string pre and said.");
474
+ }
441
475
  this.pre = pre;
442
476
  if (!hidden) {
443
477
  const habord = new HabitatRecord({
@@ -449,9 +483,8 @@ export class Hab {
449
483
  this.db.pinName(this.ns ?? "", this.name, pre);
450
484
  this.db.prefixes.add(pre);
451
485
  }
452
- const sigs = this.mgr.sign(serder.raw, keys, true);
453
486
  try {
454
- this.acceptLocally(serder, sigs);
487
+ this.acceptLocally(serder, sigers);
455
488
  }
456
489
  catch (error) {
457
490
  if (!hidden) {
@@ -460,6 +493,50 @@ export class Hab {
460
493
  throw error;
461
494
  }
462
495
  }
496
+ /**
497
+ * Adopt a pre-signed inception this `Habery` did not generate, with no
498
+ * keeper key state for it (KERIpy `SignifyHab.incept` / `makeSignifyHab`).
499
+ *
500
+ * The inception is evaluated first, without mutation, by the same `Kever`
501
+ * decision local acceptance uses: SAID, prefix derivation, key and threshold
502
+ * material, and the signatures against the event's own keys. Anything but an
503
+ * accept (including an escrow for missing signatures) is refused before any
504
+ * record is written. A name or prefix already in use is refused too.
505
+ *
506
+ * Differences from KERIpy: verification precedes persistence instead of
507
+ * following it, a taken name is refused before anything is written (KERIpy
508
+ * pins the habitat record first), and `sign` is not disabled; it succeeds
509
+ * once the host holds the matching signer (`Manager.hold`).
510
+ */
511
+ makeSigned(args) {
512
+ const { serder, sigers, hidden = false } = args;
513
+ const pre = serder.pre;
514
+ if (!pre || !serder.said) {
515
+ throw new ValidationError("Pre-signed inception must provide a prefix and SAID.");
516
+ }
517
+ if (this.db.getHab(pre) || this.db.getKever(pre) || this.db.prefixes.has(pre)) {
518
+ throw new ValidationError(`Habitat prefix ${pre} already exists.`);
519
+ }
520
+ if (!hidden && this.db.getName(this.ns ?? "", this.name) !== null) {
521
+ throw new ValidationError(`Habitat name ${this.name} already exists.`);
522
+ }
523
+ const decision = Kever.evaluateInception({ db: this.db, serder, sigers, local: true });
524
+ if (decision.kind !== "accept") {
525
+ const detail = decision.kind === "duplicate" ? decision.duplicate : decision.message;
526
+ throw new ValidationError(`Pre-signed inception ${serder.said} refused: ${detail}`);
527
+ }
528
+ try {
529
+ this.admitInception(serder, sigers, hidden);
530
+ }
531
+ catch (error) {
532
+ if (!hidden) {
533
+ this.db.habs.rem(pre);
534
+ this.db.names.rem([this.ns ?? "", this.name]);
535
+ }
536
+ this.pre = "";
537
+ throw error;
538
+ }
539
+ }
463
540
  /**
464
541
  * Rotate this habitat through the shared accepted-state path.
465
542
  *
@@ -1190,6 +1267,17 @@ export class Habery {
1190
1267
  writable: true,
1191
1268
  value: void 0
1192
1269
  });
1270
+ /**
1271
+ * Prefixes of habitats whose alias config was not applied at open because they
1272
+ * could not sign yet (a keyless habitat before the host holds its signer). The
1273
+ * host calls `hab.reconfigure()` after holding; applying config is retried then.
1274
+ */
1275
+ Object.defineProperty(this, "deferredReconfigure", {
1276
+ enumerable: true,
1277
+ configurable: true,
1278
+ writable: true,
1279
+ value: []
1280
+ });
1193
1281
  this.storeOpener = opener;
1194
1282
  this.borrowsStores = borrowsStores;
1195
1283
  this.name = name;
@@ -1237,8 +1325,10 @@ export class Habery {
1237
1325
  /**
1238
1326
  * Populate the in-memory habitat cache from durable `habs.` + `states.` data.
1239
1327
  *
1240
- * Bare metadata records without corresponding accepted key state are skipped
1241
- * so `Habery.habs` only contains reopenable local habitats.
1328
+ * Like KERIpy `loadHabs`, a local group record is held even while its
1329
+ * inception is unaccepted: the `Hab` reads accepted state on demand, so it
1330
+ * becomes usable the moment the event is accepted. A non-group record without
1331
+ * accepted state is an orphan; `Baser.reloadKevers` already dropped it.
1242
1332
  */
1243
1333
  loadHabs() {
1244
1334
  this.reconfigure();
@@ -1251,13 +1341,20 @@ export class Habery {
1251
1341
  const hab = new Hab(habord.name, this.db, this.ks, this.mgr, this.cf, this.rtr, this.rvy, this.kevery, habord.domain, hid);
1252
1342
  if (!hab.accepted) {
1253
1343
  if (habord.mid) {
1344
+ this.habs.set(hab.pre, hab);
1254
1345
  continue;
1255
1346
  }
1256
1347
  throw new ValidationError(`Problem loading Hab pre=${hid} name=${habord.name} from db.`);
1257
1348
  }
1258
1349
  this.habs.set(hab.pre, hab);
1259
1350
  }
1351
+ this.deferredReconfigure.length = 0;
1260
1352
  for (const hab of this.habs.values()) {
1353
+ // Config replies are signed. A habitat that cannot sign yet applies them once its signer is held.
1354
+ if (hab.accepted && hab.configuredSection() && !hab.canSign()) {
1355
+ this.deferredReconfigure.push(hab.pre);
1356
+ continue;
1357
+ }
1261
1358
  hab.reconfigure();
1262
1359
  }
1263
1360
  // Restart recovery: commit members of an accepted establishment event
@@ -1327,6 +1424,32 @@ export class Habery {
1327
1424
  }
1328
1425
  }
1329
1426
  }
1427
+ /**
1428
+ * Adopt an inception the caller built and signed, creating a habitat with no
1429
+ * keeper key state (KERIpy `makeSignifyHab`).
1430
+ *
1431
+ * Contract:
1432
+ * - the inception and its signatures are verified before anything is
1433
+ * persisted; a bad, under-signed or duplicate inception is refused and
1434
+ * leaves no record behind
1435
+ * - nothing is written to the keeper, so the hab cannot sign until the host
1436
+ * calls `mgr.hold()` with the matching signer(s), cannot rotate, and after
1437
+ * reopen is present again with signing unavailable until re-held
1438
+ * - hold signers with the encoding the inception's keys use (`D...` for
1439
+ * transferable, `B...` for non-transferable)
1440
+ * - unlike `makeHab`, bootstrap config replies are not applied, since they
1441
+ * need a signing key; the host reconfigures after holding
1442
+ */
1443
+ makeSignedHab(name, ns, args) {
1444
+ const pre = args.serder.pre;
1445
+ if (pre && this.habs.has(pre)) {
1446
+ throw new ValidationError(`Habitat prefix ${pre} already exists.`);
1447
+ }
1448
+ const hab = new Hab(name, this.db, this.ks, this.mgr, this.cf, this.rtr, this.rvy, this.kevery, ns, "");
1449
+ hab.makeSigned(args);
1450
+ this.habs.set(hab.pre, hab);
1451
+ return hab;
1452
+ }
1330
1453
  /** Creates and caches a new habitat under this habery. */
1331
1454
  makeHab(name, ns, args = {}) {
1332
1455
  const hab = new Hab(name, this.db, this.ks, this.mgr, this.cf, this.rtr, this.rvy, this.kevery, ns, "");
@@ -241,6 +241,16 @@ export class Manager {
241
241
  writable: true,
242
242
  value: null
243
243
  });
244
+ /**
245
+ * Borrowed, volatile signers keyed by qualified public key (`hold()`).
246
+ * Never written to the Keeper and never consulted by `Keeper` rows.
247
+ */
248
+ Object.defineProperty(this, "held", {
249
+ enumerable: true,
250
+ configurable: true,
251
+ writable: true,
252
+ value: new Map()
253
+ });
244
254
  const { ks, seed = "", aeid = "", pidx = 0, algo = Algos.salty, salt = randomSaltQb64(), tier = Tiers.low, } = args;
245
255
  this._ks = ks;
246
256
  this._seed = seed;
@@ -428,13 +438,21 @@ export class Manager {
428
438
  }
429
439
  return root;
430
440
  }
431
- /** Retain once, returning false for the identical root without replacing ciphertext. */
432
- putRegistryRoot(aid, regid, root) {
441
+ /**
442
+ * Retain once, returning false for the identical root without replacing ciphertext. `overwrite` replaces a
443
+ * different held root; only a caller that has shown that root was never used (no update staged or accepted
444
+ * for its registry) may set it.
445
+ */
446
+ putRegistryRoot(aid, regid, root, overwrite = false) {
433
447
  const keys = this.registryRootKeys(aid, regid);
434
448
  if (!(root instanceof Salter) || root.code !== MtrDex.Salt_128)
435
449
  throw new Error("Registry root must be Salt128");
436
450
  const { aeid, encrypter, decrypter } = this.registryRootCrypto();
437
- return this.ks.retainRegistryRoot(keys, root, aeid, encrypter, decrypter);
451
+ return this.ks.retainRegistryRoot(keys, root, aeid, encrypter, decrypter, overwrite);
452
+ }
453
+ /** Whether a root is retained for `aid` and `regid`; reads no ciphertext and needs no unlocked Keeper. */
454
+ hasRegistryRoot(aid, regid) {
455
+ return !!this.ks.rroots.get(this.registryRootKeys(aid, regid));
438
456
  }
439
457
  signerDecrypter() {
440
458
  if (this.aeid && !this.decrypter) {
@@ -442,8 +460,63 @@ export class Manager {
442
460
  }
443
461
  return this.decrypter ?? undefined;
444
462
  }
445
- /** Load one managed signer seed by its public verifier key. */
463
+ /**
464
+ * Borrow live signers for signing, decryption and ESSR opening without
465
+ * persisting them.
466
+ *
467
+ * Held signers are consulted before stored keys by the one private lookup
468
+ * every `sign`, `decrypt`, `open`, group-member and endpoint-role path
469
+ * resolves through. They live only in this `Manager` instance's memory:
470
+ * nothing is written to any Keeper table, re-encryption by `updateAeid()`
471
+ * neither reads nor changes them, and a new `Manager` over the same Keeper
472
+ * starts with none.
473
+ *
474
+ * Contract:
475
+ * - The table is keyed by `signer.verfer.qb64`. The same raw key encodes
476
+ * differently when transferable (`D...`) and non-transferable (`B...`), so
477
+ * build each `Signer` with the transferability the key list or prefix uses,
478
+ * and hold that encoding. A request for the other encoding does not match.
479
+ * - The host owns each `Signer` and its seed bytes, including zeroing them.
480
+ * This keeps the reference only; it never copies seed bytes and never
481
+ * erases them. Dropping a reference with `release()` does not zero memory.
482
+ * - Holding a pub that is already held replaces the earlier signer. A held
483
+ * signer shadows a stored key with the same public key.
484
+ * - The `pre/path` branch of `sign()` re-derives salty keys from the stored
485
+ * prefix salt and never consults held signers.
486
+ *
487
+ * @param signers Signers to borrow; all are validated before any is held.
488
+ */
489
+ hold(signers) {
490
+ const batch = new Map();
491
+ for (const signer of signers) {
492
+ if (!(signer instanceof Signer)) {
493
+ throw new ValidationError("Held signers must be Signer instances");
494
+ }
495
+ batch.set(signer.verfer.qb64, signer);
496
+ }
497
+ for (const [pub, signer] of batch)
498
+ this.held.set(pub, signer);
499
+ }
500
+ /**
501
+ * Drop held signer references: all of them, or only those for `pubs`.
502
+ *
503
+ * Unheld pubs are ignored. Afterwards a request for a released key resolves
504
+ * from stored keys only and fails as any missing key does. This drops
505
+ * references; zeroing a signer's seed stays the host's job.
506
+ */
507
+ release(pubs) {
508
+ if (pubs === undefined) {
509
+ this.held.clear();
510
+ return;
511
+ }
512
+ for (const pub of pubs)
513
+ this.held.delete(pub);
514
+ }
515
+ /** Resolve one signer by qualified public key: held first, then the Keeper's `pris.`. */
446
516
  getSignerByPub(pub) {
517
+ const held = this.held.get(pub);
518
+ if (held)
519
+ return held;
447
520
  const signer = this.ks.pris.get(pub, this.signerDecrypter());
448
521
  if (!signer) {
449
522
  throw new Error(`Missing prikey in db for pubkey=${pub}`);