@optimystic/db-core 0.14.0 → 0.16.2

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 (301) hide show
  1. package/dist/src/blocks/block-store.d.ts +18 -1
  2. package/dist/src/blocks/block-store.d.ts.map +1 -1
  3. package/dist/src/blocks/helpers.d.ts +2 -2
  4. package/dist/src/blocks/helpers.d.ts.map +1 -1
  5. package/dist/src/blocks/helpers.js +2 -2
  6. package/dist/src/blocks/helpers.js.map +1 -1
  7. package/dist/src/btree/btree.d.ts +27 -6
  8. package/dist/src/btree/btree.d.ts.map +1 -1
  9. package/dist/src/btree/btree.js +104 -61
  10. package/dist/src/btree/btree.js.map +1 -1
  11. package/dist/src/chain/chain.d.ts.map +1 -1
  12. package/dist/src/chain/chain.js +11 -1
  13. package/dist/src/chain/chain.js.map +1 -1
  14. package/dist/src/cluster/index.d.ts +1 -0
  15. package/dist/src/cluster/index.d.ts.map +1 -1
  16. package/dist/src/cluster/index.js +1 -0
  17. package/dist/src/cluster/index.js.map +1 -1
  18. package/dist/src/cluster/membership.d.ts +49 -0
  19. package/dist/src/cluster/membership.d.ts.map +1 -0
  20. package/dist/src/cluster/membership.js +75 -0
  21. package/dist/src/cluster/membership.js.map +1 -0
  22. package/dist/src/cluster/structs.d.ts +50 -1
  23. package/dist/src/cluster/structs.d.ts.map +1 -1
  24. package/dist/src/cluster/structs.js +9 -1
  25. package/dist/src/cluster/structs.js.map +1 -1
  26. package/dist/src/cohort-topic/addressing.d.ts +8 -2
  27. package/dist/src/cohort-topic/addressing.d.ts.map +1 -1
  28. package/dist/src/cohort-topic/addressing.js +11 -3
  29. package/dist/src/cohort-topic/addressing.js.map +1 -1
  30. package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts +13 -7
  31. package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts.map +1 -1
  32. package/dist/src/cohort-topic/antidos/bootstrap-evidence.js +17 -6
  33. package/dist/src/cohort-topic/antidos/bootstrap-evidence.js.map +1 -1
  34. package/dist/src/cohort-topic/antidos/replay-guard.d.ts +17 -0
  35. package/dist/src/cohort-topic/antidos/replay-guard.d.ts.map +1 -1
  36. package/dist/src/cohort-topic/antidos/replay-guard.js +33 -0
  37. package/dist/src/cohort-topic/antidos/replay-guard.js.map +1 -1
  38. package/dist/src/cohort-topic/antidos/topic-budget.d.ts +7 -0
  39. package/dist/src/cohort-topic/antidos/topic-budget.d.ts.map +1 -1
  40. package/dist/src/cohort-topic/antidos/topic-budget.js +8 -2
  41. package/dist/src/cohort-topic/antidos/topic-budget.js.map +1 -1
  42. package/dist/src/cohort-topic/coldstart.d.ts +34 -14
  43. package/dist/src/cohort-topic/coldstart.d.ts.map +1 -1
  44. package/dist/src/cohort-topic/coldstart.js +25 -11
  45. package/dist/src/cohort-topic/coldstart.js.map +1 -1
  46. package/dist/src/cohort-topic/gossip/bus.d.ts +12 -1
  47. package/dist/src/cohort-topic/gossip/bus.d.ts.map +1 -1
  48. package/dist/src/cohort-topic/gossip/bus.js +27 -1
  49. package/dist/src/cohort-topic/gossip/bus.js.map +1 -1
  50. package/dist/src/cohort-topic/gossip/view.d.ts +8 -0
  51. package/dist/src/cohort-topic/gossip/view.d.ts.map +1 -1
  52. package/dist/src/cohort-topic/gossip/view.js +17 -1
  53. package/dist/src/cohort-topic/gossip/view.js.map +1 -1
  54. package/dist/src/cohort-topic/member-engine.d.ts +10 -3
  55. package/dist/src/cohort-topic/member-engine.d.ts.map +1 -1
  56. package/dist/src/cohort-topic/member-engine.js +29 -14
  57. package/dist/src/cohort-topic/member-engine.js.map +1 -1
  58. package/dist/src/cohort-topic/membership/publisher.d.ts +14 -7
  59. package/dist/src/cohort-topic/membership/publisher.d.ts.map +1 -1
  60. package/dist/src/cohort-topic/membership/publisher.js +15 -27
  61. package/dist/src/cohort-topic/membership/publisher.js.map +1 -1
  62. package/dist/src/cohort-topic/membership/verifier.d.ts +35 -0
  63. package/dist/src/cohort-topic/membership/verifier.d.ts.map +1 -1
  64. package/dist/src/cohort-topic/membership/verifier.js +88 -3
  65. package/dist/src/cohort-topic/membership/verifier.js.map +1 -1
  66. package/dist/src/cohort-topic/promotion.d.ts +7 -0
  67. package/dist/src/cohort-topic/promotion.d.ts.map +1 -1
  68. package/dist/src/cohort-topic/promotion.js +16 -2
  69. package/dist/src/cohort-topic/promotion.js.map +1 -1
  70. package/dist/src/cohort-topic/registration/renewal.d.ts +18 -0
  71. package/dist/src/cohort-topic/registration/renewal.d.ts.map +1 -1
  72. package/dist/src/cohort-topic/registration/renewal.js +54 -0
  73. package/dist/src/cohort-topic/registration/renewal.js.map +1 -1
  74. package/dist/src/cohort-topic/registration/types.d.ts +12 -0
  75. package/dist/src/cohort-topic/registration/types.d.ts.map +1 -1
  76. package/dist/src/cohort-topic/registration/types.js +14 -0
  77. package/dist/src/cohort-topic/registration/types.js.map +1 -1
  78. package/dist/src/cohort-topic/service.d.ts +4 -3
  79. package/dist/src/cohort-topic/service.d.ts.map +1 -1
  80. package/dist/src/cohort-topic/service.js +38 -12
  81. package/dist/src/cohort-topic/service.js.map +1 -1
  82. package/dist/src/cohort-topic/sig/payloads.d.ts +23 -7
  83. package/dist/src/cohort-topic/sig/payloads.d.ts.map +1 -1
  84. package/dist/src/cohort-topic/sig/payloads.js +22 -6
  85. package/dist/src/cohort-topic/sig/payloads.js.map +1 -1
  86. package/dist/src/cohort-topic/traffic.d.ts +6 -0
  87. package/dist/src/cohort-topic/traffic.d.ts.map +1 -1
  88. package/dist/src/cohort-topic/traffic.js +16 -1
  89. package/dist/src/cohort-topic/traffic.js.map +1 -1
  90. package/dist/src/cohort-topic/walk.d.ts +22 -7
  91. package/dist/src/cohort-topic/walk.d.ts.map +1 -1
  92. package/dist/src/cohort-topic/walk.js +78 -18
  93. package/dist/src/cohort-topic/walk.js.map +1 -1
  94. package/dist/src/cohort-topic/wire/codec.d.ts +3 -1
  95. package/dist/src/cohort-topic/wire/codec.d.ts.map +1 -1
  96. package/dist/src/cohort-topic/wire/codec.js +7 -1
  97. package/dist/src/cohort-topic/wire/codec.js.map +1 -1
  98. package/dist/src/cohort-topic/wire/index.d.ts +1 -1
  99. package/dist/src/cohort-topic/wire/index.d.ts.map +1 -1
  100. package/dist/src/cohort-topic/wire/index.js +1 -1
  101. package/dist/src/cohort-topic/wire/index.js.map +1 -1
  102. package/dist/src/cohort-topic/wire/payloads.d.ts +5 -4
  103. package/dist/src/cohort-topic/wire/payloads.d.ts.map +1 -1
  104. package/dist/src/cohort-topic/wire/payloads.js +14 -5
  105. package/dist/src/cohort-topic/wire/payloads.js.map +1 -1
  106. package/dist/src/cohort-topic/wire/primitives.d.ts +65 -0
  107. package/dist/src/cohort-topic/wire/primitives.d.ts.map +1 -0
  108. package/dist/src/cohort-topic/wire/primitives.js +173 -0
  109. package/dist/src/cohort-topic/wire/primitives.js.map +1 -0
  110. package/dist/src/cohort-topic/wire/types.d.ts +132 -5
  111. package/dist/src/cohort-topic/wire/types.d.ts.map +1 -1
  112. package/dist/src/cohort-topic/wire/validate.d.ts +15 -5
  113. package/dist/src/cohort-topic/wire/validate.d.ts.map +1 -1
  114. package/dist/src/cohort-topic/wire/validate.js +146 -123
  115. package/dist/src/cohort-topic/wire/validate.js.map +1 -1
  116. package/dist/src/collection/collection.d.ts +23 -12
  117. package/dist/src/collection/collection.d.ts.map +1 -1
  118. package/dist/src/collection/collection.js +111 -35
  119. package/dist/src/collection/collection.js.map +1 -1
  120. package/dist/src/collection/struct.d.ts +37 -2
  121. package/dist/src/collection/struct.d.ts.map +1 -1
  122. package/dist/src/collection/struct.js +16 -1
  123. package/dist/src/collection/struct.js.map +1 -1
  124. package/dist/src/collections/tree/tree.d.ts +18 -1
  125. package/dist/src/collections/tree/tree.d.ts.map +1 -1
  126. package/dist/src/collections/tree/tree.js +36 -6
  127. package/dist/src/collections/tree/tree.js.map +1 -1
  128. package/dist/src/index.d.ts +1 -0
  129. package/dist/src/index.d.ts.map +1 -1
  130. package/dist/src/index.js +1 -0
  131. package/dist/src/index.js.map +1 -1
  132. package/dist/src/log/log.d.ts +26 -3
  133. package/dist/src/log/log.d.ts.map +1 -1
  134. package/dist/src/log/log.js +34 -7
  135. package/dist/src/log/log.js.map +1 -1
  136. package/dist/src/log/struct.d.ts +5 -4
  137. package/dist/src/log/struct.d.ts.map +1 -1
  138. package/dist/src/log/struct.js.map +1 -1
  139. package/dist/src/matchmaking/wire.d.ts +2 -1
  140. package/dist/src/matchmaking/wire.d.ts.map +1 -1
  141. package/dist/src/matchmaking/wire.js +13 -92
  142. package/dist/src/matchmaking/wire.js.map +1 -1
  143. package/dist/src/network/i-key-network.d.ts +9 -0
  144. package/dist/src/network/i-key-network.d.ts.map +1 -1
  145. package/dist/src/network/i-repo.d.ts +8 -0
  146. package/dist/src/network/i-repo.d.ts.map +1 -1
  147. package/dist/src/network/struct.d.ts +10 -0
  148. package/dist/src/network/struct.d.ts.map +1 -1
  149. package/dist/src/reactivity/push-state.d.ts.map +1 -1
  150. package/dist/src/reactivity/push-state.js +4 -33
  151. package/dist/src/reactivity/push-state.js.map +1 -1
  152. package/dist/src/reactivity/wire-validate.d.ts +7 -22
  153. package/dist/src/reactivity/wire-validate.d.ts.map +1 -1
  154. package/dist/src/reactivity/wire-validate.js +7 -73
  155. package/dist/src/reactivity/wire-validate.js.map +1 -1
  156. package/dist/src/reactivity/wire.js +3 -3
  157. package/dist/src/reactivity/wire.js.map +1 -1
  158. package/dist/src/testing/async-wait.d.ts +23 -0
  159. package/dist/src/testing/async-wait.d.ts.map +1 -0
  160. package/dist/src/testing/async-wait.js +42 -0
  161. package/dist/src/testing/async-wait.js.map +1 -0
  162. package/dist/src/testing/index.d.ts +3 -0
  163. package/dist/src/testing/index.d.ts.map +1 -0
  164. package/dist/src/testing/index.js +3 -0
  165. package/dist/src/testing/index.js.map +1 -0
  166. package/dist/src/testing/test-transactor.d.ts +44 -0
  167. package/dist/src/testing/test-transactor.d.ts.map +1 -0
  168. package/dist/src/testing/test-transactor.js +423 -0
  169. package/dist/src/testing/test-transactor.js.map +1 -0
  170. package/dist/src/transaction/actions-engine.d.ts +6 -3
  171. package/dist/src/transaction/actions-engine.d.ts.map +1 -1
  172. package/dist/src/transaction/actions-engine.js +8 -7
  173. package/dist/src/transaction/actions-engine.js.map +1 -1
  174. package/dist/src/transaction/coordinator.d.ts +43 -22
  175. package/dist/src/transaction/coordinator.d.ts.map +1 -1
  176. package/dist/src/transaction/coordinator.js +443 -178
  177. package/dist/src/transaction/coordinator.js.map +1 -1
  178. package/dist/src/transaction/errors.d.ts +82 -0
  179. package/dist/src/transaction/errors.d.ts.map +1 -0
  180. package/dist/src/transaction/errors.js +93 -0
  181. package/dist/src/transaction/errors.js.map +1 -0
  182. package/dist/src/transaction/index.d.ts +6 -3
  183. package/dist/src/transaction/index.d.ts.map +1 -1
  184. package/dist/src/transaction/index.js +4 -2
  185. package/dist/src/transaction/index.js.map +1 -1
  186. package/dist/src/transaction/operations-hash.d.ts +119 -0
  187. package/dist/src/transaction/operations-hash.d.ts.map +1 -0
  188. package/dist/src/transaction/operations-hash.js +180 -0
  189. package/dist/src/transaction/operations-hash.js.map +1 -0
  190. package/dist/src/transaction/read-dependency-collector.d.ts +43 -0
  191. package/dist/src/transaction/read-dependency-collector.d.ts.map +1 -0
  192. package/dist/src/transaction/read-dependency-collector.js +69 -0
  193. package/dist/src/transaction/read-dependency-collector.js.map +1 -0
  194. package/dist/src/transaction/session.d.ts +12 -3
  195. package/dist/src/transaction/session.d.ts.map +1 -1
  196. package/dist/src/transaction/session.js +35 -9
  197. package/dist/src/transaction/session.js.map +1 -1
  198. package/dist/src/transaction/transaction.d.ts +162 -1
  199. package/dist/src/transaction/transaction.d.ts.map +1 -1
  200. package/dist/src/transaction/transaction.js +85 -3
  201. package/dist/src/transaction/transaction.js.map +1 -1
  202. package/dist/src/transaction/validator.d.ts +3 -11
  203. package/dist/src/transaction/validator.d.ts.map +1 -1
  204. package/dist/src/transaction/validator.js +69 -28
  205. package/dist/src/transaction/validator.js.map +1 -1
  206. package/dist/src/transactor/network-transactor.d.ts +35 -0
  207. package/dist/src/transactor/network-transactor.d.ts.map +1 -1
  208. package/dist/src/transactor/network-transactor.js +146 -40
  209. package/dist/src/transactor/network-transactor.js.map +1 -1
  210. package/dist/src/transactor/transactor-source.d.ts +19 -5
  211. package/dist/src/transactor/transactor-source.d.ts.map +1 -1
  212. package/dist/src/transactor/transactor-source.js +43 -11
  213. package/dist/src/transactor/transactor-source.js.map +1 -1
  214. package/dist/src/transform/atomic-proxy.d.ts +35 -5
  215. package/dist/src/transform/atomic-proxy.d.ts.map +1 -1
  216. package/dist/src/transform/atomic-proxy.js +39 -7
  217. package/dist/src/transform/atomic-proxy.js.map +1 -1
  218. package/dist/src/transform/cache-source.d.ts +36 -5
  219. package/dist/src/transform/cache-source.d.ts.map +1 -1
  220. package/dist/src/transform/cache-source.js +84 -8
  221. package/dist/src/transform/cache-source.js.map +1 -1
  222. package/dist/src/transform/helpers.d.ts.map +1 -1
  223. package/dist/src/transform/helpers.js +8 -2
  224. package/dist/src/transform/helpers.js.map +1 -1
  225. package/dist/src/transform/tracker.d.ts +17 -2
  226. package/dist/src/transform/tracker.d.ts.map +1 -1
  227. package/dist/src/transform/tracker.js +66 -11
  228. package/dist/src/transform/tracker.js.map +1 -1
  229. package/dist/src/utility/backoff.d.ts +48 -0
  230. package/dist/src/utility/backoff.d.ts.map +1 -0
  231. package/dist/src/utility/backoff.js +60 -0
  232. package/dist/src/utility/backoff.js.map +1 -0
  233. package/dist/src/utility/pending.d.ts +1 -0
  234. package/dist/src/utility/pending.d.ts.map +1 -1
  235. package/dist/src/utility/pending.js +3 -1
  236. package/dist/src/utility/pending.js.map +1 -1
  237. package/package.json +4 -4
  238. package/src/blocks/block-store.ts +19 -1
  239. package/src/blocks/helpers.ts +3 -3
  240. package/src/btree/btree.ts +108 -63
  241. package/src/chain/chain.ts +11 -1
  242. package/src/cluster/index.ts +1 -0
  243. package/src/cluster/membership.ts +85 -0
  244. package/src/cluster/structs.ts +51 -1
  245. package/src/cohort-topic/addressing.ts +12 -4
  246. package/src/cohort-topic/antidos/bootstrap-evidence.ts +21 -9
  247. package/src/cohort-topic/antidos/replay-guard.ts +37 -0
  248. package/src/cohort-topic/antidos/topic-budget.ts +17 -2
  249. package/src/cohort-topic/coldstart.ts +48 -15
  250. package/src/cohort-topic/gossip/bus.ts +39 -2
  251. package/src/cohort-topic/gossip/view.ts +26 -1
  252. package/src/cohort-topic/member-engine.ts +36 -15
  253. package/src/cohort-topic/membership/publisher.ts +25 -33
  254. package/src/cohort-topic/membership/verifier.ts +119 -3
  255. package/src/cohort-topic/promotion.ts +23 -2
  256. package/src/cohort-topic/registration/renewal.ts +73 -1
  257. package/src/cohort-topic/registration/types.ts +15 -0
  258. package/src/cohort-topic/service.ts +41 -15
  259. package/src/cohort-topic/sig/payloads.ts +29 -9
  260. package/src/cohort-topic/traffic.ts +23 -1
  261. package/src/cohort-topic/walk.ts +95 -24
  262. package/src/cohort-topic/wire/codec.ts +12 -0
  263. package/src/cohort-topic/wire/index.ts +2 -0
  264. package/src/cohort-topic/wire/payloads.ts +14 -5
  265. package/src/cohort-topic/wire/primitives.ts +188 -0
  266. package/src/cohort-topic/wire/types.ts +136 -4
  267. package/src/cohort-topic/wire/validate.ts +168 -134
  268. package/src/collection/collection.ts +123 -40
  269. package/src/collection/struct.ts +44 -2
  270. package/src/collections/tree/tree.ts +42 -5
  271. package/src/index.ts +1 -0
  272. package/src/log/log.ts +37 -9
  273. package/src/log/struct.ts +5 -4
  274. package/src/matchmaking/wire.ts +25 -102
  275. package/src/network/i-key-network.ts +10 -0
  276. package/src/network/i-repo.ts +8 -0
  277. package/src/network/struct.ts +10 -0
  278. package/src/reactivity/push-state.ts +4 -37
  279. package/src/reactivity/wire-validate.ts +7 -81
  280. package/src/reactivity/wire.ts +3 -3
  281. package/src/testing/async-wait.ts +65 -0
  282. package/src/testing/index.ts +2 -0
  283. package/src/testing/test-transactor.ts +468 -0
  284. package/src/transaction/actions-engine.ts +8 -6
  285. package/src/transaction/coordinator.ts +498 -229
  286. package/src/transaction/errors.ts +91 -0
  287. package/src/transaction/index.ts +23 -3
  288. package/src/transaction/operations-hash.ts +196 -0
  289. package/src/transaction/read-dependency-collector.ts +78 -0
  290. package/src/transaction/session.ts +37 -9
  291. package/src/transaction/transaction.ts +211 -4
  292. package/src/transaction/validator.ts +73 -48
  293. package/src/transactor/network-transactor.ts +164 -49
  294. package/src/transactor/transactor-source.ts +47 -12
  295. package/src/transform/atomic-proxy.ts +92 -49
  296. package/src/transform/cache-source.ts +87 -9
  297. package/src/transform/helpers.ts +8 -2
  298. package/src/transform/tracker.ts +69 -11
  299. package/src/utility/backoff.ts +95 -0
  300. package/src/utility/pending.ts +3 -1
  301. package/src/transaction/context.ts +0 -103
