keri-ts 2.2.4 → 2.2.6

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 (256) hide show
  1. package/esm/keri/npm/src/_dnt.polyfills.js +14 -14
  2. package/esm/keri/npm/src/acdc/dhking.js +29 -2
  3. package/esm/keri/npm/src/acdc/observing.js +10 -3
  4. package/esm/keri/npm/src/acdc/query-resend.js +74 -0
  5. package/esm/keri/npm/src/acdc/regengine.js +39 -9
  6. package/esm/keri/npm/src/acdc/regeventing.js +5 -3
  7. package/esm/keri/npm/src/acdc/registering.js +19 -0
  8. package/esm/keri/npm/src/acdc/salting.js +4 -0
  9. package/esm/keri/npm/src/acdc/unblinding.js +38 -3
  10. package/esm/keri/npm/src/app/bootstrap/authenticating.js +32 -10
  11. package/esm/keri/npm/src/app/bootstrap/oobiery.js +363 -30
  12. package/esm/keri/npm/src/app/credentials/credential-importing.js +33 -4
  13. package/esm/keri/npm/src/app/credentials/root-replicator.js +27 -15
  14. package/esm/keri/npm/src/app/credentials/schema-resolving.js +5 -1
  15. package/esm/keri/npm/src/app/credentials/tel-publishing.js +16 -7
  16. package/esm/keri/npm/src/app/delivery/forwarding.js +205 -44
  17. package/esm/keri/npm/src/app/delivery/relaying.js +232 -0
  18. package/esm/keri/npm/src/app/delivery/respondant.js +8 -5
  19. package/esm/keri/npm/src/app/exchanges/exchange-messaging.js +1 -1
  20. package/esm/keri/npm/src/app/exchanges/exchanging.js +65 -9
  21. package/esm/keri/npm/src/app/identity/delegating.js +66 -9
  22. package/esm/keri/npm/src/app/identity/habbing.js +190 -71
  23. package/esm/keri/npm/src/app/identity/keeping.js +111 -39
  24. package/esm/keri/npm/src/app/identity/retire-identifier.js +98 -0
  25. package/esm/keri/npm/src/app/ipex/disclosure-replaying.js +116 -0
  26. package/esm/keri/npm/src/app/ipex/group-ipex.js +122 -25
  27. package/esm/keri/npm/src/app/ipex/group-issuance.js +137 -37
  28. package/esm/keri/npm/src/app/ipex/ipex-discloser.js +94 -31
  29. package/esm/keri/npm/src/app/ipex/ipex-grouping.js +53 -3
  30. package/esm/keri/npm/src/app/ipex/ipex-v2.js +7 -2
  31. package/esm/keri/npm/src/app/ipex/issuance.js +147 -44
  32. package/esm/keri/npm/src/app/ipex/pending-presentations.js +4 -2
  33. package/esm/keri/npm/src/app/ipex/presenting.js +3 -18
  34. package/esm/keri/npm/src/app/ipex/receive-issuance.js +2 -1
  35. package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +39 -11
  36. package/esm/keri/npm/src/app/mailbox/agent-inbox.js +292 -0
  37. package/esm/keri/npm/src/app/mailbox/forward-handler.js +298 -52
  38. package/esm/keri/npm/src/app/mailbox/kel-publisher.js +26 -31
  39. package/esm/keri/npm/src/app/mailbox/mailbox-poller.js +70 -62
  40. package/esm/keri/npm/src/app/mailbox/mailboxing.js +20 -4
  41. package/esm/keri/npm/src/app/multisig/counseling.js +71 -27
  42. package/esm/keri/npm/src/app/multisig/group-members.js +41 -5
  43. package/esm/keri/npm/src/app/multisig/grouping.js +50 -2
  44. package/esm/keri/npm/src/app/multisig/multisig-workflows.js +3 -18
  45. package/esm/keri/npm/src/app/multisig/proposing.js +1 -16
  46. package/esm/keri/npm/src/app/multisig/rejoin-group.js +99 -0
  47. package/esm/keri/npm/src/app/multisig/replace-member.js +29 -8
  48. package/esm/keri/npm/src/app/protocol/parsering.js +45 -17
  49. package/esm/keri/npm/src/app/protocol/protocol-processing.js +47 -21
  50. package/esm/keri/npm/src/app/queries/query-replies.js +0 -22
  51. package/esm/keri/npm/src/app/queries/relay-refresh.js +81 -0
  52. package/esm/keri/npm/src/app/queries/witness-inquisitor.js +180 -34
  53. package/esm/keri/npm/src/app/runtime/agent-runtime.js +42 -73
  54. package/esm/keri/npm/src/app/runtime/cue-runtime.js +45 -5
  55. package/esm/keri/npm/src/app/runtime/ipex-auxiliaries.js +8 -1
  56. package/esm/keri/npm/src/app/runtime/operation-owners.js +26 -56
  57. package/esm/keri/npm/src/app/runtime/workflow-contract.js +7 -4
  58. package/esm/keri/npm/src/app/transport/http-client.js +20 -2
  59. package/esm/keri/npm/src/app/transport/message-source.js +2 -1
  60. package/esm/keri/npm/src/app/transport/messengering.js +39 -8
  61. package/esm/keri/npm/src/app/witness/ingress.js +7 -0
  62. package/esm/keri/npm/src/app/witness/receipt-client.js +43 -16
  63. package/esm/keri/npm/src/app/witness/receipting.js +62 -20
  64. package/esm/keri/npm/src/cli/messaging/multisig.js +4 -3
  65. package/esm/keri/npm/src/core/errors.js +73 -0
  66. package/esm/keri/npm/src/core/kel/delegation-ancestry.js +11 -2
  67. package/esm/keri/npm/src/core/kel/eventing.js +25 -28
  68. package/esm/keri/npm/src/core/kel/kever.js +15 -9
  69. package/esm/keri/npm/src/core/mailbox/kram-policy.js +16 -0
  70. package/esm/keri/npm/src/core/mailbox/kram-pruning.js +25 -6
  71. package/esm/keri/npm/src/core/mailbox/kram-time.js +34 -6
  72. package/esm/keri/npm/src/core/mailbox/kraming.js +58 -2
  73. package/esm/keri/npm/src/core/missing-anchor-query.js +20 -0
  74. package/esm/keri/npm/src/core/routing.js +18 -25
  75. package/esm/keri/npm/src/core/scheming.js +12 -5
  76. package/esm/keri/npm/src/core/wire-fields.js +126 -0
  77. package/esm/keri/npm/src/db/basing.js +4 -13
  78. package/esm/keri/npm/src/db/core/indexeddb-persistence.js +3 -2
  79. package/esm/keri/npm/src/db/core/webdber.js +85 -27
  80. package/esm/keri/npm/src/db/mailbox/mailboxing.js +13 -0
  81. package/esm/keri/npm/src/db/subing.js +4 -0
  82. package/esm/keri/npm/src/runtime/index.js +11 -5
  83. package/esm/keri/npm/src/time/mod.js +5 -0
  84. package/esm/keri/npm/src/vdr/credential-tsn-record.js +2 -7
  85. package/esm/keri/npm/src/vdr/eventing.js +71 -28
  86. package/esm/keri/npm/src/vdr/registry-tsn-record.js +3 -13
  87. package/esm/keri/npm/src/version.js +2 -2
  88. package/package.json +1 -1
  89. package/types/_dnt.polyfills.d.ts +9 -9
  90. package/types/_dnt.polyfills.d.ts.map +1 -1
  91. package/types/acdc/dhking.d.ts +8 -0
  92. package/types/acdc/dhking.d.ts.map +1 -1
  93. package/types/acdc/observing.d.ts +5 -1
  94. package/types/acdc/observing.d.ts.map +1 -1
  95. package/types/acdc/query-resend.d.ts +24 -0
  96. package/types/acdc/query-resend.d.ts.map +1 -0
  97. package/types/acdc/regengine.d.ts +19 -1
  98. package/types/acdc/regengine.d.ts.map +1 -1
  99. package/types/acdc/regeventing.d.ts.map +1 -1
  100. package/types/acdc/registering.d.ts +6 -0
  101. package/types/acdc/registering.d.ts.map +1 -1
  102. package/types/acdc/salting.d.ts.map +1 -1
  103. package/types/acdc/unblinding.d.ts +13 -1
  104. package/types/acdc/unblinding.d.ts.map +1 -1
  105. package/types/app/bootstrap/authenticating.d.ts +12 -2
  106. package/types/app/bootstrap/authenticating.d.ts.map +1 -1
  107. package/types/app/bootstrap/oobiery.d.ts +144 -7
  108. package/types/app/bootstrap/oobiery.d.ts.map +1 -1
  109. package/types/app/credentials/credential-importing.d.ts +8 -0
  110. package/types/app/credentials/credential-importing.d.ts.map +1 -1
  111. package/types/app/credentials/root-replicator.d.ts +19 -8
  112. package/types/app/credentials/root-replicator.d.ts.map +1 -1
  113. package/types/app/credentials/schema-resolving.d.ts.map +1 -1
  114. package/types/app/credentials/tel-publishing.d.ts +4 -2
  115. package/types/app/credentials/tel-publishing.d.ts.map +1 -1
  116. package/types/app/delivery/forwarding.d.ts +90 -5
  117. package/types/app/delivery/forwarding.d.ts.map +1 -1
  118. package/types/app/delivery/relaying.d.ts +144 -0
  119. package/types/app/delivery/relaying.d.ts.map +1 -0
  120. package/types/app/delivery/respondant.d.ts +9 -2
  121. package/types/app/delivery/respondant.d.ts.map +1 -1
  122. package/types/app/exchanges/exchanging.d.ts +36 -0
  123. package/types/app/exchanges/exchanging.d.ts.map +1 -1
  124. package/types/app/identity/delegating.d.ts +6 -0
  125. package/types/app/identity/delegating.d.ts.map +1 -1
  126. package/types/app/identity/habbing.d.ts +106 -19
  127. package/types/app/identity/habbing.d.ts.map +1 -1
  128. package/types/app/identity/keeping.d.ts +54 -19
  129. package/types/app/identity/keeping.d.ts.map +1 -1
  130. package/types/app/identity/retire-identifier.d.ts +24 -0
  131. package/types/app/identity/retire-identifier.d.ts.map +1 -0
  132. package/types/app/ipex/disclosure-replaying.d.ts +61 -0
  133. package/types/app/ipex/disclosure-replaying.d.ts.map +1 -0
  134. package/types/app/ipex/group-ipex.d.ts +60 -14
  135. package/types/app/ipex/group-ipex.d.ts.map +1 -1
  136. package/types/app/ipex/group-issuance.d.ts +54 -8
  137. package/types/app/ipex/group-issuance.d.ts.map +1 -1
  138. package/types/app/ipex/ipex-discloser.d.ts +39 -2
  139. package/types/app/ipex/ipex-discloser.d.ts.map +1 -1
  140. package/types/app/ipex/ipex-grouping.d.ts +23 -2
  141. package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
  142. package/types/app/ipex/ipex-v2.d.ts +5 -2
  143. package/types/app/ipex/ipex-v2.d.ts.map +1 -1
  144. package/types/app/ipex/issuance.d.ts +46 -16
  145. package/types/app/ipex/issuance.d.ts.map +1 -1
  146. package/types/app/ipex/pending-presentations.d.ts +4 -2
  147. package/types/app/ipex/pending-presentations.d.ts.map +1 -1
  148. package/types/app/ipex/presenting.d.ts.map +1 -1
  149. package/types/app/ipex/receive-issuance.d.ts +2 -1
  150. package/types/app/ipex/receive-issuance.d.ts.map +1 -1
  151. package/types/app/ipex/unblinding-workflow.d.ts +13 -2
  152. package/types/app/ipex/unblinding-workflow.d.ts.map +1 -1
  153. package/types/app/mailbox/agent-inbox.d.ts +126 -0
  154. package/types/app/mailbox/agent-inbox.d.ts.map +1 -0
  155. package/types/app/mailbox/forward-handler.d.ts +114 -14
  156. package/types/app/mailbox/forward-handler.d.ts.map +1 -1
  157. package/types/app/mailbox/kel-publisher.d.ts +12 -22
  158. package/types/app/mailbox/kel-publisher.d.ts.map +1 -1
  159. package/types/app/mailbox/mailbox-poller.d.ts +40 -24
  160. package/types/app/mailbox/mailbox-poller.d.ts.map +1 -1
  161. package/types/app/mailbox/mailboxing.d.ts +19 -5
  162. package/types/app/mailbox/mailboxing.d.ts.map +1 -1
  163. package/types/app/multisig/counseling.d.ts +32 -11
  164. package/types/app/multisig/counseling.d.ts.map +1 -1
  165. package/types/app/multisig/group-members.d.ts +17 -1
  166. package/types/app/multisig/group-members.d.ts.map +1 -1
  167. package/types/app/multisig/grouping.d.ts +17 -1
  168. package/types/app/multisig/grouping.d.ts.map +1 -1
  169. package/types/app/multisig/multisig-workflows.d.ts +0 -8
  170. package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
  171. package/types/app/multisig/proposing.d.ts +4 -19
  172. package/types/app/multisig/proposing.d.ts.map +1 -1
  173. package/types/app/multisig/rejoin-group.d.ts +119 -0
  174. package/types/app/multisig/rejoin-group.d.ts.map +1 -0
  175. package/types/app/multisig/replace-member.d.ts +15 -1
  176. package/types/app/multisig/replace-member.d.ts.map +1 -1
  177. package/types/app/protocol/parsering.d.ts +21 -2
  178. package/types/app/protocol/parsering.d.ts.map +1 -1
  179. package/types/app/protocol/protocol-processing.d.ts +25 -5
  180. package/types/app/protocol/protocol-processing.d.ts.map +1 -1
  181. package/types/app/queries/query-replies.d.ts +4 -8
  182. package/types/app/queries/query-replies.d.ts.map +1 -1
  183. package/types/app/queries/relay-refresh.d.ts +26 -0
  184. package/types/app/queries/relay-refresh.d.ts.map +1 -0
  185. package/types/app/queries/witness-inquisitor.d.ts +56 -5
  186. package/types/app/queries/witness-inquisitor.d.ts.map +1 -1
  187. package/types/app/runtime/agent-runtime.d.ts +34 -3
  188. package/types/app/runtime/agent-runtime.d.ts.map +1 -1
  189. package/types/app/runtime/cue-runtime.d.ts +15 -3
  190. package/types/app/runtime/cue-runtime.d.ts.map +1 -1
  191. package/types/app/runtime/ipex-auxiliaries.d.ts.map +1 -1
  192. package/types/app/runtime/operation-owners.d.ts +16 -26
  193. package/types/app/runtime/operation-owners.d.ts.map +1 -1
  194. package/types/app/runtime/workflow-contract.d.ts +21 -6
  195. package/types/app/runtime/workflow-contract.d.ts.map +1 -1
  196. package/types/app/transport/http-client.d.ts +9 -0
  197. package/types/app/transport/http-client.d.ts.map +1 -1
  198. package/types/app/transport/message-source.d.ts +6 -3
  199. package/types/app/transport/message-source.d.ts.map +1 -1
  200. package/types/app/transport/messengering.d.ts +10 -1
  201. package/types/app/transport/messengering.d.ts.map +1 -1
  202. package/types/app/witness/ingress.d.ts +1 -0
  203. package/types/app/witness/ingress.d.ts.map +1 -1
  204. package/types/app/witness/receipt-client.d.ts +19 -1
  205. package/types/app/witness/receipt-client.d.ts.map +1 -1
  206. package/types/app/witness/receipting.d.ts +24 -1
  207. package/types/app/witness/receipting.d.ts.map +1 -1
  208. package/types/cli/messaging/multisig.d.ts.map +1 -1
  209. package/types/core/cues.d.ts +53 -1
  210. package/types/core/cues.d.ts.map +1 -1
  211. package/types/core/errors.d.ts +32 -0
  212. package/types/core/errors.d.ts.map +1 -1
  213. package/types/core/kel/delegation-ancestry.d.ts.map +1 -1
  214. package/types/core/kel/eventing.d.ts.map +1 -1
  215. package/types/core/kel/kever-decisions.d.ts +3 -1
  216. package/types/core/kel/kever-decisions.d.ts.map +1 -1
  217. package/types/core/kel/kever.d.ts +7 -1
  218. package/types/core/kel/kever.d.ts.map +1 -1
  219. package/types/core/mailbox/kram-policy.d.ts +12 -0
  220. package/types/core/mailbox/kram-policy.d.ts.map +1 -1
  221. package/types/core/mailbox/kram-pruning.d.ts +5 -1
  222. package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
  223. package/types/core/mailbox/kram-time.d.ts +26 -2
  224. package/types/core/mailbox/kram-time.d.ts.map +1 -1
  225. package/types/core/mailbox/kraming.d.ts +14 -1
  226. package/types/core/mailbox/kraming.d.ts.map +1 -1
  227. package/types/core/missing-anchor-query.d.ts +34 -0
  228. package/types/core/missing-anchor-query.d.ts.map +1 -0
  229. package/types/core/routing.d.ts +3 -7
  230. package/types/core/routing.d.ts.map +1 -1
  231. package/types/core/scheming.d.ts.map +1 -1
  232. package/types/core/wire-fields.d.ts +56 -0
  233. package/types/core/wire-fields.d.ts.map +1 -0
  234. package/types/db/basing.d.ts.map +1 -1
  235. package/types/db/core/indexeddb-persistence.d.ts +3 -2
  236. package/types/db/core/indexeddb-persistence.d.ts.map +1 -1
  237. package/types/db/core/webdber.d.ts +32 -6
  238. package/types/db/core/webdber.d.ts.map +1 -1
  239. package/types/db/exchange/exchange-records.d.ts +4 -0
  240. package/types/db/exchange/exchange-records.d.ts.map +1 -1
  241. package/types/db/mailbox/mailboxing.d.ts +10 -1
  242. package/types/db/mailbox/mailboxing.d.ts.map +1 -1
  243. package/types/db/subing.d.ts +2 -0
  244. package/types/db/subing.d.ts.map +1 -1
  245. package/types/runtime/index.d.ts +20 -14
  246. package/types/runtime/index.d.ts.map +1 -1
  247. package/types/time/mod.d.ts +2 -0
  248. package/types/time/mod.d.ts.map +1 -1
  249. package/types/vdr/credential-tsn-record.d.ts.map +1 -1
  250. package/types/vdr/eventing.d.ts +32 -1
  251. package/types/vdr/eventing.d.ts.map +1 -1
  252. package/types/vdr/registry-tsn-record.d.ts.map +1 -1
  253. package/types/version.d.ts +2 -2
  254. package/esm/keri/npm/src/app/runtime/signer-conditions.js +0 -51
  255. package/types/app/runtime/signer-conditions.d.ts +0 -32
  256. package/types/app/runtime/signer-conditions.d.ts.map +0 -1
