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
@@ -0,0 +1,93 @@
1
+ import { ValidationError } from "../../core/errors.js";
2
+ import { acceptIpexExchange, ipexExchangeStatus, requireIpexPrior, requireIpexSender, } from "./ipex-conversation.js";
3
+ import { ipexCredentialAdmit, ipexCredentialGrant, processCredentialPresentationArtifacts, storedGrantArtifacts, validateAdmitGrant, } from "./ipex-credentialing.js";
4
+ import { requireStoredExchange, sendCredentialStream } from "./ipex-grouping.js";
5
+ /**
6
+ * Grant a stored single-signature credential: validate the optional agree,
7
+ * assemble the embedded artifacts and support messages, sign, accept locally
8
+ * and deliver support then grant as one stream. Granting a credential again
9
+ * without an agree authors another grant; an agree answers once.
10
+ *
11
+ * @throws ValidationError for a non-local sender, a refused prior, missing local
12
+ * credential evidence or a grant local state does not accept.
13
+ */
14
+ export function* sendIpexGrant(deps, sender, { recipient, credential, message = "", agree, gvrsn, deliver = true }) {
15
+ requireIpexSender(deps.hby, sender);
16
+ if (agree)
17
+ requireIpexPrior(deps.hby, sender.pre, recipient, agree, "grant");
18
+ const built = ipexCredentialGrant({
19
+ hby: deps.hby,
20
+ hab: sender,
21
+ reger: deps.reger,
22
+ recipient,
23
+ credentialSaid: credential,
24
+ message,
25
+ options: { agree: agree ? deps.hby.db.exns.get([agree]) : null, gvrsn },
26
+ });
27
+ const genus = built.grant.gvrsn ?? gvrsn ?? built.grant.pvrsn;
28
+ yield* acceptIpexExchange(deps, built.grant, built.wire, genus, "Local IPEX grant was not accepted.", agree);
29
+ const deliveries = deliver
30
+ ? yield* sendCredentialStream(deps.postman, sender, recipient, [...built.support, built.wire])
31
+ : [];
32
+ return { grant: built.grant, credential, support: built.support, wire: built.wire, deliveries };
33
+ }
34
+ /**
35
+ * Validate a stored grant for admission by `holder` without signing: it is
36
+ * accepted, addressed to the holder, carries a credential and has no accepted
37
+ * response yet. Saving is not required here.
38
+ *
39
+ * @throws ValidationError when the grant is not stored, was already answered or is not addressed to `holder`.
40
+ */
41
+ export function requireAdmittableGrant(deps, holder, grantSaid) {
42
+ const grant = requireStoredExchange(deps.hby, grantSaid);
43
+ const sender = grant.ked?.i;
44
+ if (typeof sender !== "string" || sender.length === 0) {
45
+ throw new ValidationError("Grant is missing sender AID.");
46
+ }
47
+ requireIpexPrior(deps.hby, holder.pre, sender, grant.said, "admit");
48
+ const credential = validateAdmitGrant(grant, holder.pre, deps.reger, false);
49
+ return { grant, recipient: sender, credential };
50
+ }
51
+ /**
52
+ * The holder's consent to a grant: validate the stored grant, sign an admit,
53
+ * accept it locally and deliver it to the grant's sender. A grant that already
54
+ * has an accepted response is refused, so a second admit never re-signs.
55
+ *
56
+ * @throws ValidationError as for {@link requireAdmittableGrant}, for a credential
57
+ * that is not saved when `requireSaved` holds, or for an admit local state does not accept.
58
+ */
59
+ export function* sendIpexAdmit(deps, holder, grantSaid, { message = "", gvrsn, requireSaved = true, deliver = true } = {}) {
60
+ requireIpexSender(deps.hby, holder);
61
+ const { grant, recipient, credential } = requireAdmittableGrant(deps, holder, grantSaid);
62
+ const saved = !!deps.reger.saved.get([credential]);
63
+ const prepared = ipexCredentialAdmit({
64
+ hab: holder,
65
+ reger: deps.reger,
66
+ grant,
67
+ message,
68
+ options: { requireSaved, gvrsn },
69
+ });
70
+ const genus = prepared.admit.gvrsn ?? gvrsn ?? prepared.admit.pvrsn;
71
+ yield* acceptIpexExchange(deps, prepared.admit, prepared.wire, genus, "Local IPEX admit was not accepted.", grant.said);
72
+ const deliveries = deliver ? yield* sendCredentialStream(deps.postman, holder, recipient, [prepared.wire]) : [];
73
+ return { admit: prepared.admit, grant, credential, saved, wire: prepared.wire, deliveries };
74
+ }
75
+ /**
76
+ * Import a stored grant's authenticated artifacts once, so the wallet can save
77
+ * its credential as evidence resolves. Idempotent: a credential that is already
78
+ * saved is not replayed. Signs nothing and does not wait; observe the outcome
79
+ * with `waitForIpexExchange(..., { until: "credential-saved" })` while the
80
+ * host's workers run.
81
+ *
82
+ * @param holder AID the grant must be addressed to.
83
+ * @returns The grant's status after the import.
84
+ * @throws ValidationError when the grant is not stored or not addressed to `holder`.
85
+ */
86
+ export function* settleGrantCredential(deps, holder, grantSaid, { gvrsn } = {}) {
87
+ const grant = requireStoredExchange(deps.hby, grantSaid);
88
+ const credential = validateAdmitGrant(grant, holder, deps.reger, false);
89
+ if (!deps.reger.saved.get([credential])) {
90
+ yield* processCredentialPresentationArtifacts(deps.protocol, storedGrantArtifacts(deps.hby, grant, gvrsn));
91
+ }
92
+ return ipexExchangeStatus(deps, grantSaid);
93
+ }
@@ -36,15 +36,20 @@ function acdcV2GraphUse(hby, registry, origin, nests, walk) {
36
36
  const graph = walkIpexGraph(origin, nests, walk);
37
37
  if (!graph)
38
38
  throw new ValidationError("ACDC v2 group graph is malformed or incomplete.");
39
- const verdicts = new Map();
39
+ const verdicts = new Map(), why = [];
40
40
  for (const [said, node] of graph.nodes) {
41
- verdicts.set(said, issuedNodeVerdict(authenticateIpexNode(node.body, envelopeFromFrame(node), hby.db, registry)));
41
+ const authentication = authenticateIpexNode(node.body, envelopeFromFrame(node), hby.db, registry);
42
+ verdicts.set(said, issuedNodeVerdict(authentication));
43
+ if (authentication.kind !== "authenticated")
44
+ why.push(`${said} ${authentication.kind}: ${authentication.reason}`);
42
45
  }
43
46
  const verdict = evaluateChain(graph, verdicts, hby.db);
44
47
  if (verdict?.kind === "unknown" && verdict.retryable)
45
48
  return null;
46
- if (verdict?.kind !== "valid")
47
- throw new ValidationError("ACDC v2 group graph is false or unresolved.");
49
+ if (verdict?.kind !== "valid") {
50
+ const found = !verdict ? "no verdict" : verdict.kind === "unknown" ? `unknown: ${verdict.reason}` : verdict.kind;
51
+ throw new ValidationError(`ACDC v2 group graph is false or unresolved (${found}${why.length ? `; ${why.join("; ")}` : ""}).`);
52
+ }
48
53
  return true;
49
54
  }