@@ -88,9 +88,10 @@ class WalkRegisterService {
88
88
  return this.hintFromReply(topicId, tier, outcome.reply);
89
89
  }
90
90
  async renew(handle) {
91
- // Withdrawn handles drop out of the live set; renewing one is a no-op so withdraw() actually
92
- // stops the local ping loop (rather than the app silently continuing to refresh it).
93
- if (!this.renewals.has(recordKey(handle.topicId, this.participantId))) {
91
+ // Act only if this handle is still the live entry. A stale handle (superseded by a second
92
+ // register() for the same pair) must not drive the new registration's ping loop, and a
93
+ // withdrawn handle must not silently re-start it.
94
+ if (this.renewals.get(recordKey(handle.topicId, this.participantId)) !== handle.renewal) {
94
95
  return;
95
96
  }
96
97
  await handle.renewal.pingLoop();
@@ -103,11 +104,16 @@ class WalkRegisterService {
103
104
  // The delete happens FIRST so a concurrent renew() already no-ops before the tombstone is sent. If
104
105
  // the tombstone send fails (primary unreachable), the cohort soft-state TTL-expires as the
105
106
  // fallback — withdraw never throws on a transport failure. Idempotent: a second withdraw finds
106
- // `renewal === undefined` and no-ops.
107
+ // `renewal !== handle.renewal` (undefined ≠ any object) and no-ops.
108
+ // Guard: act only if this handle is still the live entry. A stale handle must not evict the
109
+ // new registration or send a tombstone on its behalf.
107
110
  const key = recordKey(handle.topicId, this.participantId);
108
111
  const renewal = this.renewals.get(key);
112
+ if (renewal !== handle.renewal) {
113
+ return;
114
+ }
109
115
  this.renewals.delete(key);
110
- await renewal?.withdraw();
116
+ await renewal.withdraw();
111
117
  }
112
118
  cohortGossip() {
113
119
  return this.deps.gossipBus;
@@ -121,10 +127,10 @@ class WalkRegisterService {
121
127
  throw new CohortBackoffError(outcome.kind === "retry_later" ? outcome.afterMs : 0);
122
128
  }
123
129
  const hint = this.hintFromReply(req.topicId, req.tier, outcome.reply);
124
- const renewal = this.startRenewal(req, hint, outcome.reply);
130
+ const renewal = this.startRenewal(req, hint, outcome.correlationId);
125
131
  return { ...hint, renewal };
126
132
  }
127
- startRenewal(req, hint, reply) {
133
+ startRenewal(req, hint, correlationId) {
128
134
  const ttl = req.ttl ?? this.ttl;
129
135
  const initial = {
130
136
  topicId: req.topicId,
@@ -142,9 +148,21 @@ class WalkRegisterService {
142
148
  transport,
143
149
  clock: this.clock,
144
150
  sign: (body) => this.deps.signer.signRenew(body),
145
- correlationId: reply.cohortEpoch ?? bytesToB64url(this.participantId),
151
+ // Echo the accepted RegisterV1's correlationId: RenewV1 `correlationId` "matches original
152
+ // RegisterV1" (docs §Wire, RenewV1), so a future renew-path freshness/replay guard can correlate
153
+ // a renew back to the registration it renews.
154
+ // NOTE: every periodic renew for this registration shares this ONE correlationId (as it always
155
+ // has — this only makes the shared id equal the register's, not an independent nonce). A future
156
+ // renew replay guard must therefore key renews by (correlationId, timestamp-window), NOT "drop
157
+ // any repeated correlationId" — else it would reject the 2nd+ legitimate renew.
158
+ correlationId,
146
159
  initialCohortEpoch: hint.cohortEpoch,
147
160
  });
161
+ // NOTE: a second register() for the same (topicId, participantId) overwrites the map entry here,
162
+ // orphaning the prior renewal. renew()/withdraw() on the stale handle now no-op (identity guard),
163
+ // but no tombstone is sent for the superseded record — the cohort frees it via TTL expiry. Harmless
164
+ // for occasional re-registers; if callers ever churn-register the same pair, send a withdraw for the
165
+ // displaced renewal here so the cohort reclaims immediately instead of holding up to a full TTL.
148
166
  this.renewals.set(recordKey(req.topicId, this.participantId), renewal);
149
167
  return renewal;
150
168
  }
@@ -199,12 +217,20 @@ class WalkRegisterService {
199
217
  correlationId: this.freshCorrelationId(),
200
218
  };
201
219
  if (params.probe) {
202
- // A read-only lookup probe. Mutually exclusive with bootstrap (the walk never sets
203
- // `bootstrap` on a probe), so the cold-start-evidence branch below cannot run for a probe.
220
+ // A read-only lookup probe. Mutually exclusive with bootstrap/followOn (the walk never sets
221
+ // either on a probe), so the cold-start-evidence branch below cannot run for a probe.
204
222
  body.probe = true;
205
223
  }
206
- if (params.bootstrap) {
207
- body.bootstrap = true;
224
+ // A cold-start re-issue — root (`bootstrap`) or deeper-tier follow-on (`followOn`). Both are
225
+ // gated by the identical evidence policy (§Anti-DoS), so both mint and attach the same envelope
226
+ // bound to the body's own canonical fields. Mutually exclusive with each other and with probe.
227
+ if (params.bootstrap || params.followOn) {
228
+ if (params.followOn) {
229
+ body.followOn = true;
230
+ }
231
+ else {
232
+ body.bootstrap = true;
233
+ }
208
234
  // Attach cold-start evidence BEFORE signing (so the signature covers it). Bind the
209
235
  // builder to the body's own canonical fields — the exact tuple a verifier reconstructs.
210
236
  const evidence = await this.deps.buildBootstrapEvidence?.({
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/cohort-topic/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/cohort-topic/service.ts"],"names":[],"mappings":"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"}
@@ -3,23 +3,39 @@
3
3
  *
4
4
  * A threshold signature is only verifiable if signer and verifier agree on the exact bytes signed.
5
5
  * These builders produce that deterministic byte image for each threshold-signed message
6
- * (`MembershipCertV1`, `PromotionNoticeV1`, `DemotionNoticeV1`), covering exactly the semantic
7
- * fields per `docs/cohort-topic.md` §Wire formats — never the `thresholdSig`/`signers` envelope.
6
+ * (`MembershipCertV1`, `PromotionNoticeV1`, `DemotionNoticeV1`, `ChildLinkV1`), covering exactly the
7
+ * semantic fields per `docs/cohort-topic.md` §Wire formats — never the `thresholdSig`/`signers` envelope.
8
8
  *
9
9
  * Determinism comes from encoding an explicitly-ordered JSON array (array order is stable, unlike
10
10
  * object key order) as UTF-8. The publisher signs this image; the verifier recomputes and checks it.
11
+ *
12
+ * The notice images carry `cohortCoord` (the served coord the deciding cohort sits at) so the coord the
13
+ * receiver routes by is bound into the signed bytes — rewriting it to hijack a sibling cohort breaks
14
+ * verification. It is inserted **just before the trailing `cohortEpoch`**, deliberately keeping `cohortEpoch`
15
+ * the LAST element: the `/sign` endorser (`handleSignRequest`) reads a notice's embedded epoch positionally
16
+ * as `image[image.length - 1]`, so `cohortEpoch` must stay last. This is a hard, coordinated change to the
17
+ * canonical signed bytes, acceptable pre-release (no deployed nodes speak this protocol, so there is no
18
+ * version to negotiate).
11
19
  */
12
- import type { DemotionNoticeV1, MembershipCertV1, PromotionNoticeV1 } from "../wire/types.js";
20
+ import type { ChildLinkV1, DemotionNoticeV1, MembershipCertV1, PromotionNoticeV1 } from "../wire/types.js";
13
21
  /** Fields of a `MembershipCertV1` covered by its threshold signature (doc: cohortCoord, cohortEpoch, members, stabilizedAt). */
14
22
  export type MembershipCertSignable = Pick<MembershipCertV1, "cohortCoord" | "cohortEpoch" | "members" | "stabilizedAt">;
15
23
  /** Canonical signed byte image of a membership certificate. */
16
24
  export declare function membershipCertSigningPayload(cert: MembershipCertSignable): Uint8Array;
17
25
  /** Fields of a `PromotionNoticeV1` covered by its threshold signature. */
18
- export type PromotionSignable = Pick<PromotionNoticeV1, "topicId" | "fromTier" | "toTier" | "effectiveAt" | "cohortEpoch">;
19
- /** Canonical signed byte image of a promotion notice. */
26
+ export type PromotionSignable = Pick<PromotionNoticeV1, "topicId" | "fromTier" | "toTier" | "effectiveAt" | "cohortEpoch" | "cohortCoord">;
27
+ /** Canonical signed byte image of a promotion notice. `cohortEpoch` stays last (the `/sign` endorser reads it positionally). */
20
28
  export declare function promotionNoticeSigningPayload(n: PromotionSignable): Uint8Array;
21
29
  /** Fields of a `DemotionNoticeV1` covered by its threshold signature. */
22
- export type DemotionSignable = Pick<DemotionNoticeV1, "topicId" | "tier" | "parentCohortCoord" | "effectiveAt" | "cohortEpoch">;
23
- /** Canonical signed byte image of a demotion notice. */
30
+ export type DemotionSignable = Pick<DemotionNoticeV1, "topicId" | "tier" | "parentCohortCoord" | "effectiveAt" | "cohortEpoch" | "cohortCoord">;
31
+ /** Canonical signed byte image of a demotion notice. `cohortEpoch` stays last (the `/sign` endorser reads it positionally). */
24
32
  export declare function demotionNoticeSigningPayload(n: DemotionSignable): Uint8Array;
33
+ /** Fields of a `ChildLinkV1` covered by the child cohort's threshold signature. */
34
+ export type ChildLinkSignable = Pick<ChildLinkV1, "topicId" | "childCohortCoord" | "childParticipantCoord" | "childTier" | "tier" | "effectiveAt" | "cohortEpoch">;
35
+ /**
36
+ * Canonical signed byte image of a child-link frame. `cohortEpoch` stays **last** so the `/sign` endorser
37
+ * (`handleSignRequest`) reads the embedded epoch positionally as `image[image.length - 1]`, exactly as it
38
+ * does for a promotion / demotion notice.
39
+ */
40
+ export declare function childLinkSigningPayload(n: ChildLinkSignable): Uint8Array;
25
41
  //# sourceMappingURL=payloads.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"payloads.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/sig/payloads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI9F,gIAAgI;AAChI,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS,GAAG,cAAc,CAAC,CAAC;AAExH,+DAA+D;AAC/D,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,sBAAsB,GAAG,UAAU,CAErF;AAED,0EAA0E;AAC1E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;AAE3H,yDAAyD;AACzD,wBAAgB,6BAA6B,CAAC,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAE9E;AAED,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,MAAM,GAAG,mBAAmB,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;AAEhI,wDAAwD;AACxD,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAE5E"}
1
+ {"version":3,"file":"payloads.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/sig/payloads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI3G,gIAAgI;AAChI,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS,GAAG,cAAc,CAAC,CAAC;AAExH,+DAA+D;AAC/D,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,sBAAsB,GAAG,UAAU,CAErF;AAED,0EAA0E;AAC1E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;AAE3I,gIAAgI;AAChI,wBAAgB,6BAA6B,CAAC,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAE9E;AAED,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,MAAM,GAAG,mBAAmB,GAAG,aAAa,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;AAEhJ,+HAA+H;AAC/H,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAE5E;AAED,mFAAmF;AACnF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,kBAAkB,GAAG,uBAAuB,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;AAEnK;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAExE"}
@@ -3,23 +3,39 @@
3
3
  *
4
4
  * A threshold signature is only verifiable if signer and verifier agree on the exact bytes signed.
5
5
  * These builders produce that deterministic byte image for each threshold-signed message
6
- * (`MembershipCertV1`, `PromotionNoticeV1`, `DemotionNoticeV1`), covering exactly the semantic
7
- * fields per `docs/cohort-topic.md` §Wire formats — never the `thresholdSig`/`signers` envelope.
6
+ * (`MembershipCertV1`, `PromotionNoticeV1`, `DemotionNoticeV1`, `ChildLinkV1`), covering exactly the
7
+ * semantic fields per `docs/cohort-topic.md` §Wire formats — never the `thresholdSig`/`signers` envelope.
8
8
  *
9
9
  * Determinism comes from encoding an explicitly-ordered JSON array (array order is stable, unlike
10
10
  * object key order) as UTF-8. The publisher signs this image; the verifier recomputes and checks it.
11
+ *
12
+ * The notice images carry `cohortCoord` (the served coord the deciding cohort sits at) so the coord the
13
+ * receiver routes by is bound into the signed bytes — rewriting it to hijack a sibling cohort breaks
14
+ * verification. It is inserted **just before the trailing `cohortEpoch`**, deliberately keeping `cohortEpoch`
15
+ * the LAST element: the `/sign` endorser (`handleSignRequest`) reads a notice's embedded epoch positionally
16
+ * as `image[image.length - 1]`, so `cohortEpoch` must stay last. This is a hard, coordinated change to the
17
+ * canonical signed bytes, acceptable pre-release (no deployed nodes speak this protocol, so there is no
18
+ * version to negotiate).
11
19
  */
12
20
  const utf8 = new TextEncoder();
13
21
  /** Canonical signed byte image of a membership certificate. */
14
22
  export function membershipCertSigningPayload(cert) {
15
23
  return utf8.encode(JSON.stringify(["MembershipCertV1", cert.cohortCoord, cert.cohortEpoch, cert.members, cert.stabilizedAt]));
16
24
  }
17
- /** Canonical signed byte image of a promotion notice. */
25
+ /** Canonical signed byte image of a promotion notice. `cohortEpoch` stays last (the `/sign` endorser reads it positionally). */
18
26
  export function promotionNoticeSigningPayload(n) {
19
- return utf8.encode(JSON.stringify(["PromotionNoticeV1", n.topicId, n.fromTier, n.toTier, n.effectiveAt, n.cohortEpoch]));
27
+ return utf8.encode(JSON.stringify(["PromotionNoticeV1", n.topicId, n.fromTier, n.toTier, n.effectiveAt, n.cohortCoord, n.cohortEpoch]));
20
28
  }
21
- /** Canonical signed byte image of a demotion notice. */
29
+ /** Canonical signed byte image of a demotion notice. `cohortEpoch` stays last (the `/sign` endorser reads it positionally). */
22
30
  export function demotionNoticeSigningPayload(n) {
23
- return utf8.encode(JSON.stringify(["DemotionNoticeV1", n.topicId, n.tier, n.parentCohortCoord, n.effectiveAt, n.cohortEpoch]));
31
+ return utf8.encode(JSON.stringify(["DemotionNoticeV1", n.topicId, n.tier, n.parentCohortCoord, n.effectiveAt, n.cohortCoord, n.cohortEpoch]));
32
+ }
33
+ /**
34
+ * Canonical signed byte image of a child-link frame. `cohortEpoch` stays **last** so the `/sign` endorser
35
+ * (`handleSignRequest`) reads the embedded epoch positionally as `image[image.length - 1]`, exactly as it
36
+ * does for a promotion / demotion notice.
37
+ */
38
+ export function childLinkSigningPayload(n) {
39
+ return utf8.encode(JSON.stringify(["ChildLinkV1", n.topicId, n.childCohortCoord, n.childParticipantCoord, n.childTier, n.tier, n.effectiveAt, n.cohortEpoch]));
24
40
  }
25
41
  //# sourceMappingURL=payloads.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payloads.js","sourceRoot":"","sources":["../../../../src/cohort-topic/sig/payloads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;AAK/B,+DAA+D;AAC/D,MAAM,UAAU,4BAA4B,CAAC,IAA4B;IACxE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAC/H,CAAC;AAKD,yDAAyD;AACzD,MAAM,UAAU,6BAA6B,CAAC,CAAoB;IACjE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC1H,CAAC;AAKD,wDAAwD;AACxD,MAAM,UAAU,4BAA4B,CAAC,CAAmB;IAC/D,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAChI,CAAC"}
1
+ {"version":3,"file":"payloads.js","sourceRoot":"","sources":["../../../../src/cohort-topic/sig/payloads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;AAK/B,+DAA+D;AAC/D,MAAM,UAAU,4BAA4B,CAAC,IAA4B;IACxE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAC/H,CAAC;AAKD,gIAAgI;AAChI,MAAM,UAAU,6BAA6B,CAAC,CAAoB;IACjE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACzI,CAAC;AAKD,+HAA+H;AAC/H,MAAM,UAAU,4BAA4B,CAAC,CAAmB;IAC/D,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/I,CAAC;AAKD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAoB;IAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAChK,CAAC"}
@@ -58,6 +58,12 @@ export interface TrafficCounters {
58
58
  snapshot(topicId: Uint8Array): TopicTrafficV1;
59
59
  /** Reset all counters to zero (call on `cohortEpoch` change). */
60
60
  reset(): void;
61
+ /**
62
+ * Drop all local windowed counts and the last-published summary for `topicId` (the cohort no longer
63
+ * serves it — budget eviction / teardown). Idempotent; a no-op if never observed. Siblings' gossiped
64
+ * contributions age out of {@link snapshot} on their own as their summaries stop naming the topic.
65
+ */
66
+ forget(topicId: Uint8Array): void;
61
67
  }
62
68
  export interface TrafficCountersDeps {
63
69
  /** Merged per-member gossip view — siblings' last-gossiped per-topic summaries. */
@@ -1 +1 @@
1
- {"version":3,"file":"traffic.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/traffic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE3F,gEAAgE;AAChE,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,mEAAmE;AACnE,UAAU,cAAc;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAQD,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC/B,+FAA+F;IAC/F,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,oEAAoE;IACpE,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAAC;IAC1D,kGAAkG;IAClG,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;IAC9C,iEAAiE;IACjE,KAAK,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IACnC,mFAAmF;IACnF,IAAI,EAAE,UAAU,CAAC;IACjB,iGAAiG;IACjG,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAC;IACrD,4GAA4G;IAC5G,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC;CACnD;AA6FD,+CAA+C;AAC/C,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,GAAG,eAAe,CAKnG;AAED,qHAAqH;AACrH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,cAAc,EACzB,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC/F,kBAAkB,CAUpB"}
1
+ {"version":3,"file":"traffic.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/traffic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE3F,gEAAgE;AAChE,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,mEAAmE;AACnE,UAAU,cAAc;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAQD,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC/B,+FAA+F;IAC/F,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,oEAAoE;IACpE,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAAC;IAC1D,kGAAkG;IAClG,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;IAC9C,iEAAiE;IACjE,KAAK,IAAI,IAAI,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IACnC,mFAAmF;IACnF,IAAI,EAAE,UAAU,CAAC;IACjB,iGAAiG;IACjG,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAC;IACrD,4GAA4G;IAC5G,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC;CACnD;AA6GD,+CAA+C;AAC/C,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,GAAG,eAAe,CAKnG;AAED,qHAAqH;AACrH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,cAAc,EACzB,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC/F,kBAAkB,CAUpB"}
@@ -71,7 +71,11 @@ class WindowedTrafficCounters {
71
71
  for (const [member, contribution] of this.deps.view.all()) {
72
72
  if (member === this.deps.selfMember)
73
73
  continue; // own contribution comes from lastPublished
74
- const summary = contribution.topicSummaries.find((s) => s.topicId === topicB64);
74
+ // O(1) per-topic lookup via the merge-time index; fall back to a scan only for a contribution
75
+ // not built through `merge` (which populates `topicIndex`). Net: snapshot is O(members + summaries).
76
+ const summary = contribution.topicIndex !== undefined
77
+ ? contribution.topicIndex.get(topicB64)
78
+ : contribution.topicSummaries.find((s) => s.topicId === topicB64);
75
79
  if (summary === undefined)
76
80
  continue;
77
81
  arrivals += summary.arrivalsPerMin;
@@ -80,6 +84,10 @@ class WindowedTrafficCounters {
80
84
  childCohortCount = summary.childCohortCount;
81
85
  }
82
86
  }
87
+ // NOTE: `childCohortCount` (the max of siblings' gossiped counts above) is dormant whenever the
88
+ // registry override is wired — the override returns a number (0 included), so `?? childCohortCount`
89
+ // never falls through. It becomes the effective value only if the override is unwired; the child-set
90
+ // replication follow-on converges siblings by populating each engine's registry, not via this max.
83
91
  const childOverride = this.deps.childCohortCount?.(topicId);
84
92
  return {
85
93
  windowSeconds: this.windowMs / 1000,
@@ -93,6 +101,13 @@ class WindowedTrafficCounters {
93
101
  this.windows.clear();
94
102
  this.lastPublished.clear();
95
103
  }
104
+ forget(topicId) {
105
+ // Idempotent: `Map.delete` on an absent key is a safe no-op. Clears both the raw windowed events
106
+ // and the frozen last-published summary so a re-instantiated topic starts from zero.
107
+ const key = bytesKey(topicId);
108
+ this.windows.delete(key);
109
+ this.lastPublished.delete(key);
110
+ }
96
111
  windowFor(topicId) {
97
112
  const key = bytesKey(topicId);
98
113
  let w = this.windows.get(key);
@@ -1 +1 @@
1
- {"version":3,"file":"traffic.js","sourceRoot":"","sources":["../../../src/cohort-topic/traffic.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"traffic.js","sourceRoot":"","sources":["../../../src/cohort-topic/traffic.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,12 @@
10
10
  * Reply handling (§Lookup):
11
11
  * - **`accepted`** → done; return the reply (carries `primary`/`backups`/`cohortEpoch` to cache).
12
12
  * - **`no_state`** at tier `d` → step one tier toward the root (`d − 1`); no traffic signal. At the
13
- * root (`d − 1 < 0`) re-issue once at tier 0 with `bootstrap: true` (cold-start request).
13
+ * root (`d − 1 < 0`) re-issue once at tier 0 with `bootstrap: true` (cold-start request). **If this
14
+ * `no_state` is the redirect target of a `Promoted` this walk just followed** (`followedPromoted`),
15
+ * the deeper child is cold: a register re-issues **once** at the same tier with `followOn: true` (a
16
+ * deeper-tier cold-start, gated by the same evidence a `bootstrap` pays), then backs off if that too
17
+ * returns `no_state`; a probe never instantiates, so it backs off immediately. This is what lets a
18
+ * join that lands on a freshly-promoted-but-not-yet-grown branch converge instead of oscillating.
14
19
  * - **`promoted(targetTier)`** → recompute `coord_targetTier(self, topicId)` and register there — the
15
20
  * one outward move, taken only on this explicit redirect.
16
21
  * - **`unwilling_member(candidates)`** → retry the **same** coord at a named alternative member
@@ -33,6 +38,12 @@ import type { RegisterReplyV1, RegisterV1 } from "./wire/types.js";
33
38
  export interface AcceptedWalkOutcome {
34
39
  readonly kind: "accepted";
35
40
  readonly reply: RegisterReplyV1;
41
+ /**
42
+ * The accepted register probe's own `correlationId`. The participant echoes it on every renew for this
43
+ * registration so `RenewV1.correlationId` "matches original `RegisterV1`" (docs §Wire, RenewV1). Each
44
+ * probe carries a distinct correlationId; this is the one the cohort admitted.
45
+ */
46
+ readonly correlationId: string;
36
47
  }
37
48
  /**
38
49
  * The walk hit a `Promoted` redirect and the engine was configured **not** to follow it
@@ -57,18 +68,22 @@ export type WalkOutcome = AcceptedWalkOutcome | PromotedWalkOutcome | RetryLater
57
68
  /** Builds (and signs) the {@link RegisterV1} for one probe; owns participant identity + crypto. */
58
69
  export interface RegisterMessageFactory {
59
70
  /**
60
- * Produce a signed `RegisterV1` for this participant at walk position `treeTier`. `bootstrap` is
61
- * set only on the root cold-start re-issue. `appPayload` is the opaque application slot. On the
62
- * bootstrap re-issue the factory may additionally mint and attach the signed `bootstrapEvidence`
63
- * envelope (§Anti-DoS) via the injected builder seam before signing keyed off `bootstrap`, so no
64
- * extra build parameter is needed (the walk decides `bootstrap` internally, not the application).
71
+ * Produce a signed `RegisterV1` for this participant at walk position `treeTier`. `bootstrap` is set
72
+ * only on the root cold-start re-issue; `followOn` only on the dedicated re-issue after a `Promoted`
73
+ * redirect target answered `NoState` (§Cold-start). `appPayload` is the opaque application slot. On
74
+ * either cold-start re-issue the factory mints and attaches the signed `bootstrapEvidence` envelope
75
+ * (§Anti-DoS a follow-on is gated identically to a bootstrap) via the injected builder seam before
76
+ * signing — keyed off `bootstrap`/`followOn`, so no extra parameter is needed (the walk decides both
77
+ * internally, not the application). `bootstrap`, `followOn`, and `probe` are mutually exclusive.
65
78
  */
66
79
  build(params: {
67
80
  topicId: Uint8Array;
68
81
  tier: number;
69
82
  treeTier: number;
70
83
  bootstrap: boolean;
71
- /** Read-only lookup probe: the factory stamps `RegisterV1.probe` and never mints bootstrap evidence. */
84
+ /** Follow-on cold-start re-issue after a `Promoted` redirect target answered `NoState` (`treeTier >= 1`). */
85
+ followOn: boolean;
86
+ /** Read-only lookup probe: the factory stamps `RegisterV1.probe` and never mints cold-start evidence. */
72
87
  probe: boolean;
73
88
  appPayload?: Uint8Array;
74
89
  }): Promise<RegisterV1>;
@@ -1 +1 @@
1
- {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEnE,sGAAsG;AACtG,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAExF,mGAAmG;AACnG,MAAM,WAAW,sBAAsB;IACtC;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,EAAE;QACb,OAAO,EAAE,UAAU,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,OAAO,CAAC;QACnB,wGAAwG;QACxG,KAAK,EAAE,OAAO,CAAC;QACf,UAAU,CAAC,EAAE,UAAU,CAAC;KACxB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IAC1B,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mHAAmH;IACnH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,cAAc,CAAC;IAC3B,mFAAmF;IACnF,IAAI,EAAE,YAAY,CAAC;IACnB,qEAAqE;IACrE,IAAI,EAAE,UAAU,CAAC;IACjB,iDAAiD;IACjD,OAAO,EAAE,sBAAsB,CAAC;IAChC,MAAM,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,kGAAkG;AAClG,MAAM,WAAW,UAAU;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACvH;AA2HD,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAEjE"}
1
+ {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAI9C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEnE,sGAAsG;AACtG,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAExF,mGAAmG;AACnG,MAAM,WAAW,sBAAsB;IACtC;;;;;;;;OAQG;IACH,KAAK,CAAC,MAAM,EAAE;QACb,OAAO,EAAE,UAAU,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,OAAO,CAAC;QACnB,6GAA6G;QAC7G,QAAQ,EAAE,OAAO,CAAC;QAClB,yGAAyG;QACzG,KAAK,EAAE,OAAO,CAAC;QACf,UAAU,CAAC,EAAE,UAAU,CAAC;KACxB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IAC1B,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mHAAmH;IACnH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,cAAc,CAAC;IAC3B,mFAAmF;IACnF,IAAI,EAAE,YAAY,CAAC;IACnB,qEAAqE;IACrE,IAAI,EAAE,UAAU,CAAC;IACjB,iDAAiD;IACjD,OAAO,EAAE,sBAAsB,CAAC;IAChC,MAAM,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,kGAAkG;AAClG,MAAM,WAAW,UAAU;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACvH;AAkLD,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAEjE"}
@@ -10,7 +10,12 @@
10
10
  * Reply handling (§Lookup):
11
11
  * - **`accepted`** → done; return the reply (carries `primary`/`backups`/`cohortEpoch` to cache).
12
12
  * - **`no_state`** at tier `d` → step one tier toward the root (`d − 1`); no traffic signal. At the
13
- * root (`d − 1 < 0`) re-issue once at tier 0 with `bootstrap: true` (cold-start request).
13
+ * root (`d − 1 < 0`) re-issue once at tier 0 with `bootstrap: true` (cold-start request). **If this
14
+ * `no_state` is the redirect target of a `Promoted` this walk just followed** (`followedPromoted`),
15
+ * the deeper child is cold: a register re-issues **once** at the same tier with `followOn: true` (a
16
+ * deeper-tier cold-start, gated by the same evidence a `bootstrap` pays), then backs off if that too
17
+ * returns `no_state`; a probe never instantiates, so it backs off immediately. This is what lets a
18
+ * join that lands on a freshly-promoted-but-not-yet-grown branch converge instead of oscillating.
14
19
  * - **`promoted(targetTier)`** → recompute `coord_targetTier(self, topicId)` and register there — the
15
20
  * one outward move, taken only on this explicit redirect.
16
21
  * - **`unwilling_member(candidates)`** → retry the **same** coord at a named alternative member
@@ -25,8 +30,18 @@
25
30
  * signing the {@link RegisterV1} to the injected {@link RegisterMessageFactory} (participant identity
26
31
  * and crypto live there, not here).
27
32
  */
33
+ import { DEFAULT_D_MAX_CAP } from "./dmax.js";
28
34
  import { backoffRetryMs } from "./willingness.js";
29
35
  import { b64urlToBytes, decodeRegisterReplyV1, encodeCohortMessage } from "./wire/codec.js";
36
+ /**
37
+ * A walk tier is valid iff it is an integer in `0..DEFAULT_D_MAX_CAP` — the substrate's own walk-depth
38
+ * ceiling. A `promoted` reply's explicit `targetTier` is untrusted: an out-of-range value (non-integer,
39
+ * negative, or above the ceiling) cannot name a real cohort and would reach `addressing.coord()` →
40
+ * `coordD`, which throws a raw `RangeError`. Matches the range the wire `treeTier` validator enforces.
41
+ */
42
+ function isValidTreeTier(value) {
43
+ return Number.isInteger(value) && value >= 0 && value <= DEFAULT_D_MAX_CAP;
44
+ }
30
45
  class RouterWalkEngine {
31
46
  deps;
32
47
  wantK;
@@ -51,17 +66,26 @@ class RouterWalkEngine {
51
66
  const probe = opts?.probe ?? false;
52
67
  let d = dMax;
53
68
  let bootstrap = false;
54
- let memberAttempts = 0;
69
+ let followOn = false;
70
+ // Member ids (base64url) already dialed on this walk's `unwilling_member` retries. Tracking WHICH
71
+ // members were tried — not a positional counter — lets each fresh candidate list be consumed from
72
+ // its best (index-0) member; a counter would permanently skip index 0 of every list after the first.
73
+ const triedMembers = new Set();
55
74
  let dialTarget;
56
75
  let steps = 0;
57
- let probeFollowedPromoted = false;
76
+ // True once this walk has followed a `Promoted` redirect outward (either mode). On a subsequent
77
+ // `NoState` the redirect target is cold: a probe backs off (never instantiates), a register
78
+ // re-issues once with `followOn: true` to instantiate the child, then backs off.
79
+ let followedPromoted = false;
80
+ // True once the register path has spent its single `followOn: true` re-issue at the cold child.
81
+ let followOnReissued = false;
58
82
  for (;;) {
59
83
  if (++steps > maxSteps) {
60
84
  // Safety valve: a well-formed tree converges well within this bound. Surface a temporal
61
85
  // back-off rather than spin.
62
86
  return { kind: "retry_later", afterMs: backoffRetryMs(0) };
63
87
  }
64
- const reg = await this.deps.factory.build({ topicId, tier, treeTier: d, bootstrap, probe, appPayload });
88
+ const reg = await this.deps.factory.build({ topicId, tier, treeTier: d, bootstrap, followOn, probe, appPayload });
65
89
  const activity = encodeCohortMessage(reg, this.maxMessageBytes);
66
90
  const raw = dialTarget !== undefined
67
91
  ? await this.deps.router.dialMember(dialTarget, activity)
@@ -72,16 +96,30 @@ class RouterWalkEngine {
72
96
  const reply = decodeRegisterReplyV1(raw, this.maxMessageBytes);
73
97
  switch (reply.result) {
74
98
  case "accepted": {
75
- return { kind: "accepted", reply };
99
+ // Surface the accepted probe's correlationId so the participant's renewals can echo it
100
+ // (RenewV1 correlationId "matches original RegisterV1"). `reg` is the frame just admitted.
101
+ return { kind: "accepted", reply, correlationId: reg.correlationId };
76
102
  }
77
103
  case "no_state": {
78
104
  // Step toward the root. The cohort served nothing here; no spatial sibling state.
79
105
  dialTarget = undefined;
80
- memberAttempts = 0;
81
- if (probe && probeFollowedPromoted) {
82
- // The promoted child is cold (not yet instantiated). A probe never instantiates it,
83
- // so back off immediately walking inward to the promoting ancestor would just
84
- // re-trigger the Promoted redirect and loop.
106
+ triedMembers.clear(); // a spatial move to a new coord starts sibling retries fresh
107
+ if (followedPromoted) {
108
+ // The `Promoted` redirect target is cold (not yet instantiated). Walking inward to the
109
+ // promoting ancestor would just re-trigger the redirect and oscillate, so handle it here.
110
+ if (probe) {
111
+ // A probe never instantiates — back off immediately (mirror of the register re-issue).
112
+ return { kind: "retry_later", afterMs: backoffRetryMs(0) };
113
+ }
114
+ if (!followOnReissued) {
115
+ // Re-issue ONCE at the SAME child tier as a follow-on cold-start: RegisterV1{ followOn:
116
+ // true } + minted evidence. The mirror of the root NoState → bootstrap:true re-issue.
117
+ followOn = true;
118
+ followOnReissued = true;
119
+ break; // re-register at the same coord/tier, now carrying followOn
120
+ }
121
+ // The follow-on re-issue still got NoState → the cold child's quorum is unwilling to
122
+ // instantiate. Back off in time; do NOT loop inward.
85
123
  return { kind: "retry_later", afterMs: backoffRetryMs(0) };
86
124
  }
87
125
  const next = d - 1;
@@ -107,12 +145,30 @@ class RouterWalkEngine {
107
145
  }
108
146
  case "promoted": {
109
147
  dialTarget = undefined;
110
- memberAttempts = 0;
148
+ triedMembers.clear(); // spatial move to the redirect target: sibling retries start fresh
111
149
  bootstrap = false;
112
150
  const targetTier = reply.targetTier ?? d + 1;
113
- if (probe) {
114
- probeFollowedPromoted = true;
151
+ // The cohort names the tier to jump outward to. When it supplied `targetTier` EXPLICITLY it is
152
+ // untrusted: an out-of-range value would reach `coord()` → `coordD` and throw a raw RangeError,
153
+ // an unclassified crash out of register()/lookup() rather than a clean outcome. Bound it before
154
+ // BOTH adoption sites (the followPromoted-false surface below and the `d = targetTier` hop) and
155
+ // back off in time instead. Only the EXPLICIT attacker value is the hazard; the `d + 1`
156
+ // fallback is left unchecked because `d` is walk-bounded to `dMax + maxSteps` (≈190 under the
157
+ // default `maxSteps`), comfortably under coordD's 255 range.
158
+ // NOTE: `maxSteps` is operator-configurable — a value above ~195 plus an adversarial chain of
159
+ // no-`targetTier` `promoted` replies (each bumps `d` by +1) could push the `d + 1` fallback
160
+ // past coordD's range and reintroduce the RangeError. If maxSteps is ever raised that high,
161
+ // bound the fallback here too.
162
+ if (reply.targetTier !== undefined && !isValidTreeTier(targetTier)) {
163
+ return { kind: "retry_later", afterMs: backoffRetryMs(0) };
115
164
  }
165
+ // Following a (fresh) redirect: mark it, and reset the follow-on latch so a cold child at
166
+ // THIS target gets its own single follow-on re-issue. The honest flow re-registers the
167
+ // child with a PLAIN frame first (followOn false) and only escalates to followOn on its
168
+ // NoState — so clear the flag here; the NoState branch re-arms it.
169
+ followedPromoted = true;
170
+ followOn = false;
171
+ followOnReissued = false;
116
172
  if (!this.followPromoted) {
117
173
  return { kind: "promoted", targetTier };
118
174
  }
@@ -121,14 +177,18 @@ class RouterWalkEngine {
121
177
  }
122
178
  case "unwilling_member": {
123
179
  const candidates = reply.candidateMembers ?? [];
124
- if (candidates.length === 0 || memberAttempts >= this.maxMemberRetries) {
125
- // Exhausted the named siblings (or none offered) fall through to a cohort-level
126
- // temporal back-off, restarting at d_max on the caller's retry.
180
+ // Consume this (possibly fresh) list from its best (index-0) member: pick the FIRST
181
+ // candidate not already dialed on this walk. A positional `memberAttempts % len` offset
182
+ // would skip index 0 of every list after the first, permanently starving the best member.
183
+ const next = candidates.find((c) => !triedMembers.has(c));
184
+ if (next === undefined || triedMembers.size >= this.maxMemberRetries) {
185
+ // No untried candidate offered (or the retry cap is spent) → fall through to a
186
+ // cohort-level temporal back-off, restarting at d_max on the caller's retry.
127
187
  return { kind: "retry_later", afterMs: backoffRetryMs(0) };
128
188
  }
129
189
  // Retry the SAME coord at a named alternative member (spatial move within the cohort).
130
- dialTarget = { id: b64urlToBytes(candidates[memberAttempts % candidates.length]) };
131
- memberAttempts++;
190
+ triedMembers.add(next);
191
+ dialTarget = { id: b64urlToBytes(next) };
132
192
  break;
133
193
  }
134
194
  case "unwilling_cohort": {
@@ -1 +1 @@
1
- {"version":3,"file":"walk.js","sourceRoot":"","sources":["../../../src/cohort-topic/walk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"walk.js","sourceRoot":"","sources":["../../../src/cohort-topic/walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AA4G5F;;;;;GAKG;AACH,SAAS,eAAe,CAAC,KAAa;IACrC,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,iBAAiB,CAAC;AAC5E,CAAC;AAED,MAAM,gBAAgB;IAQQ;IAPZ,KAAK,CAAS;IACd,OAAO,CAAS;IAChB,gBAAgB,CAAS;IACzB,cAAc,CAAU;IACxB,kBAAkB,CAAU;IAC5B,eAAe,CAAU;IAE1C,YAA6B,IAAoB;QAApB,SAAI,GAAJ,IAAI,CAAgB;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC,KAAK,CAAC;QAC3D,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC;QACjD,IAAI,CAAC,kBAAkB,GAAG,GAAG,CAAC,QAAQ,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC,eAAe,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAmB,EAAE,IAAY,EAAE,UAAuB,EAAE,IAA0B;QACpG,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QACvF,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC;QAEnC,IAAI,CAAC,GAAG,IAAI,CAAC;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,kGAAkG;QAClG,kGAAkG;QAClG,qGAAqG;QACrG,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QACvC,IAAI,UAA+B,CAAC;QACpC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,gGAAgG;QAChG,4FAA4F;QAC5F,iFAAiF;QACjF,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,gGAAgG;QAChG,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAE7B,SAAS,CAAC;YACT,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,CAAC;gBACxB,wFAAwF;gBACxF,6BAA6B;gBAC7B,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;YAClH,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,UAAU,KAAK,SAAS;gBACnC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC;gBACzD,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE;oBACtG,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,OAAO,EAAE,IAAI,CAAC,OAAO;iBACrB,CAAC,CAAC;YACJ,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YAE/D,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;gBACtB,KAAK,UAAU,CAAC,CAAC,CAAC;oBACjB,uFAAuF;oBACvF,2FAA2F;oBAC3F,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC;gBACtE,CAAC;gBACD,KAAK,UAAU,CAAC,CAAC,CAAC;oBACjB,kFAAkF;oBAClF,UAAU,GAAG,SAAS,CAAC;oBACvB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,6DAA6D;oBACnF,IAAI,gBAAgB,EAAE,CAAC;wBACtB,uFAAuF;wBACvF,0FAA0F;wBAC1F,IAAI,KAAK,EAAE,CAAC;4BACX,uFAAuF;4BACvF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC5D,CAAC;wBACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;4BACvB,wFAAwF;4BACxF,sFAAsF;4BACtF,QAAQ,GAAG,IAAI,CAAC;4BAChB,gBAAgB,GAAG,IAAI,CAAC;4BACxB,MAAM,CAAC,4DAA4D;wBACpE,CAAC;wBACD,qFAAqF;wBACrF,qDAAqD;wBACrD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5D,CAAC;oBACD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;oBACnB,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;wBACd,IAAI,SAAS,EAAE,CAAC;4BACf,6EAA6E;4BAC7E,yDAAyD;4BACzD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC5D,CAAC;wBACD,IAAI,KAAK,EAAE,CAAC;4BACX,iFAAiF;4BACjF,6EAA6E;4BAC7E,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC5D,CAAC;wBACD,mFAAmF;wBACnF,CAAC,GAAG,CAAC,CAAC;wBACN,SAAS,GAAG,IAAI,CAAC;wBACjB,MAAM;oBACP,CAAC;oBACD,CAAC,GAAG,IAAI,CAAC;oBACT,SAAS,GAAG,KAAK,CAAC;oBAClB,MAAM;gBACP,CAAC;gBACD,KAAK,UAAU,CAAC,CAAC,CAAC;oBACjB,UAAU,GAAG,SAAS,CAAC;oBACvB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,mEAAmE;oBACzF,SAAS,GAAG,KAAK,CAAC;oBAClB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC;oBAC7C,+FAA+F;oBAC/F,gGAAgG;oBAChG,gGAAgG;oBAChG,gGAAgG;oBAChG,wFAAwF;oBACxF,8FAA8F;oBAC9F,6DAA6D;oBAC7D,8FAA8F;oBAC9F,4FAA4F;oBAC5F,4FAA4F;oBAC5F,+BAA+B;oBAC/B,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;wBACpE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5D,CAAC;oBACD,0FAA0F;oBAC1F,uFAAuF;oBACvF,wFAAwF;oBACxF,mEAAmE;oBACnE,gBAAgB,GAAG,IAAI,CAAC;oBACxB,QAAQ,GAAG,KAAK,CAAC;oBACjB,gBAAgB,GAAG,KAAK,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;wBAC1B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;oBACzC,CAAC;oBACD,CAAC,GAAG,UAAU,CAAC,CAAC,gEAAgE;oBAChF,MAAM;gBACP,CAAC;gBACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;oBACzB,MAAM,UAAU,GAAG,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC;oBAChD,oFAAoF;oBACpF,wFAAwF;oBACxF,0FAA0F;oBAC1F,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC1D,IAAI,IAAI,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBACtE,+EAA+E;wBAC/E,6EAA6E;wBAC7E,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5D,CAAC;oBACD,uFAAuF;oBACvF,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACvB,UAAU,GAAG,EAAE,EAAE,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzC,MAAM;gBACP,CAAC;gBACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;oBACzB,mFAAmF;oBACnF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,YAAY,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClF,CAAC;gBACD,OAAO,CAAC,CAAC,CAAC;oBACT,sFAAsF;oBACtF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;CACD;AAED,qGAAqG;AACrG,MAAM,UAAU,gBAAgB,CAAC,IAAoB;IACpD,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}