@optimystic/db-core 0.13.4 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (447) hide show
  1. package/dist/src/cluster/structs.d.ts +29 -0
  2. package/dist/src/cluster/structs.d.ts.map +1 -1
  3. package/dist/src/cohort-topic/addressing.d.ts +53 -0
  4. package/dist/src/cohort-topic/addressing.d.ts.map +1 -0
  5. package/dist/src/cohort-topic/addressing.js +95 -0
  6. package/dist/src/cohort-topic/addressing.js.map +1 -0
  7. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts +105 -0
  8. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts.map +1 -0
  9. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js +197 -0
  10. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js.map +1 -0
  11. package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts +50 -0
  12. package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts.map +1 -0
  13. package/dist/src/cohort-topic/antidos/bootstrap-evidence.js +62 -0
  14. package/dist/src/cohort-topic/antidos/bootstrap-evidence.js.map +1 -0
  15. package/dist/src/cohort-topic/antidos/index.d.ts +6 -0
  16. package/dist/src/cohort-topic/antidos/index.d.ts.map +1 -0
  17. package/dist/src/cohort-topic/antidos/index.js +6 -0
  18. package/dist/src/cohort-topic/antidos/index.js.map +1 -0
  19. package/dist/src/cohort-topic/antidos/rate-limiter.d.ts +95 -0
  20. package/dist/src/cohort-topic/antidos/rate-limiter.d.ts.map +1 -0
  21. package/dist/src/cohort-topic/antidos/rate-limiter.js +146 -0
  22. package/dist/src/cohort-topic/antidos/rate-limiter.js.map +1 -0
  23. package/dist/src/cohort-topic/antidos/replay-guard.d.ts +37 -0
  24. package/dist/src/cohort-topic/antidos/replay-guard.d.ts.map +1 -0
  25. package/dist/src/cohort-topic/antidos/replay-guard.js +78 -0
  26. package/dist/src/cohort-topic/antidos/replay-guard.js.map +1 -0
  27. package/dist/src/cohort-topic/antidos/topic-budget.d.ts +50 -0
  28. package/dist/src/cohort-topic/antidos/topic-budget.d.ts.map +1 -0
  29. package/dist/src/cohort-topic/antidos/topic-budget.js +95 -0
  30. package/dist/src/cohort-topic/antidos/topic-budget.js.map +1 -0
  31. package/dist/src/cohort-topic/antiflood/index.d.ts +3 -0
  32. package/dist/src/cohort-topic/antiflood/index.d.ts.map +1 -0
  33. package/dist/src/cohort-topic/antiflood/index.js +3 -0
  34. package/dist/src/cohort-topic/antiflood/index.js.map +1 -0
  35. package/dist/src/cohort-topic/antiflood/invariants.d.ts +70 -0
  36. package/dist/src/cohort-topic/antiflood/invariants.d.ts.map +1 -0
  37. package/dist/src/cohort-topic/antiflood/invariants.js +86 -0
  38. package/dist/src/cohort-topic/antiflood/invariants.js.map +1 -0
  39. package/dist/src/cohort-topic/antiflood/jitter.d.ts +65 -0
  40. package/dist/src/cohort-topic/antiflood/jitter.d.ts.map +1 -0
  41. package/dist/src/cohort-topic/antiflood/jitter.js +75 -0
  42. package/dist/src/cohort-topic/antiflood/jitter.js.map +1 -0
  43. package/dist/src/cohort-topic/coldstart.d.ts +117 -0
  44. package/dist/src/cohort-topic/coldstart.d.ts.map +1 -0
  45. package/dist/src/cohort-topic/coldstart.js +127 -0
  46. package/dist/src/cohort-topic/coldstart.js.map +1 -0
  47. package/dist/src/cohort-topic/dmax.d.ts +44 -0
  48. package/dist/src/cohort-topic/dmax.d.ts.map +1 -0
  49. package/dist/src/cohort-topic/dmax.js +70 -0
  50. package/dist/src/cohort-topic/dmax.js.map +1 -0
  51. package/dist/src/cohort-topic/gossip/bus.d.ts +85 -0
  52. package/dist/src/cohort-topic/gossip/bus.d.ts.map +1 -0
  53. package/dist/src/cohort-topic/gossip/bus.js +146 -0
  54. package/dist/src/cohort-topic/gossip/bus.js.map +1 -0
  55. package/dist/src/cohort-topic/gossip/index.d.ts +4 -0
  56. package/dist/src/cohort-topic/gossip/index.d.ts.map +1 -0
  57. package/dist/src/cohort-topic/gossip/index.js +4 -0
  58. package/dist/src/cohort-topic/gossip/index.js.map +1 -0
  59. package/dist/src/cohort-topic/gossip/records.d.ts +12 -0
  60. package/dist/src/cohort-topic/gossip/records.d.ts.map +1 -0
  61. package/dist/src/cohort-topic/gossip/records.js +41 -0
  62. package/dist/src/cohort-topic/gossip/records.js.map +1 -0
  63. package/dist/src/cohort-topic/gossip/view.d.ts +39 -0
  64. package/dist/src/cohort-topic/gossip/view.d.ts.map +1 -0
  65. package/dist/src/cohort-topic/gossip/view.js +30 -0
  66. package/dist/src/cohort-topic/gossip/view.js.map +1 -0
  67. package/dist/src/cohort-topic/index.d.ts +21 -0
  68. package/dist/src/cohort-topic/index.d.ts.map +1 -0
  69. package/dist/src/cohort-topic/index.js +21 -0
  70. package/dist/src/cohort-topic/index.js.map +1 -0
  71. package/dist/src/cohort-topic/load/barometer.d.ts +78 -0
  72. package/dist/src/cohort-topic/load/barometer.d.ts.map +1 -0
  73. package/dist/src/cohort-topic/load/barometer.js +93 -0
  74. package/dist/src/cohort-topic/load/barometer.js.map +1 -0
  75. package/dist/src/cohort-topic/load/index.d.ts +2 -0
  76. package/dist/src/cohort-topic/load/index.d.ts.map +1 -0
  77. package/dist/src/cohort-topic/load/index.js +2 -0
  78. package/dist/src/cohort-topic/load/index.js.map +1 -0
  79. package/dist/src/cohort-topic/member-engine.d.ts +134 -0
  80. package/dist/src/cohort-topic/member-engine.d.ts.map +1 -0
  81. package/dist/src/cohort-topic/member-engine.js +264 -0
  82. package/dist/src/cohort-topic/member-engine.js.map +1 -0
  83. package/dist/src/cohort-topic/membership/index.d.ts +4 -0
  84. package/dist/src/cohort-topic/membership/index.d.ts.map +1 -0
  85. package/dist/src/cohort-topic/membership/index.js +4 -0
  86. package/dist/src/cohort-topic/membership/index.js.map +1 -0
  87. package/dist/src/cohort-topic/membership/publisher.d.ts +82 -0
  88. package/dist/src/cohort-topic/membership/publisher.d.ts.map +1 -0
  89. package/dist/src/cohort-topic/membership/publisher.js +107 -0
  90. package/dist/src/cohort-topic/membership/publisher.js.map +1 -0
  91. package/dist/src/cohort-topic/membership/source.d.ts +31 -0
  92. package/dist/src/cohort-topic/membership/source.d.ts.map +1 -0
  93. package/dist/src/cohort-topic/membership/source.js +32 -0
  94. package/dist/src/cohort-topic/membership/source.js.map +1 -0
  95. package/dist/src/cohort-topic/membership/verifier.d.ts +96 -0
  96. package/dist/src/cohort-topic/membership/verifier.d.ts.map +1 -0
  97. package/dist/src/cohort-topic/membership/verifier.js +250 -0
  98. package/dist/src/cohort-topic/membership/verifier.js.map +1 -0
  99. package/dist/src/cohort-topic/ports.d.ts +149 -0
  100. package/dist/src/cohort-topic/ports.d.ts.map +1 -0
  101. package/dist/src/cohort-topic/ports.js +25 -0
  102. package/dist/src/cohort-topic/ports.js.map +1 -0
  103. package/dist/src/cohort-topic/promotion.d.ts +135 -0
  104. package/dist/src/cohort-topic/promotion.d.ts.map +1 -0
  105. package/dist/src/cohort-topic/promotion.js +269 -0
  106. package/dist/src/cohort-topic/promotion.js.map +1 -0
  107. package/dist/src/cohort-topic/registration/bytes.d.ts +16 -0
  108. package/dist/src/cohort-topic/registration/bytes.d.ts.map +1 -0
  109. package/dist/src/cohort-topic/registration/bytes.js +32 -0
  110. package/dist/src/cohort-topic/registration/bytes.js.map +1 -0
  111. package/dist/src/cohort-topic/registration/handoff.d.ts +69 -0
  112. package/dist/src/cohort-topic/registration/handoff.d.ts.map +1 -0
  113. package/dist/src/cohort-topic/registration/handoff.js +98 -0
  114. package/dist/src/cohort-topic/registration/handoff.js.map +1 -0
  115. package/dist/src/cohort-topic/registration/index.d.ts +7 -0
  116. package/dist/src/cohort-topic/registration/index.d.ts.map +1 -0
  117. package/dist/src/cohort-topic/registration/index.js +7 -0
  118. package/dist/src/cohort-topic/registration/index.js.map +1 -0
  119. package/dist/src/cohort-topic/registration/renewal.d.ts +115 -0
  120. package/dist/src/cohort-topic/registration/renewal.d.ts.map +1 -0
  121. package/dist/src/cohort-topic/registration/renewal.js +306 -0
  122. package/dist/src/cohort-topic/registration/renewal.js.map +1 -0
  123. package/dist/src/cohort-topic/registration/sharding.d.ts +31 -0
  124. package/dist/src/cohort-topic/registration/sharding.d.ts.map +1 -0
  125. package/dist/src/cohort-topic/registration/sharding.js +48 -0
  126. package/dist/src/cohort-topic/registration/sharding.js.map +1 -0
  127. package/dist/src/cohort-topic/registration/store.d.ts +13 -0
  128. package/dist/src/cohort-topic/registration/store.d.ts.map +1 -0
  129. package/dist/src/cohort-topic/registration/store.js +72 -0
  130. package/dist/src/cohort-topic/registration/store.js.map +1 -0
  131. package/dist/src/cohort-topic/registration/types.d.ts +71 -0
  132. package/dist/src/cohort-topic/registration/types.d.ts.map +1 -0
  133. package/dist/src/cohort-topic/registration/types.js +27 -0
  134. package/dist/src/cohort-topic/registration/types.js.map +1 -0
  135. package/dist/src/cohort-topic/ring-hash.d.ts +27 -0
  136. package/dist/src/cohort-topic/ring-hash.d.ts.map +1 -0
  137. package/dist/src/cohort-topic/ring-hash.js +45 -0
  138. package/dist/src/cohort-topic/ring-hash.js.map +1 -0
  139. package/dist/src/cohort-topic/service.d.ts +157 -0
  140. package/dist/src/cohort-topic/service.d.ts.map +1 -0
  141. package/dist/src/cohort-topic/service.js +237 -0
  142. package/dist/src/cohort-topic/service.js.map +1 -0
  143. package/dist/src/cohort-topic/sig/index.d.ts +3 -0
  144. package/dist/src/cohort-topic/sig/index.d.ts.map +1 -0
  145. package/dist/src/cohort-topic/sig/index.js +3 -0
  146. package/dist/src/cohort-topic/sig/index.js.map +1 -0
  147. package/dist/src/cohort-topic/sig/payloads.d.ts +25 -0
  148. package/dist/src/cohort-topic/sig/payloads.d.ts.map +1 -0
  149. package/dist/src/cohort-topic/sig/payloads.js +25 -0
  150. package/dist/src/cohort-topic/sig/payloads.js.map +1 -0
  151. package/dist/src/cohort-topic/sig/threshold.d.ts +33 -0
  152. package/dist/src/cohort-topic/sig/threshold.d.ts.map +1 -0
  153. package/dist/src/cohort-topic/sig/threshold.js +51 -0
  154. package/dist/src/cohort-topic/sig/threshold.js.map +1 -0
  155. package/dist/src/cohort-topic/tiers.d.ts +58 -0
  156. package/dist/src/cohort-topic/tiers.d.ts.map +1 -0
  157. package/dist/src/cohort-topic/tiers.js +49 -0
  158. package/dist/src/cohort-topic/tiers.js.map +1 -0
  159. package/dist/src/cohort-topic/traffic.d.ts +90 -0
  160. package/dist/src/cohort-topic/traffic.d.ts.map +1 -0
  161. package/dist/src/cohort-topic/traffic.js +146 -0
  162. package/dist/src/cohort-topic/traffic.js.map +1 -0
  163. package/dist/src/cohort-topic/walk.d.ts +123 -0
  164. package/dist/src/cohort-topic/walk.d.ts.map +1 -0
  165. package/dist/src/cohort-topic/walk.js +150 -0
  166. package/dist/src/cohort-topic/walk.js.map +1 -0
  167. package/dist/src/cohort-topic/willingness.d.ts +123 -0
  168. package/dist/src/cohort-topic/willingness.d.ts.map +1 -0
  169. package/dist/src/cohort-topic/willingness.js +143 -0
  170. package/dist/src/cohort-topic/willingness.js.map +1 -0
  171. package/dist/src/cohort-topic/wire/codec.d.ts +42 -0
  172. package/dist/src/cohort-topic/wire/codec.d.ts.map +1 -0
  173. package/dist/src/cohort-topic/wire/codec.js +163 -0
  174. package/dist/src/cohort-topic/wire/codec.js.map +1 -0
  175. package/dist/src/cohort-topic/wire/index.d.ts +6 -0
  176. package/dist/src/cohort-topic/wire/index.d.ts.map +1 -0
  177. package/dist/src/cohort-topic/wire/index.js +6 -0
  178. package/dist/src/cohort-topic/wire/index.js.map +1 -0
  179. package/dist/src/cohort-topic/wire/payloads.d.ts +38 -0
  180. package/dist/src/cohort-topic/wire/payloads.d.ts.map +1 -0
  181. package/dist/src/cohort-topic/wire/payloads.js +102 -0
  182. package/dist/src/cohort-topic/wire/payloads.js.map +1 -0
  183. package/dist/src/cohort-topic/wire/types.d.ts +304 -0
  184. package/dist/src/cohort-topic/wire/types.d.ts.map +1 -0
  185. package/dist/src/cohort-topic/wire/types.js +16 -0
  186. package/dist/src/cohort-topic/wire/types.js.map +1 -0
  187. package/dist/src/cohort-topic/wire/validate.d.ts +25 -0
  188. package/dist/src/cohort-topic/wire/validate.d.ts.map +1 -0
  189. package/dist/src/cohort-topic/wire/validate.js +427 -0
  190. package/dist/src/cohort-topic/wire/validate.js.map +1 -0
  191. package/dist/src/collection/collection.d.ts +58 -1
  192. package/dist/src/collection/collection.d.ts.map +1 -1
  193. package/dist/src/collection/collection.js +76 -0
  194. package/dist/src/collection/collection.js.map +1 -1
  195. package/dist/src/collections/tree/tree.d.ts +58 -2
  196. package/dist/src/collections/tree/tree.d.ts.map +1 -1
  197. package/dist/src/collections/tree/tree.js +59 -2
  198. package/dist/src/collections/tree/tree.js.map +1 -1
  199. package/dist/src/index.d.ts +3 -0
  200. package/dist/src/index.d.ts.map +1 -1
  201. package/dist/src/index.js +3 -0
  202. package/dist/src/index.js.map +1 -1
  203. package/dist/src/log/log.d.ts +42 -4
  204. package/dist/src/log/log.d.ts.map +1 -1
  205. package/dist/src/log/log.js +71 -3
  206. package/dist/src/log/log.js.map +1 -1
  207. package/dist/src/log/struct.d.ts +122 -2
  208. package/dist/src/log/struct.d.ts.map +1 -1
  209. package/dist/src/log/struct.js.map +1 -1
  210. package/dist/src/matchmaking/capability-filter.d.ts +24 -0
  211. package/dist/src/matchmaking/capability-filter.d.ts.map +1 -0
  212. package/dist/src/matchmaking/capability-filter.js +37 -0
  213. package/dist/src/matchmaking/capability-filter.js.map +1 -0
  214. package/dist/src/matchmaking/config.d.ts +77 -0
  215. package/dist/src/matchmaking/config.d.ts.map +1 -0
  216. package/dist/src/matchmaking/config.js +69 -0
  217. package/dist/src/matchmaking/config.js.map +1 -0
  218. package/dist/src/matchmaking/index.d.ts +21 -0
  219. package/dist/src/matchmaking/index.d.ts.map +1 -0
  220. package/dist/src/matchmaking/index.js +21 -0
  221. package/dist/src/matchmaking/index.js.map +1 -0
  222. package/dist/src/matchmaking/multi-cohort-seeker.d.ts +133 -0
  223. package/dist/src/matchmaking/multi-cohort-seeker.d.ts.map +1 -0
  224. package/dist/src/matchmaking/multi-cohort-seeker.js +142 -0
  225. package/dist/src/matchmaking/multi-cohort-seeker.js.map +1 -0
  226. package/dist/src/matchmaking/provider.d.ts +70 -0
  227. package/dist/src/matchmaking/provider.d.ts.map +1 -0
  228. package/dist/src/matchmaking/provider.js +93 -0
  229. package/dist/src/matchmaking/provider.js.map +1 -0
  230. package/dist/src/matchmaking/query-eval.d.ts +53 -0
  231. package/dist/src/matchmaking/query-eval.d.ts.map +1 -0
  232. package/dist/src/matchmaking/query-eval.js +69 -0
  233. package/dist/src/matchmaking/query-eval.js.map +1 -0
  234. package/dist/src/matchmaking/seeker-walk.d.ts +95 -0
  235. package/dist/src/matchmaking/seeker-walk.d.ts.map +1 -0
  236. package/dist/src/matchmaking/seeker-walk.js +75 -0
  237. package/dist/src/matchmaking/seeker-walk.js.map +1 -0
  238. package/dist/src/matchmaking/seeker.d.ts +51 -0
  239. package/dist/src/matchmaking/seeker.d.ts.map +1 -0
  240. package/dist/src/matchmaking/seeker.js +62 -0
  241. package/dist/src/matchmaking/seeker.js.map +1 -0
  242. package/dist/src/matchmaking/topic-anchor.d.ts +54 -0
  243. package/dist/src/matchmaking/topic-anchor.d.ts.map +1 -0
  244. package/dist/src/matchmaking/topic-anchor.js +67 -0
  245. package/dist/src/matchmaking/topic-anchor.js.map +1 -0
  246. package/dist/src/matchmaking/voting-quorum.d.ts +233 -0
  247. package/dist/src/matchmaking/voting-quorum.d.ts.map +1 -0
  248. package/dist/src/matchmaking/voting-quorum.js +238 -0
  249. package/dist/src/matchmaking/voting-quorum.js.map +1 -0
  250. package/dist/src/matchmaking/wire.d.ts +259 -0
  251. package/dist/src/matchmaking/wire.d.ts.map +1 -0
  252. package/dist/src/matchmaking/wire.js +484 -0
  253. package/dist/src/matchmaking/wire.js.map +1 -0
  254. package/dist/src/network/i-repo.d.ts +19 -0
  255. package/dist/src/network/i-repo.d.ts.map +1 -1
  256. package/dist/src/network/repo-protocol.d.ts +3 -1
  257. package/dist/src/network/repo-protocol.d.ts.map +1 -1
  258. package/dist/src/network/struct.d.ts +23 -1
  259. package/dist/src/network/struct.d.ts.map +1 -1
  260. package/dist/src/reactivity/backfill.d.ts +118 -0
  261. package/dist/src/reactivity/backfill.d.ts.map +1 -0
  262. package/dist/src/reactivity/backfill.js +137 -0
  263. package/dist/src/reactivity/backfill.js.map +1 -0
  264. package/dist/src/reactivity/backpressure.d.ts +99 -0
  265. package/dist/src/reactivity/backpressure.d.ts.map +1 -0
  266. package/dist/src/reactivity/backpressure.js +153 -0
  267. package/dist/src/reactivity/backpressure.js.map +1 -0
  268. package/dist/src/reactivity/checkpoint.d.ts +165 -0
  269. package/dist/src/reactivity/checkpoint.d.ts.map +1 -0
  270. package/dist/src/reactivity/checkpoint.js +232 -0
  271. package/dist/src/reactivity/checkpoint.js.map +1 -0
  272. package/dist/src/reactivity/config.d.ts +131 -0
  273. package/dist/src/reactivity/config.d.ts.map +1 -0
  274. package/dist/src/reactivity/config.js +135 -0
  275. package/dist/src/reactivity/config.js.map +1 -0
  276. package/dist/src/reactivity/dedupe.d.ts +51 -0
  277. package/dist/src/reactivity/dedupe.d.ts.map +1 -0
  278. package/dist/src/reactivity/dedupe.js +90 -0
  279. package/dist/src/reactivity/dedupe.js.map +1 -0
  280. package/dist/src/reactivity/forwarder.d.ts +50 -0
  281. package/dist/src/reactivity/forwarder.d.ts.map +1 -0
  282. package/dist/src/reactivity/forwarder.js +52 -0
  283. package/dist/src/reactivity/forwarder.js.map +1 -0
  284. package/dist/src/reactivity/index.d.ts +34 -0
  285. package/dist/src/reactivity/index.d.ts.map +1 -0
  286. package/dist/src/reactivity/index.js +34 -0
  287. package/dist/src/reactivity/index.js.map +1 -0
  288. package/dist/src/reactivity/notification.d.ts +72 -0
  289. package/dist/src/reactivity/notification.d.ts.map +1 -0
  290. package/dist/src/reactivity/notification.js +92 -0
  291. package/dist/src/reactivity/notification.js.map +1 -0
  292. package/dist/src/reactivity/policy.d.ts +59 -0
  293. package/dist/src/reactivity/policy.d.ts.map +1 -0
  294. package/dist/src/reactivity/policy.js +64 -0
  295. package/dist/src/reactivity/policy.js.map +1 -0
  296. package/dist/src/reactivity/push-state.d.ts +140 -0
  297. package/dist/src/reactivity/push-state.d.ts.map +1 -0
  298. package/dist/src/reactivity/push-state.js +270 -0
  299. package/dist/src/reactivity/push-state.js.map +1 -0
  300. package/dist/src/reactivity/recover.d.ts +75 -0
  301. package/dist/src/reactivity/recover.d.ts.map +1 -0
  302. package/dist/src/reactivity/recover.js +105 -0
  303. package/dist/src/reactivity/recover.js.map +1 -0
  304. package/dist/src/reactivity/replay-buffer.d.ts +57 -0
  305. package/dist/src/reactivity/replay-buffer.d.ts.map +1 -0
  306. package/dist/src/reactivity/replay-buffer.js +88 -0
  307. package/dist/src/reactivity/replay-buffer.js.map +1 -0
  308. package/dist/src/reactivity/resume.d.ts +214 -0
  309. package/dist/src/reactivity/resume.d.ts.map +1 -0
  310. package/dist/src/reactivity/resume.js +358 -0
  311. package/dist/src/reactivity/resume.js.map +1 -0
  312. package/dist/src/reactivity/rotation.d.ts +283 -0
  313. package/dist/src/reactivity/rotation.d.ts.map +1 -0
  314. package/dist/src/reactivity/rotation.js +265 -0
  315. package/dist/src/reactivity/rotation.js.map +1 -0
  316. package/dist/src/reactivity/subscriber.d.ts +66 -0
  317. package/dist/src/reactivity/subscriber.d.ts.map +1 -0
  318. package/dist/src/reactivity/subscriber.js +75 -0
  319. package/dist/src/reactivity/subscriber.js.map +1 -0
  320. package/dist/src/reactivity/subscription.d.ts +52 -0
  321. package/dist/src/reactivity/subscription.d.ts.map +1 -0
  322. package/dist/src/reactivity/subscription.js +28 -0
  323. package/dist/src/reactivity/subscription.js.map +1 -0
  324. package/dist/src/reactivity/topic-anchor.d.ts +46 -0
  325. package/dist/src/reactivity/topic-anchor.d.ts.map +1 -0
  326. package/dist/src/reactivity/topic-anchor.js +61 -0
  327. package/dist/src/reactivity/topic-anchor.js.map +1 -0
  328. package/dist/src/reactivity/verify.d.ts +41 -0
  329. package/dist/src/reactivity/verify.d.ts.map +1 -0
  330. package/dist/src/reactivity/verify.js +48 -0
  331. package/dist/src/reactivity/verify.js.map +1 -0
  332. package/dist/src/reactivity/wire-validate.d.ts +28 -0
  333. package/dist/src/reactivity/wire-validate.d.ts.map +1 -0
  334. package/dist/src/reactivity/wire-validate.js +79 -0
  335. package/dist/src/reactivity/wire-validate.js.map +1 -0
  336. package/dist/src/reactivity/wire.d.ts +102 -0
  337. package/dist/src/reactivity/wire.d.ts.map +1 -0
  338. package/dist/src/reactivity/wire.js +129 -0
  339. package/dist/src/reactivity/wire.js.map +1 -0
  340. package/dist/src/transaction/coordinator.d.ts +9 -5
  341. package/dist/src/transaction/coordinator.d.ts.map +1 -1
  342. package/dist/src/transaction/coordinator.js +48 -25
  343. package/dist/src/transaction/coordinator.js.map +1 -1
  344. package/dist/src/transactor/change-notifier.d.ts +74 -0
  345. package/dist/src/transactor/change-notifier.d.ts.map +1 -0
  346. package/dist/src/transactor/change-notifier.js +4 -0
  347. package/dist/src/transactor/change-notifier.js.map +1 -0
  348. package/dist/src/transactor/index.d.ts +1 -0
  349. package/dist/src/transactor/index.d.ts.map +1 -1
  350. package/dist/src/transactor/index.js +1 -0
  351. package/dist/src/transactor/index.js.map +1 -1
  352. package/dist/src/transactor/network-transactor.d.ts +44 -2
  353. package/dist/src/transactor/network-transactor.d.ts.map +1 -1
  354. package/dist/src/transactor/network-transactor.js +132 -17
  355. package/dist/src/transactor/network-transactor.js.map +1 -1
  356. package/package.json +3 -2
  357. package/src/cluster/structs.ts +86 -57
  358. package/src/cohort-topic/addressing.ts +112 -0
  359. package/src/cohort-topic/antidos/bootstrap-evidence-envelope.ts +253 -0
  360. package/src/cohort-topic/antidos/bootstrap-evidence.ts +94 -0
  361. package/src/cohort-topic/antidos/index.ts +5 -0
  362. package/src/cohort-topic/antidos/rate-limiter.ts +210 -0
  363. package/src/cohort-topic/antidos/replay-guard.ts +109 -0
  364. package/src/cohort-topic/antidos/topic-budget.ts +145 -0
  365. package/src/cohort-topic/antiflood/index.ts +2 -0
  366. package/src/cohort-topic/antiflood/invariants.ts +108 -0
  367. package/src/cohort-topic/antiflood/jitter.ts +117 -0
  368. package/src/cohort-topic/coldstart.ts +204 -0
  369. package/src/cohort-topic/dmax.ts +88 -0
  370. package/src/cohort-topic/gossip/bus.ts +217 -0
  371. package/src/cohort-topic/gossip/index.ts +3 -0
  372. package/src/cohort-topic/gossip/records.ts +45 -0
  373. package/src/cohort-topic/gossip/view.ts +66 -0
  374. package/src/cohort-topic/index.ts +20 -0
  375. package/src/cohort-topic/load/barometer.ts +134 -0
  376. package/src/cohort-topic/load/index.ts +1 -0
  377. package/src/cohort-topic/member-engine.ts +409 -0
  378. package/src/cohort-topic/membership/index.ts +3 -0
  379. package/src/cohort-topic/membership/publisher.ts +171 -0
  380. package/src/cohort-topic/membership/source.ts +41 -0
  381. package/src/cohort-topic/membership/verifier.ts +345 -0
  382. package/src/cohort-topic/ports.ts +157 -0
  383. package/src/cohort-topic/promotion.ts +384 -0
  384. package/src/cohort-topic/registration/bytes.ts +37 -0
  385. package/src/cohort-topic/registration/handoff.ts +154 -0
  386. package/src/cohort-topic/registration/index.ts +6 -0
  387. package/src/cohort-topic/registration/renewal.ts +423 -0
  388. package/src/cohort-topic/registration/sharding.ts +61 -0
  389. package/src/cohort-topic/registration/store.ts +81 -0
  390. package/src/cohort-topic/registration/types.ts +76 -0
  391. package/src/cohort-topic/ring-hash.ts +50 -0
  392. package/src/cohort-topic/service.ts +390 -0
  393. package/src/cohort-topic/sig/index.ts +2 -0
  394. package/src/cohort-topic/sig/payloads.ts +39 -0
  395. package/src/cohort-topic/sig/threshold.ts +64 -0
  396. package/src/cohort-topic/tiers.ts +74 -0
  397. package/src/cohort-topic/traffic.ts +211 -0
  398. package/src/cohort-topic/walk.ts +255 -0
  399. package/src/cohort-topic/willingness.ts +237 -0
  400. package/src/cohort-topic/wire/codec.ts +204 -0
  401. package/src/cohort-topic/wire/index.ts +16 -0
  402. package/src/cohort-topic/wire/payloads.ts +117 -0
  403. package/src/cohort-topic/wire/types.ts +343 -0
  404. package/src/cohort-topic/wire/validate.ts +478 -0
  405. package/src/collection/collection.ts +93 -1
  406. package/src/collections/tree/tree.ts +84 -3
  407. package/src/index.ts +3 -0
  408. package/src/log/log.ts +86 -7
  409. package/src/log/struct.ts +126 -2
  410. package/src/matchmaking/capability-filter.ts +45 -0
  411. package/src/matchmaking/config.ts +98 -0
  412. package/src/matchmaking/index.ts +21 -0
  413. package/src/matchmaking/multi-cohort-seeker.ts +234 -0
  414. package/src/matchmaking/provider.ts +123 -0
  415. package/src/matchmaking/query-eval.ts +105 -0
  416. package/src/matchmaking/seeker-walk.ts +127 -0
  417. package/src/matchmaking/seeker.ts +86 -0
  418. package/src/matchmaking/topic-anchor.ts +90 -0
  419. package/src/matchmaking/voting-quorum.ts +394 -0
  420. package/src/matchmaking/wire.ts +680 -0
  421. package/src/network/i-repo.ts +19 -0
  422. package/src/network/repo-protocol.ts +3 -2
  423. package/src/network/struct.ts +24 -1
  424. package/src/reactivity/backfill.ts +220 -0
  425. package/src/reactivity/backpressure.ts +191 -0
  426. package/src/reactivity/checkpoint.ts +308 -0
  427. package/src/reactivity/config.ts +172 -0
  428. package/src/reactivity/dedupe.ts +132 -0
  429. package/src/reactivity/forwarder.ts +87 -0
  430. package/src/reactivity/index.ts +34 -0
  431. package/src/reactivity/notification.ts +123 -0
  432. package/src/reactivity/policy.ts +79 -0
  433. package/src/reactivity/push-state.ts +343 -0
  434. package/src/reactivity/recover.ts +153 -0
  435. package/src/reactivity/replay-buffer.ts +141 -0
  436. package/src/reactivity/resume.ts +549 -0
  437. package/src/reactivity/rotation.ts +415 -0
  438. package/src/reactivity/subscriber.ts +132 -0
  439. package/src/reactivity/subscription.ts +66 -0
  440. package/src/reactivity/topic-anchor.ts +71 -0
  441. package/src/reactivity/verify.ts +73 -0
  442. package/src/reactivity/wire-validate.ts +87 -0
  443. package/src/reactivity/wire.ts +224 -0
  444. package/src/transaction/coordinator.ts +53 -27
  445. package/src/transactor/change-notifier.ts +80 -0
  446. package/src/transactor/index.ts +1 -0
  447. package/src/transactor/network-transactor.ts +162 -19
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Cohort-topic substrate — capacity barometer.
3
+ *
4
+ * Transcribed from `docs/cohort-topic.md` §Capacity barometer (and folded back from the
5
+ * simulator-validated `packages/substrate-simulator/src/willingness.ts`). A cohort member tracks a
6
+ * coarse **3-bit (0..7) log-bucketed utilization** per tier (T0..T3). The barometer feeds two
7
+ * decisions:
8
+ *
9
+ * 1. **Willingness-bit refresh.** When a tier's bucket reaches `overloadBucket` the member sheds
10
+ * that tier — its load-driven willingness bit flips off until utilization recedes. Siblings see
11
+ * the flip within one gossip round (the bit rides `CohortGossipV1.willingnessBits`).
12
+ * 2. **Early-promote signal.** `bucket ≥ overloadBucket` (default 6, the `bucket_overload` of
13
+ * §Configuration) is the "cohort is hot at this tier" signal the promotion ticket consumes to
14
+ * fire promotion earlier than the strict `cap_promote`. This module only *exposes* the signal;
15
+ * it does not itself promote.
16
+ *
17
+ * The barometer is **not** aggregated across the tree — children promote independently, so a member
18
+ * only ever observes its own per-tier utilization here. The 3-bit buckets (× 4 tiers) plus the
19
+ * willingness bit fit in 16 bits of cohort gossip; the cost is negligible.
20
+ */
21
+ import { ALL_TIERS } from "../tiers.js";
22
+ /**
23
+ * Load-barometer bucket at/above which a member sheds a tier (willingness flips off) and the cohort
24
+ * is considered hot enough to promote early. `bucket_overload` in `docs/cohort-topic.md`
25
+ * §Configuration; simulator-confirmed at 6.
26
+ */
27
+ export const DEFAULT_OVERLOAD_BUCKET = 6;
28
+ /**
29
+ * Map a utilization ratio (`load / capacity`, where `1.0` = at capacity) to a 0..7 log bucket.
30
+ *
31
+ * Each bucket spans a doubling of utilization, anchored so the top of the range is at-capacity:
32
+ *
33
+ * | bucket | utilization range |
34
+ * |--------|-------------------|
35
+ * | 7 | `u ≥ 1.0` |
36
+ * | 6 | `[0.5, 1.0)` |
37
+ * | 5 | `[0.25, 0.5)` |
38
+ * | … | … |
39
+ * | 1 | `[1/64, 1/32)` |
40
+ * | 0 | `u < 1/64` (incl. 0, negative clamped) |
41
+ *
42
+ * Monotonic non-decreasing in `u`; `bucket = clamp(7 + ⌊log₂ u⌋, 0, 7)`. With the default
43
+ * `overloadBucket = 6`, a member sheds a tier once utilization reaches half capacity.
44
+ */
45
+ export function utilizationBucket(utilization) {
46
+ if (!(utilization > 0)) {
47
+ return 0; // zero, negative, or NaN → idle
48
+ }
49
+ const b = 7 + Math.floor(Math.log2(utilization));
50
+ if (b < 0)
51
+ return 0;
52
+ if (b > 7)
53
+ return 7;
54
+ return b;
55
+ }
56
+ class ArrayLoadBarometer {
57
+ buckets = [0, 0, 0, 0];
58
+ overloadBucket;
59
+ constructor(config) {
60
+ const ob = config?.overloadBucket ?? DEFAULT_OVERLOAD_BUCKET;
61
+ if (!Number.isInteger(ob) || ob < 1 || ob > 7) {
62
+ throw new RangeError(`overloadBucket must be an integer in [1, 7], got ${ob}`);
63
+ }
64
+ this.overloadBucket = ob;
65
+ }
66
+ observe(tier, utilization) {
67
+ this.buckets[tier] = utilizationBucket(utilization);
68
+ }
69
+ bucket(tier) {
70
+ return this.buckets[tier];
71
+ }
72
+ reading(tier) {
73
+ return { tier, bucket: this.buckets[tier] };
74
+ }
75
+ loadBuckets() {
76
+ return [...this.buckets];
77
+ }
78
+ isOverloaded(tier) {
79
+ return this.buckets[tier] >= this.overloadBucket;
80
+ }
81
+ loadWilling(tier) {
82
+ return !this.isOverloaded(tier);
83
+ }
84
+ }
85
+ /** Construct an idle (all-bucket-0) {@link LoadBarometerState}. */
86
+ export function createLoadBarometer(config) {
87
+ return new ArrayLoadBarometer(config);
88
+ }
89
+ /** Iterate the four tiers — convenience for callers folding the barometer into a gossip frame. */
90
+ export function eachTier() {
91
+ return ALL_TIERS;
92
+ }
93
+ //# sourceMappingURL=barometer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"barometer.js","sourceRoot":"","sources":["../../../../src/cohort-topic/load/barometer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,SAAS,EAAa,MAAM,aAAa,CAAC;AASnD;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAEzC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACpD,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC,CAAC,gCAAgC;IAC3C,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACpB,OAAO,CAAC,CAAC;AACV,CAAC;AA0BD,MAAM,kBAAkB;IACN,OAAO,GAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,cAAc,CAAS;IAExC,YAAY,MAA4B;QACvC,MAAM,EAAE,GAAG,MAAM,EAAE,cAAc,IAAI,uBAAuB,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,UAAU,CAAC,oDAAoD,EAAE,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO,CAAC,IAAU,EAAE,WAAmB;QACtC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,IAAU;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAE,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,IAAU;QACjB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAE,EAAE,CAAC;IAC9C,CAAC;IAED,WAAW;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,YAAY,CAAC,IAAU;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAE,IAAI,IAAI,CAAC,cAAc,CAAC;IACnD,CAAC;IAED,WAAW,CAAC,IAAU;QACrB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;CACD;AAED,mEAAmE;AACnE,MAAM,UAAU,mBAAmB,CAAC,MAA4B;IAC/D,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,QAAQ;IACvB,OAAO,SAAS,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./barometer.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/load/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./barometer.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cohort-topic/load/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Cohort-topic substrate — cohort-side member engine.
3
+ *
4
+ * This is the logic a cohort member runs when FRET's `RouteAndMaybeAct` lands a `RegisterV1`/`RenewV1`
5
+ * on it (the activity callback in `docs/cohort-topic.md` §FRET integration). It is the cohort-facing
6
+ * half of the substrate, composed from the prereq tickets' pure modules — the participant-facing half
7
+ * lives in {@link import("./service.js").CohortTopicService}. db-p2p's FRET host decodes an inbound
8
+ * frame, supplies the routing context this module can't see (`followOn`, the quorum-willing tally),
9
+ * and serializes whatever reply this returns back over the wire. db-core never imports FRET here.
10
+ *
11
+ * Inbound `RegisterV1` decision pipeline (§Registration mechanics, §Willingness, §Cold-start):
12
+ *
13
+ * 1. **Anti-DoS** — freshness/replay guard, per-(peer,topic) rate limit, and cold-root bootstrap
14
+ * evidence. A failure short-circuits to `unwilling_cohort` (temporal back-off) or, for a replay,
15
+ * a silent `no_state` (no state is served and nothing is recorded).
16
+ * 2. **Hot vs cold** — if this cohort already serves the topic (forwarder state resident), run the
17
+ * willingness check; a promoted topic answers `Promoted(d+1)`. If cold, the topic-budget +
18
+ * cold-start gate decides whether to instantiate, else `no_state` (walk steps toward the root).
19
+ * 3. **Admission** — on `accepted`, assign the deterministic primary/backup slots, persist the
20
+ * soft-state record, count the arrival, run the promotion trigger, and attach the topic-traffic
21
+ * signal to the reply.
22
+ *
23
+ * Every collaborator is injected, so the engine unit-tests without FRET or libp2p.
24
+ */
25
+ import type { IRingHash } from "./ports.js";
26
+ import type { RegistrationRecord, RegistrationStore } from "./registration/types.js";
27
+ import type { SlotAssigner } from "./registration/sharding.js";
28
+ import type { RenewalCohortSide } from "./registration/renewal.js";
29
+ import type { WillingnessCheck } from "./willingness.js";
30
+ import type { PromotionLifecycle } from "./promotion.js";
31
+ import type { ColdStartManager } from "./coldstart.js";
32
+ import type { TrafficCounters } from "./traffic.js";
33
+ import type { RegisterRateLimiter } from "./antidos/rate-limiter.js";
34
+ import type { CorrelationReplayGuard } from "./antidos/replay-guard.js";
35
+ import type { TopicBudget } from "./antidos/topic-budget.js";
36
+ import type { BootstrapEvidence } from "./antidos/bootstrap-evidence.js";
37
+ import type { NodeProfile, Tier } from "./tiers.js";
38
+ import type { DemotionNoticeV1, PromotionNoticeV1, RegisterReplyV1, RegisterV1, RenewReplyV1, RenewV1 } from "./wire/types.js";
39
+ /** Routing context the FRET host supplies for an inbound register (db-core can't derive it). */
40
+ export interface RegisterContext {
41
+ /** Did this register arrive as a follow-on to a parent cohort's `Promoted` redirect? */
42
+ readonly followOn: boolean;
43
+ /** Tree tier `d` this cohort serves the topic at (the walk position the register landed on). */
44
+ readonly treeTier: number;
45
+ /** The tier-`(d − 1)` parent cohort coord, for a cold-start forwarder's parent registration. */
46
+ readonly parentCoord?: Uint8Array;
47
+ }
48
+ /** Current cohort snapshot — the FRET host fills this from the membership source. */
49
+ export interface CohortSnapshotView {
50
+ readonly members: readonly Uint8Array[];
51
+ readonly cohortEpoch: Uint8Array;
52
+ }
53
+ export interface CohortMemberEngineDeps {
54
+ /** This member's own peer id. */
55
+ readonly self: Uint8Array;
56
+ /** This member's static tier profile (Edge/Core willing-tier set). */
57
+ readonly profile: NodeProfile;
58
+ /** Hash used for slot assignment + keys (db-core's own SHA-256). */
59
+ readonly hash: IRingHash;
60
+ /** Replicated soft-state registration store. */
61
+ readonly store: RegistrationStore;
62
+ /** Deterministic primary/backup slot assignment, shared with renewal + handoff. */
63
+ readonly slots: SlotAssigner;
64
+ /** Per-member willingness / admission control. */
65
+ readonly willingness: WillingnessCheck;
66
+ /** Promotion / demotion lifecycle. */
67
+ readonly promotion: PromotionLifecycle;
68
+ /** Cold-start forwarder instantiation + parent registration. */
69
+ readonly coldStart: ColdStartManager;
70
+ /** Per-topic traffic counters (gossip-derived snapshots feed the reply signal). */
71
+ readonly traffic: TrafficCounters;
72
+ /** Cohort-side TTL renewal handler (touch / primary_moved / sweep). */
73
+ readonly renewal: RenewalCohortSide;
74
+ /** Live cohort snapshot (members + epoch). */
75
+ readonly cohort: () => CohortSnapshotView;
76
+ /** Whether a quorum of members is willing to serve `tier` (the cold-start gate input). */
77
+ readonly quorumWilling: (tier: Tier) => boolean;
78
+ readonly rateLimiter?: RegisterRateLimiter;
79
+ /**
80
+ * Dedicated per-(peer, topic) rate limiter for the read-only {@link CohortMemberEngine.handleRegister}
81
+ * **probe** path — its own budget, separate from {@link rateLimiter}, so a probe flood cannot exhaust a
82
+ * participant's register budget (or vice-versa). An over-rate probe answers `unwilling_cohort`
83
+ * (walk → `retry_later` → `CohortBackoffError`). Absent → the probe rate gate is skipped (the read-only
84
+ * classify still runs), keeping key-less / unit / mock flows composing.
85
+ */
86
+ readonly probeRateLimiter?: RegisterRateLimiter;
87
+ readonly replayGuard?: CorrelationReplayGuard;
88
+ readonly topicBudget?: TopicBudget;
89
+ readonly bootstrapEvidence?: BootstrapEvidence;
90
+ /**
91
+ * Optional participant peer-key signature verifier (db-p2p binds it to the peer-sig primitive over
92
+ * {@link import("./wire/payloads.js").registerSigningPayload}). A `RegisterV1` whose signature does
93
+ * not verify against the claimed `participantCoord` is answered `no_state` (serve nothing, record
94
+ * nothing) — a cohort member cannot trust an unsigned/forged `participantCoord`. Verified first so a
95
+ * forged frame never reaches (or pollutes) the replay/rate guards. Absent → the gate is skipped.
96
+ */
97
+ readonly verifyRegisterSig?: (reg: RegisterV1) => boolean;
98
+ /**
99
+ * Sink for a freshly threshold-signed promotion/demotion notice produced on an arrival (the `accept`
100
+ * path's promotion trigger). db-p2p's host wires this to broadcast the notice over the `promote`
101
+ * protocol to the cohort (and, for a demotion, the parent coord). Absent → notices are produced and
102
+ * applied locally but not broadcast (unit/mock flows). Called fire-and-forget, off the reply path.
103
+ */
104
+ readonly onNotice?: (notice: PromotionNoticeV1 | DemotionNoticeV1) => void;
105
+ /**
106
+ * Optional logger. Used only to record a failed promotion sign/broadcast (the threshold-sign round
107
+ * can reject when the cohort quorum is unreachable) rather than swallow it. Absent → silent.
108
+ */
109
+ readonly log?: (formatter: string, ...args: unknown[]) => void;
110
+ /**
111
+ * Sink for a freshly-admitted registration record (the `accept` path), symmetric to the renewal
112
+ * `gossip.touch` hook. db-p2p wires this to the same per-coord gossip delta queue the renewal side
113
+ * appends to, so an admitted record is replicated to the cohort at the next gossip round — closing the
114
+ * durability window between admission and the participant's first renewal touch. A queue append, not a
115
+ * synchronous broadcast: admission must not block on a round, and last-writer-wins by `lastPing` dedupes
116
+ * an admit-then-touch landing in the same round. Absent → no admission-time replication (unit/mock flows
117
+ * that don't exercise gossip).
118
+ */
119
+ readonly onAdmit?: (rec: RegistrationRecord) => void;
120
+ }
121
+ /** Cohort-side register/renew handler — the body of the FRET activity callback. */
122
+ export interface CohortMemberEngine {
123
+ /** Classify and admit (or decline) an inbound `RegisterV1`, returning the reply to serialize. */
124
+ handleRegister(reg: RegisterV1, ctx: RegisterContext, now: number): Promise<RegisterReplyV1>;
125
+ /** Handle an inbound `RenewV1` (ping / re-attach), delegating to the renewal cohort side. */
126
+ handleRenew(msg: RenewV1, now: number): RenewReplyV1;
127
+ /** Evict stale records and gossip each eviction; returns the evicted set. */
128
+ sweepStale(now: number): readonly RegistrationRecord[];
129
+ }
130
+ /** Build a {@link CohortMemberEngine} over the injected cohort-side collaborators. */
131
+ export declare function createCohortMemberEngine(deps: CohortMemberEngineDeps): CohortMemberEngine;
132
+ /** True iff `a` and `b` name the same peer (re-exported convenience for host equality checks). */
133
+ export declare function samePeer(a: Uint8Array, b: Uint8Array): boolean;
134
+ //# sourceMappingURL=member-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member-engine.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/member-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Cohort-topic substrate — cohort-side member engine.
3
+ *
4
+ * This is the logic a cohort member runs when FRET's `RouteAndMaybeAct` lands a `RegisterV1`/`RenewV1`
5
+ * on it (the activity callback in `docs/cohort-topic.md` §FRET integration). It is the cohort-facing
6
+ * half of the substrate, composed from the prereq tickets' pure modules — the participant-facing half
7
+ * lives in {@link import("./service.js").CohortTopicService}. db-p2p's FRET host decodes an inbound
8
+ * frame, supplies the routing context this module can't see (`followOn`, the quorum-willing tally),
9
+ * and serializes whatever reply this returns back over the wire. db-core never imports FRET here.
10
+ *
11
+ * Inbound `RegisterV1` decision pipeline (§Registration mechanics, §Willingness, §Cold-start):
12
+ *
13
+ * 1. **Anti-DoS** — freshness/replay guard, per-(peer,topic) rate limit, and cold-root bootstrap
14
+ * evidence. A failure short-circuits to `unwilling_cohort` (temporal back-off) or, for a replay,
15
+ * a silent `no_state` (no state is served and nothing is recorded).
16
+ * 2. **Hot vs cold** — if this cohort already serves the topic (forwarder state resident), run the
17
+ * willingness check; a promoted topic answers `Promoted(d+1)`. If cold, the topic-budget +
18
+ * cold-start gate decides whether to instantiate, else `no_state` (walk steps toward the root).
19
+ * 3. **Admission** — on `accepted`, assign the deterministic primary/backup slots, persist the
20
+ * soft-state record, count the arrival, run the promotion trigger, and attach the topic-traffic
21
+ * signal to the reply.
22
+ *
23
+ * Every collaborator is injected, so the engine unit-tests without FRET or libp2p.
24
+ */
25
+ import { bytesEqual, bytesKey } from "./registration/bytes.js";
26
+ import { DEFAULT_TTL_MS } from "./registration/types.js";
27
+ import { backoffRetryMs } from "./willingness.js";
28
+ import { promotedRedirectReply } from "./coldstart.js";
29
+ import { shouldInstantiate } from "./coldstart.js";
30
+ import { attachTopicTraffic } from "./traffic.js";
31
+ import { b64urlToBytes } from "./wire/codec.js";
32
+ class StoreCohortMemberEngine {
33
+ deps;
34
+ constructor(deps) {
35
+ this.deps = deps;
36
+ }
37
+ async handleRegister(reg, ctx, now) {
38
+ const topicId = b64urlToBytes(reg.topicId);
39
+ const participantId = b64urlToBytes(reg.participantCoord);
40
+ const tier = reg.tier;
41
+ // 0. Read-only lookup probe: classify + return the cohort snapshot without admitting anything.
42
+ // Branches before the admission pipeline (and the durable-state anti-DoS guards), so even a
43
+ // hand-crafted `probe: true, bootstrap: true` frame can never instantiate — defense in depth.
44
+ if (reg.probe === true) {
45
+ return this.handleProbe(reg, topicId, participantId, ctx, now);
46
+ }
47
+ // 1. Anti-DoS gates. A replay/stale frame is answered with NoState (serve nothing, record
48
+ // nothing); an over-rate source or missing bootstrap evidence backs off in time.
49
+ const guard = this.runGuards(reg, topicId, participantId, tier, now);
50
+ if (guard !== undefined) {
51
+ return guard;
52
+ }
53
+ // 2. Hot path: this cohort already serves the topic.
54
+ if (this.serves(topicId)) {
55
+ if (this.deps.promotion.isPromoted(topicId)) {
56
+ // Promoted: bounce same-tier registrations onward (the cheap single-RPC redirect).
57
+ return promotedRedirectReply(ctx.treeTier + 1, this.deps.traffic.snapshot(topicId));
58
+ }
59
+ return this.admitOrDecline(reg, topicId, participantId, tier, ctx, now);
60
+ }
61
+ // 3. Cold path: instantiate only at a legitimate growth point with a willing quorum.
62
+ const quorumWilling = this.deps.quorumWilling(tier);
63
+ if (!shouldInstantiate({ bootstrap: reg.bootstrap === true, followOn: ctx.followOn, quorumWilling })) {
64
+ return { v: 1, result: "no_state" };
65
+ }
66
+ if (this.deps.topicBudget?.admit(topicId) === false) {
67
+ // Forwarder-state budget is full of populated topics — decline in time.
68
+ return this.unwillingCohort(reg, now);
69
+ }
70
+ this.deps.coldStart.instantiate(topicId, ctx.treeTier, ctx.parentCoord, tier);
71
+ return this.admitOrDecline(reg, topicId, participantId, tier, ctx, now);
72
+ }
73
+ /**
74
+ * Read-only resolution of the cohort for a topic (the `lookup` probe). It walks the same path a
75
+ * register does (the walk loop is byte-for-byte identical) but the **terminal** member action is a
76
+ * classify, never an admission: it persists **no** record, counts **no** arrival, fires **no**
77
+ * promotion trigger, touches **no** topic budget, and **never** instantiates a cold-start forwarder.
78
+ *
79
+ * DoS posture (`docs/cohort-topic.md` §Anti-DoS): a probe still runs the stateless participant-sig gate
80
+ * (forged → `no_state`) and a dedicated probe rate limiter (over-rate → `unwilling_cohort`), but skips
81
+ * the replay guard, the bootstrap-evidence gate, and the topic budget — an idempotent read records
82
+ * nothing, so it is strictly cheaper than the register it replaces.
83
+ *
84
+ * Classification mirrors a register's terminal cases so the walk's existing branches drive a probe
85
+ * unchanged: a served-and-promoted topic answers `promoted(treeTier + 1)` (the walk follows it), a
86
+ * served topic answers `accepted` with the participant-specific slot assignment + read-only traffic
87
+ * snapshot, and a topic this cohort does not serve answers `no_state` (the walk steps inward).
88
+ */
89
+ handleProbe(reg, topicId, participantId, ctx, now) {
90
+ if (this.deps.verifyRegisterSig?.(reg) === false) {
91
+ // Unsigned / forged participant signature: serve nothing, exactly like the register path — a
92
+ // cohort member never resolves a cohort snapshot for an untrusted `participantCoord`.
93
+ return { v: 1, result: "no_state" };
94
+ }
95
+ const rate = this.deps.probeRateLimiter?.check(participantId, topicId, now);
96
+ if (rate !== undefined && rate.ok === false) {
97
+ return { v: 1, result: "unwilling_cohort", retryAfterMs: rate.retryAfterMs };
98
+ }
99
+ if (this.serves(topicId)) {
100
+ if (this.deps.promotion.isPromoted(topicId)) {
101
+ return promotedRedirectReply(ctx.treeTier + 1, this.deps.traffic.snapshot(topicId));
102
+ }
103
+ const { members, cohortEpoch } = this.deps.cohort();
104
+ const { primary, backups } = this.deps.slots.assignSlots(participantId, cohortEpoch, members);
105
+ const reply = {
106
+ v: 1,
107
+ result: "accepted",
108
+ primary: bytesKey(primary),
109
+ backups: backups.map(bytesKey),
110
+ cohortEpoch: bytesKey(cohortEpoch),
111
+ cohortMembers: members.map(bytesKey),
112
+ };
113
+ return attachTopicTraffic(reply, this.deps.traffic.snapshot(topicId));
114
+ }
115
+ return { v: 1, result: "no_state" };
116
+ }
117
+ handleRenew(msg, now) {
118
+ const reply = this.deps.renewal.onRenew(msg, now);
119
+ if (reply.result === "ok") {
120
+ // A renewal is an arrival proxy for the traffic barometer (§Topic traffic signal).
121
+ this.deps.traffic.recordArrival(b64urlToBytes(msg.topicId), now);
122
+ }
123
+ else if (reply.result === "withdrawn") {
124
+ // A withdraw evicted a direct participant: re-touch the topic budget DOWN (mirrors the
125
+ // sweepStale drain release below) so the freed slot does not leak. Never an arrival — it is a
126
+ // departure, so the traffic barometer is deliberately not touched.
127
+ const topicId = b64urlToBytes(msg.topicId);
128
+ this.deps.topicBudget?.touch(topicId, this.deps.store.directParticipants(topicId));
129
+ }
130
+ return reply;
131
+ }
132
+ sweepStale(now) {
133
+ // Reclaim idle (peer, topic) rate-limiter keys on the existing gossip cadence. The limiters' own
134
+ // hard LRU cap already bounds worst-case footprint; this sweep adds proactive steady-state reclaim
135
+ // of long-quiet keys so a long-running coord does not hold register/probe state for departed peers.
136
+ this.deps.rateLimiter?.sweep(now);
137
+ this.deps.probeRateLimiter?.sweep(now);
138
+ const evicted = this.deps.renewal.sweepStale(now);
139
+ const budget = this.deps.topicBudget;
140
+ if (budget !== undefined && evicted.length > 0) {
141
+ // Mirror the `accept()` up-touch on the drain side: a TTL sweep that removes a topic's last
142
+ // direct participant must re-`touch` the budget down so the topic falls to participantCount 0
143
+ // and becomes the coldest-evictable resident again. Without this the budget slot leaks — a
144
+ // drained topic keeps its stale positive count forever and `coldestEvictable()` never picks it,
145
+ // so the cohort eventually refuses every new topic while serving nothing. Re-touch once per
146
+ // distinct affected topic from `store.directParticipants` (the source of truth, post-eviction).
147
+ const seen = new Set();
148
+ for (const rec of evicted) {
149
+ const key = bytesKey(rec.topicId);
150
+ if (seen.has(key))
151
+ continue;
152
+ seen.add(key);
153
+ budget.touch(rec.topicId, this.deps.store.directParticipants(rec.topicId));
154
+ }
155
+ }
156
+ return evicted;
157
+ }
158
+ // --- admission ---
159
+ /** Run the willingness check; on `accepted` persist the record and attach the traffic signal. */
160
+ async admitOrDecline(reg, topicId, participantId, tier, ctx, now) {
161
+ const outcome = this.deps.willingness.evaluate(reg, this.deps.profile, now);
162
+ switch (outcome.kind) {
163
+ case "unwilling_member": {
164
+ return { v: 1, result: "unwilling_member", candidateMembers: outcome.candidateMembers.map(bytesKey) };
165
+ }
166
+ case "unwilling_cohort": {
167
+ return { v: 1, result: "unwilling_cohort", retryAfterMs: outcome.retryAfterMs };
168
+ }
169
+ case "accepted": {
170
+ return this.accept(reg, topicId, participantId, tier, ctx, now);
171
+ }
172
+ default: {
173
+ return this.unwillingCohort(reg, now);
174
+ }
175
+ }
176
+ }
177
+ async accept(reg, topicId, participantId, tier, ctx, now) {
178
+ const { members, cohortEpoch } = this.deps.cohort();
179
+ const { primary, backups } = this.deps.slots.assignSlots(participantId, cohortEpoch, members);
180
+ const ttl = reg.ttl > 0 ? reg.ttl : DEFAULT_TTL_MS;
181
+ const record = {
182
+ topicId,
183
+ participantId,
184
+ tier,
185
+ primary,
186
+ backups,
187
+ attachedAt: now,
188
+ lastPing: now,
189
+ ttl,
190
+ appState: reg.appPayload === undefined ? undefined : b64urlToBytes(reg.appPayload),
191
+ };
192
+ this.deps.store.put(record);
193
+ this.deps.onAdmit?.(record);
194
+ this.deps.traffic.recordArrival(topicId, now);
195
+ this.deps.topicBudget?.touch(topicId, this.deps.store.directParticipants(topicId));
196
+ // Promotion may fire on this arrival; broadcast whatever notice comes back. Fire-and-forget so the
197
+ // register reply is not delayed by the threshold-sign collection round.
198
+ void this.firePromotion(topicId, now);
199
+ const reply = {
200
+ v: 1,
201
+ result: "accepted",
202
+ primary: bytesKey(primary),
203
+ backups: backups.map(bytesKey),
204
+ cohortEpoch: bytesKey(cohortEpoch),
205
+ cohortMembers: members.map(bytesKey),
206
+ };
207
+ return attachTopicTraffic(reply, this.deps.traffic.snapshot(topicId));
208
+ }
209
+ /** Run the promotion trigger for an arrival and hand any signed notice to {@link CohortMemberEngineDeps.onNotice}. */
210
+ async firePromotion(topicId, now) {
211
+ try {
212
+ const notice = await this.deps.promotion.onParticipantCountChange(topicId, now);
213
+ if (notice !== undefined) {
214
+ this.deps.onNotice?.(notice);
215
+ }
216
+ }
217
+ catch (err) {
218
+ // Threshold signing rejects when the cohort quorum is unreachable this round; the next arrival
219
+ // re-fires, so this is transient. Log rather than crash the register path — or leak the
220
+ // unhandled rejection the bare `void promotion...` did once signing became real (db-p2p ticket 1).
221
+ this.deps.log?.("cohort-topic: promotion sign/broadcast failed for an arrival: %o", err);
222
+ }
223
+ }
224
+ // --- guards ---
225
+ /** Returns a short-circuit reply if any anti-DoS gate rejects `reg`, else `undefined`. */
226
+ runGuards(reg, topicId, participantId, tier, now) {
227
+ if (this.deps.verifyRegisterSig?.(reg) === false) {
228
+ // Unsigned / forged participant signature: serve nothing and record nothing (the cohort
229
+ // cannot trust this participantCoord). Checked before the replay/rate guards so a forged
230
+ // frame cannot consume their state.
231
+ return { v: 1, result: "no_state" };
232
+ }
233
+ const correlationId = b64urlToBytes(reg.correlationId);
234
+ if (this.deps.replayGuard?.accept(correlationId, participantId, reg.timestamp, now) === false) {
235
+ // Stale / future-skewed / replayed: serve nothing and record nothing.
236
+ return { v: 1, result: "no_state" };
237
+ }
238
+ if (this.deps.bootstrapEvidence?.verify(reg, tier) === false) {
239
+ return this.unwillingCohort(reg, now);
240
+ }
241
+ const rate = this.deps.rateLimiter?.check(participantId, topicId, now);
242
+ if (rate !== undefined && rate.ok === false) {
243
+ return { v: 1, result: "unwilling_cohort", retryAfterMs: rate.retryAfterMs };
244
+ }
245
+ return undefined;
246
+ }
247
+ serves(topicId) {
248
+ return this.deps.coldStart.get(topicId) !== undefined || this.deps.store.directParticipants(topicId) > 0;
249
+ }
250
+ unwillingCohort(reg, now) {
251
+ void reg;
252
+ void now;
253
+ return { v: 1, result: "unwilling_cohort", retryAfterMs: backoffRetryMs(0) };
254
+ }
255
+ }
256
+ /** Build a {@link CohortMemberEngine} over the injected cohort-side collaborators. */
257
+ export function createCohortMemberEngine(deps) {
258
+ return new StoreCohortMemberEngine(deps);
259
+ }
260
+ /** True iff `a` and `b` name the same peer (re-exported convenience for host equality checks). */
261
+ export function samePeer(a, b) {
262
+ return bytesEqual(a, b);
263
+ }
264
+ //# sourceMappingURL=member-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member-engine.js","sourceRoot":"","sources":["../../../src/cohort-topic/member-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./source.js";
2
+ export * from "./verifier.js";
3
+ export * from "./publisher.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./source.js";
2
+ export * from "./verifier.js";
3
+ export * from "./publisher.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Cohort-topic substrate — cohort-side `MembershipCertV1` publication.
3
+ *
4
+ * Per `docs/cohort-topic.md` §Membership snapshots: the cohort publishes a threshold-signed
5
+ * `MembershipCertV1`
6
+ *
7
+ * - at stabilization, and on any change to the first `k − x` members ({@link MembershipCertPublisher.onStabilized});
8
+ * - refreshed every `T_membership_refresh` (default 5 min) ({@link MembershipCertPublisher.tick}).
9
+ *
10
+ * The publisher is db-core logic over the {@link CohortSigner} (threshold sign) and the
11
+ * {@link IMembershipPublishSink} (serve/advertise). It never imports FRET. Members are sorted
12
+ * ascending for the cert (matching the sharding order) and the first `minSigs` (= `k − x`) of that
13
+ * order are the "first `k − x`" whose change forces a fresh publish.
14
+ */
15
+ import type { IMembershipPublishSink } from "../ports.js";
16
+ import type { MembershipCertV1 } from "../wire/types.js";
17
+ import { type CohortSigner } from "../sig/threshold.js";
18
+ import { type MembershipCertSignable } from "../sig/payloads.js";
19
+ /** Default membership-cert refresh interval (`T_membership_refresh`). */
20
+ export declare const DEFAULT_T_MEMBERSHIP_REFRESH_MS: number;
21
+ /**
22
+ * The canonical {@link MembershipCertSignable} for a stabilized snapshot: members sorted ascending (the
23
+ * cert / sharding order), byte fields base64url-encoded, over exactly the threshold-signed fields. The
24
+ * publisher signs `membershipCertSigningPayload` of this; a rotation-attestation **producer** (db-p2p,
25
+ * `cohort-topic-trust-anchor-rotation-production`) signs the *successor* cert's image through the SAME
26
+ * helper, so signer and verifier never canonicalize the cert independently (signature-image agreement —
27
+ * a mismatch makes the db-core chain check fail).
28
+ */
29
+ export declare function membershipCertSignable(snapshot: CohortSnapshot): MembershipCertSignable;
30
+ /** A stabilized cohort snapshot the publisher attests. */
31
+ export interface CohortSnapshot {
32
+ /** Cohort coord (32 bytes). */
33
+ coord: Uint8Array;
34
+ /** Cohort epoch for this snapshot. */
35
+ cohortEpoch: Uint8Array;
36
+ /** Cohort members (any order; the cert sorts them ascending). */
37
+ members: readonly Uint8Array[];
38
+ /** Unix ms this membership stabilized. */
39
+ stabilizedAt: number;
40
+ /** Optional FRET stabilization proof. */
41
+ fretAttestation?: Uint8Array;
42
+ }
43
+ /**
44
+ * A predecessor-cohort rotation attestation to attach to a fresh cert (an epoch rotation). The
45
+ * predecessor cohort threshold-signs the **successor** cert's `membershipCertSigningPayload`; that
46
+ * `(prevEpoch, rotationSig, rotationSigners)` triple lets a participant holding a trusted predecessor
47
+ * verify the rotation is legitimate. Producing this triple is the db-p2p ticket
48
+ * `cohort-topic-trust-anchor-rotation-production`; the publisher only attaches a provided one.
49
+ */
50
+ export interface RotationAttestation {
51
+ /** Predecessor cohort epoch this cert rotates from (32 bytes). */
52
+ prevEpoch: Uint8Array;
53
+ /** Predecessor cohort's threshold signature over the successor cert's signing payload. */
54
+ rotationSig: Uint8Array;
55
+ /** Predecessor cohort signers that produced {@link rotationSig}; `>= minSigs`. */
56
+ rotationSigners: readonly Uint8Array[];
57
+ }
58
+ /** Cohort-side membership-cert publisher. */
59
+ export interface MembershipCertPublisher {
60
+ /**
61
+ * Drive publication on a stabilization event. Publishes (and returns the cert) when the first
62
+ * `k − x` members changed since the last publish, or on the first call; otherwise returns `undefined`.
63
+ * Pass `rotation` to attach a predecessor-cohort rotation attestation (an epoch rotation); omit it for
64
+ * the default non-rotation publish (no rotation fields are emitted).
65
+ */
66
+ onStabilized(snapshot: CohortSnapshot, now: number, rotation?: RotationAttestation): Promise<MembershipCertV1 | undefined>;
67
+ /**
68
+ * Periodic tick. Re-publishes (and returns the cert) when `T_membership_refresh` has elapsed since
69
+ * the last publish; otherwise returns `undefined`. Pass `rotation` to attach a rotation attestation.
70
+ */
71
+ tick(snapshot: CohortSnapshot, now: number, rotation?: RotationAttestation): Promise<MembershipCertV1 | undefined>;
72
+ }
73
+ export interface MembershipCertPublisherDeps {
74
+ signer: CohortSigner;
75
+ sink: IMembershipPublishSink;
76
+ refreshMs?: number;
77
+ minSigs?: number;
78
+ maxMessageBytes?: number;
79
+ }
80
+ /** Build a cohort-side {@link MembershipCertPublisher}. */
81
+ export declare function createMembershipCertPublisher(deps: MembershipCertPublisherDeps): MembershipCertPublisher;
82
+ //# sourceMappingURL=publisher.d.ts.map