50
55
  /** Current retained Grant authentication and graph truth are separate from protocol completion/history. */
@@ -136,20 +141,13 @@ export function* prepareAcdcV2GroupIpex(hby, protocol, group, raw) {
136
141
  return wire;
137
142
  }
138
143
  /**
139
- * Approve one pending multisig wrapper around an embedded IPEX message.
140
- *
141
- * @param hby Borrowed local identities and accepted-state stores.
142
- * @param protocol Borrowed semantic owner; this approval creates its own byte-input context.
143
- * @param postman Borrowed delivery owner; the caller runs and joins its worker.
144
- * @param reger Explicit legacy store, required for grant approval/delivery and fresh admit approval.
145
- * @param wrapper Accepted multisig exchange carrying the proposed IPEX child.
146
- * @param options Approval/genus policy used for the existing group workflow.
147
- * @returns Approval and current group/protocol completion information.
144
+ * Approve one stored multisig wrapper around an IPEX message locally: validate it, reuse or sign this member's
145
+ * contribution and accept it, without publishing or sending anything. The explicit consent of the library's group
146
+ * IPEX operations; {@link approveMultisigIpex} adds publication and the lead's delivery.
148
147
  */
149
- export function* approveMultisigIpex(hby, protocol, postman, reger, wrapper, options = {}) {
148
+ export function* approveMultisigIpexLocally(hby, protocol, reger, wrapper) {
150
149
  const { child, groupHab } = yield* loadIpexProposal(hby, wrapper);
151
150
  const { event: embedded, genus } = child;
152
- const embeddedSaid = embedded.said;
153
151
  if (embedded.pvrsn.major === 1 && embedded.route === IPEX_GRANT_ROUTE && !reger) {
154
152
  throw new ValidationError("VDR runtime did not open Reger.");
155
153
  }
@@ -166,12 +164,30 @@ export function* approveMultisigIpex(hby, protocol, postman, reger, wrapper, opt
166
164
  }
167
165
  }
168
166
  const approved = yield* approveIpexChild(hby, protocol, groupHab, child, wrapper, reger);
169
- if (!approved)
170
- return { approved: null, accepted: protocol.exc.complete(embeddedSaid), messages: [], deliveries: [] };
167
+ return { embedded, groupHab, genus, approved };
168
+ }
169
+ /**
170
+ * Approve one pending multisig wrapper around an embedded IPEX message.
171
+ *
172
+ * @param hby Borrowed local identities and accepted-state stores.
173
+ * @param protocol Borrowed semantic owner; this approval creates its own byte-input context.
174
+ * @param postman Borrowed delivery owner; the caller runs and joins its worker.
175
+ * @param reger Explicit legacy store, required for grant approval/delivery and fresh admit approval.
176
+ * @param wrapper Accepted multisig exchange carrying the proposed IPEX child.
177
+ * @param options Approval/genus policy used for the existing group workflow.
178
+ * @returns Approval and current group/protocol completion information.
179
+ */
180
+ export function* approveMultisigIpex(hby, protocol, postman, reger, wrapper, options = {}) {
181
+ const local = yield* approveMultisigIpexLocally(hby, protocol, reger, wrapper);
182
+ const { embedded, groupHab, genus, approved } = local;
183
+ const embeddedSaid = embedded.said;
184
+ if (!approved) {
185
+ return { approved: null, accepted: protocol.exc.complete(embeddedSaid), messages: [], deliveries: [], members: [] };
186
+ }
171
187
  const publication = options.publish
172
188
  ? yield* publishGroupIpexProposal(hby, protocol, postman, groupHab, approved, genus)
173
- : { messages: [], deliveries: [] };
174
- const deliveries = publication.deliveries;
189
+ : { messages: [], deliveries: [], members: [] };
190
+ const deliveries = [...publication.deliveries];
175
191
  if ((options.sendLead ?? true)
176
192
  && hby.db.exns.get([embeddedSaid])?.said === embeddedSaid
177
193
  && protocol.exc.lead(groupHab, embeddedSaid)) {
@@ -181,6 +197,7 @@ export function* approveMultisigIpex(hby, protocol, postman, reger, wrapper, opt
181
197
  accepted: hby.db.exns.get([embeddedSaid])?.said === embeddedSaid,
182
198
  messages: publication.messages,
183
199
  deliveries,
200
+ members: publication.members,
184
201
  approved,
185
202
  };
186
203
  }
@@ -420,6 +437,7 @@ export function* publishInitialGroupIpex(hby, protocol, postman, groupHab, embed
420
437
  recipient: message.recipient,
421
438
  exnSaid: message.exnSaid,
422
439
  payloadSaid: message.payloadSaid,
440
+ outcome: "delivered",
423
441
  deliveries: outcome.deliveries,
424
442
  });