@@ -1,23 +1,56 @@
1
- /** Authenticated /fwd intake: validate provider authority before storing reconstructed child bytes. */
2
- import { collectPayload, concatBytes, Counter, Diger, nestedPayload, parsePather, SerderACDC, SerderKERI, Vrsn_2_0, } from "cesr-ts";
3
- import { Roles } from "../../core/roles.js";
1
+ /** Authenticated /fwd intake: deliver locally or re-forward for senders this host serves, else store for recipients. */
2
+ import { collectPayload, concatBytes, Counter, Diger, nestedPayload, parseBytes, parsePather, ParserError, SerderACDC, SerderKERI, Vrsn_2_0, } from "cesr-ts";
3
+ import { call } from "effection";
4
+ import { readPrefixer } from "../../core/wire-fields.js";
5
+ import { storableTopic } from "../../db/mailbox/mailboxing.js";
6
+ import { isAcceptedGroupMember } from "../multisig/group-members.js";
4
7
  import { abortable } from "../runtime/abortable.js";
8
+ import { authorizedStoringHost, keepsForPickup, ownTraffic } from "./agent-inbox.js";
9
+ import { mailboxTopicKey } from "./mailboxing.js";
10
+ import { transportMailboxTopic } from "./topic-routing.js";
5
11
  /**
6
- * Accepted `/fwd` route handler that stores embedded payloads in mailbox topics.
12
+ * Accepted `/fwd` route handler that stores embedded payloads in mailbox topics and, on a relaying host, delivers
13
+ * a served sender's payloads onward.
7
14
  *
8
15
  * This is the `keri-ts` mailbox-storage analogue to KERIpy's `ForwardHandler`.
9
16
  *
10
- * Authorization rule:
11
- * - the request-scoped mailbox AID passed with this message must currently be
12
- * authorized for the addressed recipient
17
+ * Paths, in order; exactly one runs for one `/fwd`:
18
+ * - ingest: the recipient is a habitat of this Habery and either this host
19
+ * keeps the recipient's mail for pickup (`keepsForPickup`: a local group that
20
+ * authorized it as mailbox or agent), whoever the sender is and whether or
21
+ * not the host relays, or the host relays and the `/fwd` sender is served.
22
+ * The child goes through this runtime's own byte ingress as remote input
23
+ * addressed to that habitat's endpoint, so
24
+ * signature, KRAM and escrow rules apply as for any received message. This is
25
+ * how an edge's group co-member hosted on the agent receives every group
26
+ * message. When the host keeps mail for pickup and the child is not
27
+ * `ownTraffic` (its originator is a local habitat, an agent principal of the
28
+ * host, or a member of the group, i.e. the edge that would pick it up), it is
29
+ * also stored once in the group's mailbox topic for its remote members: one
30
+ * ingest, one stored copy. A third party's `/fwd` to the group is ingested and
31
+ * stored; the edge's own is ingested only. This ingest is the only local
32
+ * delivery of a pickup group's mail: the host's `MailboxPoller` never polls
33
+ * its own endpoint for that group, so the stored copy is for remote members.
34
+ * - store: the request-scoped mailbox AID passed with this message must
35
+ * currently be authorized for the addressed recipient (witness, mailbox or
36
+ * agent). A recipient this host stores for is never also relayed.
37
+ * - relay (relaying only): the `/fwd` sender is served and the recipient is
38
+ * remote. The host re-sends the child with its own Poster, as KERIA's agent
39
+ * re-sends a Signify client's exn.
40
+ *
41
+ * A served sender authorized this host as its `mailbox` or `agent`, directly or
42
+ * through a group it is an accepted member of. Witness membership never makes a
43
+ * sender served.
13
44
  */