425
443
  }
@@ -665,3 +683,16 @@ function hexToFixedBytes(hex, size) {
665
683
  }
666
684
  return raw;
667
685
  }
686
+ /** The stored `/multisig/exn` wrapper that carries the IPEX message `embeddedSaid`, if one is held. */
687
+ export function findStoredMultisigIpex(db, embeddedSaid) {
688
+ for (const [, wrapper] of db.exns.getTopItemIter()) {
689
+ if (wrapper.route === MULTISIG_EXN_ROUTE && storedMultisigIpexBody(db, wrapper)?.said === embeddedSaid) {
690
+ return wrapper;
691
+ }
692
+ }
693
+ return null;
694
+ }
695
+ /** Whether the local member of `group` already holds a verified contribution to `embedded` (a recorded approval). */
696
+ export function groupIpexApproved(hby, group, embedded) {
697
+ return !!localIpexContribution(hby.db, localGroupMember(hby, group).pre, embedded, rebuildStoredExchangeGroups(hby.db, embedded.said));
698
+ }
@@ -1,9 +1,10 @@
1
1
  /** Node issuer authentication over public KEL/TEL evidence; no conversation or validity policy. */
2
- import { Diger, NumberPrimitive, Prefixer } from "cesr-ts";
2
+ import { Diger, NumberPrimitive, Prefixer, SerderACDC } from "cesr-ts";
3
3
  import { validateRip, validateUpdate, vetBinds, vetBlind, vetBound, } from "../../acdc/regeventing.js";