14
45
  export class ForwardHandler {
15
46
  /**
16
- * Bind mailbox publication without acquiring a store.
47
+ * Bind mailbox publication, local ingress and optional relaying without acquiring a store.
17
48
  *
18
49
  * @param mailboxDirector Borrowed provider owner that publishes accepted forwarded payloads.
50
+ * @param reactor Borrowed ingress for a local recipient's child; null only outside a runtime.
51
+ * @param relay Borrowed Poster of a relaying host; null keeps the host from relaying or serving senders.
19
52
  */
20
- constructor(mailboxDirector) {
53
+ constructor(mailboxDirector, reactor, relay) {
21
54
  /** Instance route identity used by exchange dispatch. */
22
55
  Object.defineProperty(this, "resource", {
23
56
  enumerable: true,
@@ -39,21 +72,40 @@ export class ForwardHandler {
39
72
  writable: true,
40
73
  value: void 0
41
74
  });
75
+ /**
76
+ * Borrowed byte ingress of this host's runtime, through which a local recipient receives the child; null (a
77
+ * standalone Exchanger without a runtime) never ingests and only stores.
78
+ */
79
+ Object.defineProperty(this, "reactor", {
80
+ enumerable: true,
81
+ configurable: true,
82
+ writable: true,
83
+ value: void 0
84
+ });
85
+ /** Borrowed Poster that re-sends a served sender's child to a remote recipient; null means this host never relays. */
86
+ Object.defineProperty(this, "relay", {
87
+ enumerable: true,
88
+ configurable: true,
89
+ writable: true,
90
+ value: void 0
91
+ });
42
92
  this.mailboxDirector = mailboxDirector;
93
+ this.reactor = reactor;
94
+ this.relay = relay;
43
95
  }
44
96
  /**
45
- * Verify that the embedded exchange has the mailbox modifiers and one
46
- * extractable forwarded payload.
97
+ * Verify that the exchange names a {@link ForwardAddress} and carries one forwarded message: a legacy embed that
98
+ * rebuilds into exactly one complete message ({@link legacyForwardedMessage}), or one SAID-bound v2 child. Any
99
+ * other shape is refused here, so the Exchanger rejects the `/fwd` and nothing is stored, relayed or ingested.
47
100
  *
48
101
  * @param args Signed forwarding exchange, attachment evidence and optional nested frames; children retain their own authentication requirements.
49
- * @returns Whether required modifiers and one bound forwarded payload are structurally valid.
102
+ * @returns Whether the address and one bound forwarded message are structurally valid.
50
103
  */
51
104
  verify(args) {
52
- const modifiers = args.serder.ked?.q;
53
- if (typeof modifiers?.pre !== "string" || typeof modifiers?.topic !== "string")
105
+ if (!forwardAddress(args.serder))
54
106
  return false;
55
107
  if (args.serder.pvrsn.major < 2) {
56
- return !args.nests?.length && extractForwardedMessage(args.serder, args.attachments) !== null;
108
+ return !args.nests?.length && legacyForwardedMessage(args.serder, args.attachments) !== null;
57
109
  }
58
110
  if (args.nests?.length !== 1)
59
111
  return false;
@@ -69,10 +121,9 @@ export class ForwardHandler {
69
121
  }
70
122
  }
71
123
  /**
72
- * Store one forwarded payload when the receiving host is allowed to act as
73
- * the recipient's async correspondence store.
124
+ * Take the one {@link ForwardPath} this `/fwd` qualifies for, or drop it.
74
125
  *
75
- * Accepted host shapes:
126
+ * Accepted store host shapes:
76
127
  * - explicit mailbox provider authorized in `ends.`
77
128
  * - recipient witness host from the accepted KEL witness set
78
129
  * - recipient agent host authorized in `ends.`
@@ -80,31 +131,112 @@ export class ForwardHandler {
80
131
  * Controller endpoints stay excluded here because they are direct
81
132
  * correspondence destinations, not store-and-forward hosts.
82
133
  *
134
+ * A relayed child is admitted to the Poster with this host as source and the
135
+ * `/fwd` topic unchanged; the Poster's own `transportMailboxTopic` is
136
+ * idempotent on that already-bare topic. Admission is the end of this
137
+ * handler's duty: a failed onward attempt is the Poster's logged failed
138
+ * outcome, with no outbox and no acknowledgement back to the sender.
139
+ *
140
+ * An ingested child is dispatched inside this handler's operation, after the
141
+ * Exchanger has committed the `/fwd`; it is one more input to the shared
142
+ * protocol owners, which hold no lock or input queue. A child the recipient
143
+ * cannot process yet escrows as any received message does.
144
+ *
83
145
  * @param args Accepted exchange with borrowed attachments/children and receiving mailboxAid provenance.
84
- * @returns An operation for v2 child serialization, or synchronous completion/no-op for legacy or unauthorized input.
146
+ * @returns An operation for v2 child serialization or local ingest, or synchronous completion/no-op otherwise.
85
147
  */
86
148
  handle(args) {
87
- const modifiers = args.serder.ked?.q;
88
- const recipient = typeof modifiers?.pre === "string" ? modifiers.pre : null;
89
- const topic = typeof modifiers?.topic === "string" ? modifiers.topic : null;
90
- const child = args.serder.pvrsn.major >= 2 ? args.nests?.[0] : undefined;
91
- const forwarded = child ? null : extractForwardedMessage(args.serder, args.attachments);
149
+ const address = forwardAddress(args.serder);
92
150
  const mailboxAid = args.mailboxAid;
93
- if (!recipient || !topic || (!child && !forwarded)) {
151
+ if (!address)
94
152
  return;
153
+ if (args.serder.pvrsn.major < 2) {
154
+ const message = legacyForwardedMessage(args.serder, args.attachments);
155
+ if (!message)
156
+ return;
157
+ const path = this.forwardPath(forwardSource(args.serder, message.frame.body), address.recipient, mailboxAid);
158
+ return path ? this.deliver(path, address, message.wire) : undefined;
95
159
  }
96
- if (!this.canStoreRecipient(recipient, mailboxAid))
160
+ const child = args.nests?.[0];
161
+ if (!child)
97
162
  return;
98
- if (child) {
99
- // Mailbox LMDB accepts a finite row; collect one child, never the whole exchange stream.
100
- return abortable(async (signal) => {
101
- const wire = await collectPayload(nestedPayload(child, Vrsn_2_0), signal);
102
- signal.throwIfAborted();
103
- if (this.canStoreRecipient(recipient, mailboxAid))
163
+ const source = forwardSource(args.serder, child.body);
164
+ if (!this.forwardPath(source, address.recipient, mailboxAid))
165
+ return;
166
+ // deno-lint-ignore no-this-alias -- The operation owns this one child's delivery.
167
+ const self = this;
168
+ return call(function* () {
169
+ const wire = yield* collectNestedMessage(child);
170
+ if (!wire)
171
+ return;
172
+ // Re-read accepted authority in the same synchronous turn as delivery.
173
+ const current = self.forwardPath(source, address.recipient, mailboxAid);
174
+ if (current)
175
+ yield* call(() => self.deliver(current, address, wire));
176
+ });
177
+ }
178
+ /**
179
+ * Decide the path from current accepted state; see the class rules for their order.
180
+ *
181
+ * @param source Authenticated `/fwd` signer and the forwarded message's own originator.
182
+ * @param recipient Final recipient AID named by the `/fwd` modifiers.
183
+ * @param mailboxAid Receiving hosted endpoint AID, or null when the request named none.
184
+ * @returns The one path to take, or null to drop the `/fwd`.
185
+ */
186
+ forwardPath(source, recipient, mailboxAid) {
187
+ const hby = this.mailboxDirector.hby;
188
+ if (this.reactor && hby.habs.has(recipient)) {
189
+ const pickup = this.pickupHost(recipient, mailboxAid);
190
+ if (pickup)
191
+ return { kind: "ingest", store: !ownTraffic(hby, source.origin, recipient, pickup) };
192
+ if (this.relay && servingHost(hby, source, mailboxAid))
193
+ return { kind: "ingest", store: false };
194
+ }
195
+ if (this.canStoreRecipient(recipient, mailboxAid))
196
+ return { kind: "store" };
197
+ // Nothing addressed to this Habery leaves through its own Poster; it would only loop back here.
198
+ if (!this.relay || hby.db.prefixes.has(recipient))
199
+ return null;
200
+ const host = servingHost(hby, source, mailboxAid);
201
+ return host ? { kind: "relay", host } : null;
202
+ }
203
+ /**
204
+ * Select the local host that keeps `recipient`'s mail for pickup, or null; any local habitat without
205
+ * request-scoped provenance, as {@link servingHost} does.
206
+ *
207
+ * @param recipient Final recipient AID named by the `/fwd` modifiers.
208
+ * @param mailboxAid Receiving hosted endpoint AID, or null when the request named none.
209
+ * @returns The local AID that keeps the recipient's mail for pickup, or null.
210
+ */
211
+ pickupHost(recipient, mailboxAid) {
212
+ const hby = this.mailboxDirector.hby;
213
+ const hosts = mailboxAid ? [mailboxAid] : [...hby.db.prefixes];
214
+ return hosts.find((host) => hby.habs.has(host) && keepsForPickup(hby, recipient, host)) ?? null;
215
+ }
216
+ /**
217
+ * Take one decided path for complete child wire.
218
+ *
219
+ * @param path Path decided in this turn.
220
+ * @param address Final recipient AID and `/fwd` mailbox topic.
221
+ * @param wire Exactly one complete child message, signed by its originator.
222
+ * @returns The ingest operation for a local recipient; storage (including an ingested child's pickup copy, written
223
+ * before ingest in the turn its authority was read) and Poster admission complete synchronously.
224
+ */
225
+ deliver(path, address, wire) {
226
+ const { recipient, topic } = address;
227
+ switch (path.kind) {
228
+ case "store":
229
+ this.mailboxDirector.publish(recipient, topic, wire);
230
+ return;
231
+ case "relay":
232
+ this.relay.send({ src: path.host, dest: recipient, topic, msg: wire });
233
+ return;
234
+ case "ingest":
235
+ if (path.store)
104
236
  this.mailboxDirector.publish(recipient, topic, wire);
105
- });
237
+ // Remote input at the recipient's own endpoint, never `local`: it must earn acceptance like any arrival.
238
+ return this.reactor.processBytes(wire, { mailboxAid: recipient });
106
239
  }
107
- this.mailboxDirector.publish(recipient, topic, forwarded);
108
240
  }
109
241
  /** Re-read accepted authority in the same synchronous turn as provider publication. */
110
242
  canStoreRecipient(recipient, mailboxAid) {
@@ -140,13 +272,115 @@ function hostCanStoreForwardRecipient(hby, recipient, recipientKever, hostAid) {
140
272
  if (recipientKever.wits.includes(hostAid)) {
141
273
  return true;
142
274
  }
143
- for (const role of [Roles.mailbox, Roles.agent]) {
144
- const end = hby.db.ends.get([recipient, role, hostAid]);
145
- if (end?.allowed || end?.enabled) {
146
- return true;
147
- }
275
+ return authorizedStoringHost(hby, recipient, hostAid);
276
+ }
277
+ /**
278
+ * Select the local host that serves this source, or null. This is the one served-sender rule of a relaying host:
279
+ * `/fwd` intake relays only for it and the `/oobis` handler resolves only for it.
280
+ *
281
+ * Without request-scoped provenance any local habitat the source authorized serves it, as the store path
282
+ * accepts any local store host.
283
+ *
284
+ * @param hby Borrowed local habitat collection and accepted-state database.
285
+ * @param source Authenticated signer and, for a `/fwd`, the forwarded message's own originator.
286
+ * @param mailboxAid Receiving hosted endpoint AID, or null when the request named none.
287
+ * @returns The local AID the source authorized, or null.
288
+ */
289
+ export function servingHost(hby, source, mailboxAid) {
290
+ const hosts = mailboxAid ? [mailboxAid] : [...hby.db.prefixes];
291
+ return hosts.find((host) => hby.habs.has(host) && servesSource(hby, source, host)) ?? null;
292
+ }
293
+ /**
294
+ * Whether `hostAid` relays for this source: the sender authorized the host, or the forwarded message originates
295
+ * from a group the sender is an accepted member of and that group authorized the host. Witness membership of
296
+ * either is not consulted. Rows read: `ends.[sender, mailbox|agent, hostAid]`, then, only when the sender is an
297
+ * accepted member of `origin`, `ends.[origin, mailbox|agent, hostAid]`.
298
+ *
299
+ * @param hby Borrowed local habitat collection and accepted-state database.
300
+ * @param source Authenticated `/fwd` signer and forwarded originator.
301
+ * @param hostAid Local endpoint AID that would relay.
302
+ * @returns True when accepted end-role state makes the sender a served sender of this host.
303
+ */
304
+ function servesSource(hby, source, hostAid) {
305
+ if (!source.sender)
306
+ return false;
307
+ if (authorizedStoringHost(hby, source.sender, hostAid))
308
+ return true;
309
+ return !!source.origin && source.origin !== source.sender
310
+ && isAcceptedGroupMember(hby.db, source.origin, source.sender)
311
+ && authorizedStoringHost(hby, source.origin, hostAid);
312
+ }
313
+ /**
314
+ * Read the `/fwd` address, or null when this host could not store or relay under it.
315
+ *
316
+ * The recipient must parse as one identifier prefix, since it becomes a Poster destination and a mailbox key. The
317
+ * topic must be nonempty in bare form (a forwarded delivery requires one, and the Poster refuses an empty topic as a
318
+ * programmer error) and storable as a mailbox key under that recipient, so a stored, ingested or relayed child never
319
+ * reaches the mailbox store with a key it would refuse as a fault.
320
+ *
321
+ * @param serder Forwarding exchange.
322
+ * @returns The usable address, or null.
323
+ */
324
+ function forwardAddress(serder) {
325
+ const modifiers = serder.ked?.q;
326
+ const recipient = modifiers?.pre, topic = modifiers?.topic;
327
+ if (typeof recipient !== "string" || typeof topic !== "string")
328
+ return null;
329
+ // The whole string must be the prefix: a shorter qb64 followed by trailing text is not one.
330
+ if (readPrefixer(recipient)?.qb64 !== recipient || transportMailboxTopic(topic).length === 0)
331
+ return null;
332
+ return storableTopic(mailboxTopicKey(recipient, topic)) ? { recipient, topic } : null;
333
+ }
334
+ /**
335
+ * The `/fwd` signer and the forwarded message's own originator: a KERI message's `i`, an ACDC's issuer.
336
+ *
337
+ * @param serder Authenticated forwarding exchange.
338
+ * @param body Body of the one forwarded message.
339
+ * @returns Who the request speaks for.
340
+ */
341
+ function forwardSource(serder, body) {
342
+ const origin = body instanceof SerderKERI ? body.pre : body instanceof SerderACDC ? body.issuer : null;
343
+ return { sender: serder.pre, origin };
344
+ }
345
+ /**
346
+ * The one frame `wire` parses as, or null when it is not exactly one complete CESR message with its attachments.
347
+ *
348
+ * `ParserError` is the decoder's refusal of the bytes; nothing else here reads a store or does I/O, so any other
349
+ * error is a fault and propagates.
350
+ *
351
+ * @param wire Candidate child wire.
352
+ * @returns The single parsed frame, or null.
353
+ */
354
+ function oneCompleteMessage(wire) {
355
+ try {
356
+ const frames = parseBytes(wire);
357
+ return frames.length === 1 ? frames[0] : null;
358
+ }
359
+ catch (error) {
360
+ if (error instanceof ParserError)
361
+ return null;
362
+ throw error;
148
363
  }
149
- return false;
364
+ }
365
+ /**
366
+ * Collect a v2 child's own wire, or null when it does not re-enclose as exactly one complete message.
367
+ *
368
+ * @param child Bound nested child, borrowed for this operation.
369
+ * @returns The child's complete wire, or null.
370
+ */
371
+ function* collectNestedMessage(child) {
372
+ let payload;
373
+ try {
374
+ payload = nestedPayload(child, Vrsn_2_0);
375
+ }
376
+ catch (error) {
377
+ if (error instanceof ParserError)
378
+ return null;
379
+ throw error;
380
+ }
381
+ // Mailbox LMDB and Poster take one finite message; collect one child, never the whole exchange stream.
382
+ const wire = yield* abortable((signal) => collectPayload(payload, signal));
383
+ return oneCompleteMessage(wire) ? wire : null;
150
384
  }
151
385
  /**
152
386
  * Check recipient-specific store-forward authority without treating a controller endpoint as a mailbox.
@@ -167,29 +401,41 @@ function hasLocalStoreForwardHost(hby, recipient, recipientKever) {
167
401
  return false;
168
402
  }
169
403
  /**
170
- * Reconstruct legacy forwarded wire without assigning outer attachments to the child.
404
+ * Rebuild the legacy embed into its one message, or null when it is not exactly one complete message.
405
+ *
406
+ * The body is serialized from `e.evt`, followed by only the attachment material pathed to `/e/evt`; other pathed
407
+ * groups belong to the outer `/fwd`. The result must parse as exactly one complete message with its attachments, so
408
+ * an embed that is not a message, or whose pathed attachments are not that message's complete attachments, is
409
+ * refused here and never reaches the mailbox store, this runtime's ingress or the Poster.
171
410
  *
172
411
  * @param serder Legacy forwarding exchange containing an e.evt body.
173
412
  * @param attachments Pathed attachments; only /e/evt material belongs to the embedded message.
174
- * @returns Reconstructed child wire, or null without an embedded event.
413
+ * @returns The forwarded message, or null.
175
414
  */
176
- function extractForwardedMessage(serder, attachments) {
415
+ function legacyForwardedMessage(serder, attachments) {
177
416
  const embeds = serder.ked?.e;
178
417
  const evt = embeds?.evt;
179
418
  if (!evt || typeof evt !== "object" || Array.isArray(evt)) {
180
419
  return null;
181
420
  }
182
- // Rebuild the embedded event from SAD plus only the attachment material
183
- // pathed to `/e/evt`; other pathed groups belong to the outer `/fwd` message.
184
- const embedded = embeddedSerderRaw(evt);
185
- const messageParts = [embedded];
186
- for (const attachment of attachments) {
187
- const atc = forwardedAttachmentForPath(attachment.raw, "/e/evt");
188
- if (atc) {
189
- messageParts.push(atc);
421
+ const parts = [];
422
+ try {
423
+ parts.push(embeddedSerderRaw(evt));
424
+ for (const attachment of attachments) {
425
+ const atc = forwardedAttachmentForPath(attachment.raw, "/e/evt");
426
+ if (atc)
427
+ parts.push(atc);
190
428
  }
191
429
  }
192
- return concatBytes(...messageParts);
430
+ catch (error) {
431
+ // The embed's SAD and the pathed groups are remote input; the codec refuses what it cannot serialize or read.
432
+ if (error instanceof ParserError)
433
+ return null;
434
+ throw error;
435
+ }
436
+ const wire = concatBytes(...parts);
437
+ const frame = oneCompleteMessage(wire);
438
+ return frame ? { wire, frame } : null;
193
439
  }
194
440
  /**
195
441
  * Serialize one legacy embedded body according to its declared protocol.
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _KelPublisher_instances, _KelPublisher_deps, _KelPublisher_budgets, _KelPublisher_inflight, _KelPublisher_dirty, _KelPublisher_owed, _KelPublisher_statusOf, _KelPublisher_budget, _KelPublisher_attempt, _KelPublisher_derive, _KelPublisher_deriveFor, _KelPublisher_prune;
12
+ var _KelPublisher_instances, _KelPublisher_deps, _KelPublisher_budgets, _KelPublisher_inflight, _KelPublisher_dirty, _KelPublisher_owed, _KelPublisher_repair, _KelPublisher_statusOf, _KelPublisher_budget, _KelPublisher_attempt, _KelPublisher_derive, _KelPublisher_deriveFor, _KelPublisher_prune;
13
13
  import { Deck } from "../../core/deck.js";
14
14
  import { dgKey } from "../../db/core/keys.js";
15
15
  import { doEvery } from "../runtime/doing.js";
@@ -50,12 +50,12 @@ export class KelPublisher {
50
50
  writable: true,
51
51
  value: new Deck()
52
52
  });
53
- /** A failure that escapes a pass is counted and kept here; the fiber keeps running. */
54
- Object.defineProperty(this, "health", {
53
+ /** The mailbox poller pushes what each poll said here; the next tock re-arms or repairs that entry. */
54
+ Object.defineProperty(this, "polls", {
55
55
  enumerable: true,
56
56
  configurable: true,
57
57
  writable: true,
58
- value: { faults: 0, last: null }
58
+ value: new Deck()
59
59
  });
60
60
  _KelPublisher_deps.set(this, void 0);
61
61
  _KelPublisher_budgets.set(this, new Map());
@@ -68,7 +68,7 @@ export class KelPublisher {
68
68
  }
69
69
  /**
70
70
  * Give `pre`'s entries a fresh budget and derive them on the next tock; with `mailbox`, re-arm only that mailbox's
71
- * entry, and only if it timed out (the poller calls this after a successful poll).
71
+ * entry, and only if it timed out (what a `polled` record on {@link KelPublisher.polls} does).
72
72
  */
73
73
  prompt(pre, mailbox) {
74
74
  if (mailbox !== undefined) {
@@ -84,19 +84,6 @@ export class KelPublisher {
84
84
  }
85
85
  __classPrivateFieldGet(this, _KelPublisher_dirty, "f").add(pre);
86
86
  }
87
- /**
88
- * A mailbox refused the owner's poll with 403: whatever the record says it holds, it cannot authenticate
89
- * the owner (it lost its state, or accepted a post it then escrowed). Forget what it was given, so the next
90
- * pass posts the KEL again, and give the entry a fresh budget. The poller calls this at most once per backoff
91
- * period, which is also the most this posts; a mailbox that never recovers is given up on like any other.
92
- */
93
- repair(pre, mailbox) {
94
- const { hby } = __classPrivateFieldGet(this, _KelPublisher_deps, "f"), record = hby.db.kpub.get([pre, mailbox]);
95
- if (!hby.readonly && record?.d)
96
- hby.db.kpub.pin([pre, mailbox], { d: null, dt: record.dt });
97
- __classPrivateFieldGet(this, _KelPublisher_budgets, "f").delete(idOf(pre, mailbox));
98
- __classPrivateFieldGet(this, _KelPublisher_dirty, "f").add(pre);
99
- }
100
87
  /**
101
88
  * The full check: forget records of mailboxes no longer authorized, and mark every identifier for derivation.
102
89
  * A walk of all identifiers, so a host runs it at open and every many tocks.
@@ -111,7 +98,7 @@ export class KelPublisher {
111
98
  __classPrivateFieldGet(this, _KelPublisher_dirty, "f").add(hab.pre);
112
99
  }
113
100
  /**
114
- * The fixed-tock pass: drain the cues, derive the marked identifiers and those still owed, then send up to
101
+ * The fixed-tock pass: drain the decks, derive the marked identifiers and those still owed, then send up to
115
102
  * {@link KelSendsPerPass} due posts, each within `timeoutMs` for the mailbox's answer. An idle pass reads no
116
103
  * store. A post is recorded when the mailbox answers 2xx; a failure is retried on the schedule until the budget
117
104
  * is used up. Never throws on a remote failure; every attempt is returned.
@@ -120,6 +107,12 @@ export class KelPublisher {
120
107
  const { clock, hby } = __classPrivateFieldGet(this, _KelPublisher_deps, "f");
121
108
  for (let cue = this.rotated.pull(); cue; cue = this.rotated.pull())
122
109
  this.prompt(cue.pre);
110
+ for (let cue = this.polls.pull(); cue; cue = this.polls.pull()) {
111
+ if (cue.kin === "polled")
112
+ this.prompt(cue.pre, cue.mailbox);
113
+ else
114
+ __classPrivateFieldGet(this, _KelPublisher_instances, "m", _KelPublisher_repair).call(this, cue.pre, cue.mailbox);
115
+ }
123
116
  if (hby.readonly)
124
117
  return [];
125
118
  const owed = [];
@@ -186,7 +179,13 @@ export class KelPublisher {
186
179
  return done ? { outcome: "settled", status } : { outcome: "timed-out", status, timeoutMs };
187
180
  }
188
181
  }
189
- _KelPublisher_deps = new WeakMap(), _KelPublisher_budgets = new WeakMap(), _KelPublisher_inflight = new WeakMap(), _KelPublisher_dirty = new WeakMap(), _KelPublisher_owed = new WeakMap(), _KelPublisher_instances = new WeakSet(), _KelPublisher_statusOf = function _KelPublisher_statusOf(entry) {
182
+ _KelPublisher_deps = new WeakMap(), _KelPublisher_budgets = new WeakMap(), _KelPublisher_inflight = new WeakMap(), _KelPublisher_dirty = new WeakMap(), _KelPublisher_owed = new WeakMap(), _KelPublisher_instances = new WeakSet(), _KelPublisher_repair = function _KelPublisher_repair(pre, mailbox) {
183
+ const { hby } = __classPrivateFieldGet(this, _KelPublisher_deps, "f"), record = hby.db.kpub.get([pre, mailbox]);
184
+ if (!hby.readonly && record?.d)
185
+ hby.db.kpub.pin([pre, mailbox], { d: null, dt: record.dt });
186
+ __classPrivateFieldGet(this, _KelPublisher_budgets, "f").delete(idOf(pre, mailbox));
187
+ __classPrivateFieldGet(this, _KelPublisher_dirty, "f").add(pre);
188
+ }, _KelPublisher_statusOf = function _KelPublisher_statusOf(entry) {
190
189
  const base = { pre: entry.pre, mailbox: entry.mailbox, said: entry.said };
191
190
  if (entry.published)
192
191
  return { ...base, state: "published", attempts: 0 };
@@ -304,19 +303,15 @@ _KelPublisher_deps = new WeakMap(), _KelPublisher_budgets = new WeakMap(), _KelP
304
303
  /**
305
304
  * Run the publisher on its own fiber until halted, as a fixed-tock doer: a sweep on tock 0 and every
306
305
  * `pacing.sweepTocks`, a pass on every tock, then a wait of one tock. A mailbox that hangs holds up only this
307
- * fiber, never the operation owners. A failure that escapes a pass is counted in `publisher.health` and the
308
- * loop keeps running.
306
+ * fiber, never the operation owners. Nothing is caught: every outcome of a post (an HTTP error status, a transport
307
+ * failure, no answer in time) is a `failed` publication that the pass records and retries, so what escapes a pass is a
308
+ * real fault (a store that cannot be read or written, a local group whose member is missing) and it ends the loop and
309
+ * `runAgentRuntime`. Halting the loop returns from the pass and is not a fault.
309
310
  */
310
311
  export function* kelPublisherDo(publisher, clock, pacing = KEL_PUBLISHER_PACING) {
311
312
  return yield* doEvery(clock, pacing.tockMs, function* (tock) {
312
- try {
313
- if (tock % pacing.sweepTocks === 0)
314
- publisher.sweep();
315
- yield* publisher.processDue();
316
- }
317
- catch (error) {
318
- publisher.health.faults++;
319
- publisher.health.last = { error, at: clock.now() };
320
- }
313
+ if (tock % pacing.sweepTocks === 0)
314
+ publisher.sweep();
315
+ yield* publisher.processDue();
321
316
  });
322
317
  }