4
4
  import { TransIdxSigGroup } from "../../core/dispatch.js";
5
5
  import { DatabaseOperationError } from "../../core/errors.js";
6
6
  import { verifyExchangeProofs } from "../../core/exchange/exchange-proofing.js";
7
+ import { envelopeFromFrame } from "../protocol/parsering.js";
7
8
  /** Protocol admission authenticates registry observations without imposing an application state vocabulary. */
8
9
  export function authenticatedNodeVerdict(authentication) {
9
10
  switch (authentication.kind) {
@@ -65,35 +66,57 @@ export function acceptedRegistryEvidence(store, regid) {
65
66
  }
66
67
  return { rip, updates };
67
68
  }
69
+ /**
70
+ * Whether a Grant's origin node is a fresh issuance: a credential its own sender issues, disclosed with no registry
71
+ * proof because no registry update has issued it yet. A presentation of an issued credential carries the proof
72
+ * that opens its registry update, so it never matches. Both are Grants on the wire; only a fresh one is consented to
73
+ * as an issuance. The answer is the same before and after the registry update is approved.
74
+ */
75
+ export function isIssuanceOrigin(sender, origin) {
76
+ const body = origin?.body;
77
+ if (!(body instanceof SerderACDC) || body.issuer !== sender || !body.regid)
78
+ return false;
79
+ const { bsqs, bsss } = envelopeFromFrame(origin);
80
+ return !bsqs.length && !bsss.length;
81
+ }
68
82
  /** A declared registry, then supplied anchors, take precedence over current signatures. */
69
83
  export function authenticateIpexNode(serder, envelope, db, registry, historical = false) {
70
84
  if (serder.regid) {
71
85
  const proofs = [...envelope.bsqs, ...envelope.bsss];
72
- if (!proofs.length || !registry)
73
- return { kind: "reject" };
86
+ if (!proofs.length || !registry) {
87
+ return {
88
+ kind: "reject",
89
+ reason: "The node declares a registry but carries no issuer proof or no registry store is open.",
90
+ };
91
+ }
74
92
  const chain = acceptedRegistryEvidence(registry, serder.regid);
75
93
  if (!chain)
76
94
  return { kind: "missing", reason: `Missing local TEL evidence for ${serder.regid}.` };
77
95
  // A RIP alone authenticates ownership, never a disclosed credential state.
78
- if (!chain.updates.length)
79
- return { kind: "reject" };
96
+ if (!chain.updates.length) {
97
+ return {
98
+ kind: "reject",
99
+ reason: "The registry has only its inception; a RIP alone authenticates ownership, never a disclosed credential state.",
100
+ };
101
+ }
80
102
  let at;
81
103
  if (historical) {
82
104
  if (!serder.verify() || serder.issuer !== chain.rip.issuer || serder.regid !== chain.rip.said) {
83
- return { kind: "reject" };
105
+ return { kind: "reject", reason: "The node differs from the registry inception it declares." };
84
106
  }
85
107
  // Authenticate all supplied bodies/duplicates and known bound contradictions
86
108
  // before missing evidence wins, independently of attachment order.
87
109
  if (proofs.some((proof) => !vetBlind(proof, proof.d.nonce))
88
110
  || new Set(proofs.map((proof) => proof.d.nonce)).size !== proofs.length)
89
- return { kind: "reject" };
111
+ return { kind: "reject", reason: "The disclosed issuer proofs are malformed or repeat a nonce." };
90
112
  let unresolved = false;
91
113
  for (const proof of proofs) {
92
114
  if (proof.td.nonce && proof.td.nonce !== serder.said)
93
115
  continue;
94
116
  const bound = vetBound(proof, serder, db);
95
- if (bound?.kind === "reject")
96
- return { kind: "reject" };
117
+ if (bound?.kind === "reject") {
118
+ return { kind: "reject", reason: "A disclosed issuer proof contradicts the node." };
119
+ }
97
120
  if (bound)
98
121
  unresolved = true;
99
122
  }
@@ -103,7 +126,7 @@ export function authenticateIpexNode(serder, envelope, db, registry, historical
103
126
  continue;
104
127
  const matches = chain.updates.filter((event) => event.sad.b === proof.d.nonce);
105
128
  if (matches.length > 1)
106
- return { kind: "reject" };
129
+ return { kind: "reject", reason: "Several registry updates match one issuer proof." };
107
130
  if (matches.length)
108
131
  selected.push(matches[0]);
109
132
  else
@@ -111,8 +134,9 @@ export function authenticateIpexNode(serder, envelope, db, registry, historical
111
134
  }
112
135
  if (unresolved)
113
136
  return { kind: "missing", reason: `Missing retained issuer proof evidence for ${serder.said}.` };
114
- if (!selected.length)
115
- return { kind: "reject" };
137
+ if (!selected.length) {
138
+ return { kind: "reject", reason: "No registry update matches the disclosed issuer proofs." };
139
+ }
116
140
  const candidates = new Set(selected.map((event) => event.said));
117
141
  // Accepted history is ascending. Vacuous and other-target openings cannot
118
142
  // advance this issuer prefix; generic source locators never select it.
@@ -131,7 +155,7 @@ export function authenticateIpexNode(serder, envelope, db, registry, historical
131
155
  }
132
156
  return result.kind === "verified" && result.state.regid === serder.regid
133
157
  ? { kind: "authenticated", registration: result.state }
134
- : { kind: "reject" };
158
+ : { kind: "reject", reason: "The registry update does not bind the node." };
135
159
  }
136
160
  // Disclosed inner rd without top-level rd is an unsupported hidden issuer registry.
137
161
  // Compact aggregate entries expose no declaration and remain opaque here.
@@ -139,15 +163,15 @@ export function authenticateIpexNode(serder, envelope, db, registry, historical
139
163
  const sections = [serder.sad.a, ...(Array.isArray(aggregate) ? aggregate.slice(1) : [aggregate])];
140
164
  if (sections.some(section => section && typeof section === "object" && !Array.isArray(section)
141
165
  && section.rd))
142
- return { kind: "reject" };
166
+ return { kind: "reject", reason: "A disclosed inner registry has no top-level declaration." };
143
167
  if (!serder.issuer)
144
- return { kind: "reject" };
168
+ return { kind: "reject", reason: "The node names no issuer." };
145
169
  let issuer;
146
170
  try {
147
171
  issuer = new Prefixer({ qb64: serder.issuer });
148
172
  }
149
173
  catch {
150
- return { kind: "reject" };
174
+ return { kind: "reject", reason: "The node names a malformed issuer." };
151
175
  }
152
176
  const sourceSeals = [
153
177
  ...envelope.sscs.map((seal) => ({ i: issuer, ...seal })),
@@ -159,7 +183,7 @@ export function authenticateIpexNode(serder, envelope, db, registry, historical
159
183
  ? { kind: "missing", reason: `Missing issuer KEL anchor for ${serder.said}.` }
160
184
  : result.sourceSeals.length > 0
161
185
  ? { kind: "authenticated", registration: null }
162
- : { kind: "reject" };
186
+ : { kind: "reject", reason: "No issuer KEL anchor seals the node." };
163
187
  }
164
188
  const explicit = envelope.tsgs.filter((group) => group.pre === issuer.qb64);
165
189
  const last = envelope.ssgs.filter((group) => group.pre === issuer.qb64);
@@ -181,5 +205,5 @@ export function authenticateIpexNode(serder, envelope, db, registry, historical
181
205
  ? { kind: "missing", reason: `Missing current issuer KEL evidence for ${serder.said}.` }
182
206
  : result.tsgs.length + result.cigars.length > 0
183
207
  ? { kind: "authenticated", registration: null }
184
- : { kind: "reject" };
208
+ : { kind: "reject", reason: "No current issuer signature authenticates the node." };
185
209
  }