@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 @@
1
+ {"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/publisher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAgC,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE/F,yEAAyE;AACzE,eAAO,MAAM,+BAA+B,QAAa,CAAC;AAE1D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,sBAAsB,CAQvF;AAED,0DAA0D;AAC1D,MAAM,WAAW,cAAc;IAC9B,+BAA+B;IAC/B,KAAK,EAAE,UAAU,CAAC;IAClB,sCAAsC;IACtC,WAAW,EAAE,UAAU,CAAC;IACxB,iEAAiE;IACjE,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IAC/B,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,eAAe,CAAC,EAAE,UAAU,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IACnC,kEAAkE;IAClE,SAAS,EAAE,UAAU,CAAC;IACtB,0FAA0F;IAC1F,WAAW,EAAE,UAAU,CAAC;IACxB,kFAAkF;IAClF,eAAe,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED,6CAA6C;AAC7C,MAAM,WAAW,uBAAuB;IACvC;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IAC3H;;;OAGG;IACH,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;CACnH;AAED,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,sBAAsB,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAwED,2DAA2D;AAC3D,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,2BAA2B,GAAG,uBAAuB,CAExG"}
@@ -0,0 +1,107 @@
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 { bytesToB64url, encodeCohortMessage } from "../wire/codec.js";
16
+ import { compareBytes } from "../registration/bytes.js";
17
+ import { DEFAULT_MIN_SIGS } from "../sig/threshold.js";
18
+ import { membershipCertSigningPayload } from "../sig/payloads.js";
19
+ /** Default membership-cert refresh interval (`T_membership_refresh`). */
20
+ export const DEFAULT_T_MEMBERSHIP_REFRESH_MS = 5 * 60_000;
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 function membershipCertSignable(snapshot) {
30
+ const sorted = [...snapshot.members].sort(compareBytes);
31
+ return {
32
+ cohortCoord: bytesToB64url(snapshot.coord),
33
+ cohortEpoch: bytesToB64url(snapshot.cohortEpoch),
34
+ members: sorted.map(bytesToB64url),
35
+ stabilizedAt: snapshot.stabilizedAt,
36
+ };
37
+ }
38
+ class SigningMembershipCertPublisher {
39
+ deps;
40
+ refreshMs;
41
+ minSigs;
42
+ /** base64url of the first `minSigs` members of the last published snapshot. */
43
+ lastFirstKx;
44
+ lastPublishedAt;
45
+ constructor(deps) {
46
+ this.deps = deps;
47
+ this.refreshMs = deps.refreshMs ?? DEFAULT_T_MEMBERSHIP_REFRESH_MS;
48
+ this.minSigs = deps.minSigs ?? DEFAULT_MIN_SIGS;
49
+ }
50
+ async onStabilized(snapshot, now, rotation) {
51
+ const firstKx = this.firstKx(snapshot.members);
52
+ if (this.lastFirstKx !== undefined && sameOrder(this.lastFirstKx, firstKx)) {
53
+ return undefined; // first k − x unchanged — no republish needed
54
+ }
55
+ return this.publish(snapshot, now, rotation);
56
+ }
57
+ async tick(snapshot, now, rotation) {
58
+ if (this.lastPublishedAt !== undefined && now - this.lastPublishedAt < this.refreshMs) {
59
+ return undefined;
60
+ }
61
+ return this.publish(snapshot, now, rotation);
62
+ }
63
+ /** The first `minSigs` members of the cert's ascending order, base64url — the republish-change key. */
64
+ firstKx(members) {
65
+ return [...members].sort(compareBytes).slice(0, this.minSigs).map(bytesToB64url);
66
+ }
67
+ async publish(snapshot, now, rotation) {
68
+ const signable = membershipCertSignable(snapshot);
69
+ const { thresholdSig, signers } = await this.deps.signer.thresholdSign(membershipCertSigningPayload(signable));
70
+ const cert = {
71
+ v: 1,
72
+ ...signable,
73
+ thresholdSig: bytesToB64url(thresholdSig),
74
+ signers: signers.map(bytesToB64url),
75
+ };
76
+ if (snapshot.fretAttestation !== undefined) {
77
+ cert.fretAttestation = bytesToB64url(snapshot.fretAttestation);
78
+ }
79
+ // A rotation attestation (when given) signs *over* the cert's signing payload, so it is attached to the
80
+ // envelope after signing and is not part of `membershipCertSigningPayload`. Omitted → no rotation fields.
81
+ if (rotation !== undefined) {
82
+ cert.prevEpoch = bytesToB64url(rotation.prevEpoch);
83
+ cert.rotationSig = bytesToB64url(rotation.rotationSig);
84
+ cert.rotationSigners = rotation.rotationSigners.map(bytesToB64url);
85
+ }
86
+ this.deps.sink.publish(encodeCohortMessage(cert, this.deps.maxMessageBytes));
87
+ this.lastFirstKx = signable.members.slice(0, this.minSigs);
88
+ this.lastPublishedAt = now;
89
+ return cert;
90
+ }
91
+ }
92
+ function sameOrder(a, b) {
93
+ if (a.length !== b.length) {
94
+ return false;
95
+ }
96
+ for (let i = 0; i < a.length; i++) {
97
+ if (a[i] !== b[i]) {
98
+ return false;
99
+ }
100
+ }
101
+ return true;
102
+ }
103
+ /** Build a cohort-side {@link MembershipCertPublisher}. */
104
+ export function createMembershipCertPublisher(deps) {
105
+ return new SigningMembershipCertPublisher(deps);
106
+ }
107
+ //# sourceMappingURL=publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publisher.js","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/publisher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Cohort-topic substrate — membership-source dispatch.
3
+ *
4
+ * Resolved open question (per `docs/cohort-topic.md` §Membership source): how *committed*
5
+ * membership is obtained differs by tier.
6
+ *
7
+ * - **T0/T1** cohorts serve committed work (transaction commits, chain serving); their membership is
8
+ * anchored in the transaction log's commit certificate. The verifier reads it from there (it never
9
+ * writes the log).
10
+ * - **T2/T3** cohorts (matchmaking, push forwarding) derive membership from current FRET state and
11
+ * verify against FRET's signed `MembershipCertV1` advertisements.
12
+ *
13
+ * Both back-ends present the same {@link IMembershipSource} surface; this router picks between them by
14
+ * tier. db-p2p supplies the two concrete sources (tx-log reader and FRET cert source).
15
+ */
16
+ import type { IMembershipSource } from "../ports.js";
17
+ /** Picks the authoritative membership source for a cohort by its tier. */
18
+ export interface IMembershipSourceRouter {
19
+ /** Source for a cohort at `tier`: T0/T1 → committed tx-log, T2/T3 → FRET certs. */
20
+ for(tier: number): IMembershipSource;
21
+ }
22
+ /**
23
+ * Build a router over the two membership back-ends.
24
+ * @param deps.committed source backed by the transaction-log commit certificate (T0/T1).
25
+ * @param deps.fret source backed by FRET's signed `MembershipCertV1` advertisements (T2/T3).
26
+ */
27
+ export declare function createMembershipSourceRouter(deps: {
28
+ committed: IMembershipSource;
29
+ fret: IMembershipSource;
30
+ }): IMembershipSourceRouter;
31
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,0EAA0E;AAC1E,MAAM,WAAW,uBAAuB;IACvC,mFAAmF;IACnF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC;CACrC;AAOD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAAG,uBAAuB,CAMrI"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Cohort-topic substrate — membership-source dispatch.
3
+ *
4
+ * Resolved open question (per `docs/cohort-topic.md` §Membership source): how *committed*
5
+ * membership is obtained differs by tier.
6
+ *
7
+ * - **T0/T1** cohorts serve committed work (transaction commits, chain serving); their membership is
8
+ * anchored in the transaction log's commit certificate. The verifier reads it from there (it never
9
+ * writes the log).
10
+ * - **T2/T3** cohorts (matchmaking, push forwarding) derive membership from current FRET state and
11
+ * verify against FRET's signed `MembershipCertV1` advertisements.
12
+ *
13
+ * Both back-ends present the same {@link IMembershipSource} surface; this router picks between them by
14
+ * tier. db-p2p supplies the two concrete sources (tx-log reader and FRET cert source).
15
+ */
16
+ /** Tiers whose committed membership is anchored in the transaction log. */
17
+ function isCommittedTier(tier) {
18
+ return tier === 0 || tier === 1;
19
+ }
20
+ /**
21
+ * Build a router over the two membership back-ends.
22
+ * @param deps.committed source backed by the transaction-log commit certificate (T0/T1).
23
+ * @param deps.fret source backed by FRET's signed `MembershipCertV1` advertisements (T2/T3).
24
+ */
25
+ export function createMembershipSourceRouter(deps) {
26
+ return {
27
+ for(tier) {
28
+ return isCommittedTier(tier) ? deps.committed : deps.fret;
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,2EAA2E;AAC3E,SAAS,eAAe,CAAC,IAAY;IACpC,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAA+D;IAC3G,OAAO;QACN,GAAG,CAAC,IAAY;YACf,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC3D,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Cohort-topic substrate — participant-side membership verification with a trust-anchor gate.
3
+ *
4
+ * Per `docs/cohort-topic.md` §Membership snapshots and §Bootstrapping trust. A participant verifying
5
+ * a threshold-signed message:
6
+ *
7
+ * 1. takes the message's `signers`, the cohort `coord` the signers should belong to, and the tier;
8
+ * 2. looks up the cached `MembershipCertV1` for that coord (or pulls the source's `current`);
9
+ * 3. checks the signers are a `≥ minSigs` subset of the cert's members and the signature verifies;
10
+ * 4. **on failure against a cached/stale cert, re-fetches the cert from any cohort member exactly
11
+ * once and retries**; still failing → the message is untrusted.
12
+ *
13
+ * **Trust anchoring (the gate this module adds).** Self-consistency (a cert's own threshold signature
14
+ * is a `≥ minSigs` quorum over its own `members`) proves only internal well-formedness — *not* that the
15
+ * attesting key set is the legitimate cohort for the coord. An adversary controlling `k − x` keys could
16
+ * mint a self-consistent cert over a coord it does not own. So before a (re)fetched cert is believed,
17
+ * {@link CachingMembershipVerifier.certIsTrusted} requires it to be self-consistent **AND** anchored by
18
+ * at least one of:
19
+ *
20
+ * - **Trust root** — `(coord, epoch, member-set)` is in the out-of-band-seeded {@link TrustRoot} set
21
+ * (the genesis-block cohorts). Base case of every chain; checked before the direct anchor, so a
22
+ * configured root is authoritative.
23
+ * - **Direct anchor** — the injected {@link IMembershipTrustAnchor} vouches for the binding from a
24
+ * source the node directly trusts (FRET ring agreement / tx-log commit cert, bound in db-p2p). A
25
+ * `"rejected"` verdict is **fatal** (a forgery, even if self-consistent) and overrides the fallback.
26
+ * - **Attestation chain** — a cert carrying a rotation attestation (`prevEpoch`/`rotationSig`/
27
+ * `rotationSigners`) inherits trust when the node already holds a **trusted** predecessor for the same
28
+ * coord at `prevEpoch` whose members form a `≥ minSigs` quorum over this cert's signing payload.
29
+ *
30
+ * **Interim TOFU fallback (documented limit).** For a coord the node cannot anchor (the direct anchor
31
+ * returns `"unknown"` and there is no trust root / chain) and that has **no trusted cert yet**, the
32
+ * verifier falls back to trust-on-first-use of any self-consistent cert — identical to the pre-anchor
33
+ * behavior, so there is strictly no regression on coords no node can verify today (distant T2/T3, and
34
+ * T0/T1 until the committed-index binding lands). Once a coord *does* hold a trusted cert, the chain
35
+ * governs successors: an un-anchored cert for an already-trusted coord is rejected (no TOFU downgrade),
36
+ * which is what gives the rotation chain its teeth. The FRET / tx-log direct-anchor bindings that close
37
+ * the remaining TOFU gap are tracked in `cohort-topic-trust-anchor-fret-binding` and the backlog
38
+ * `...-fret-stabilization-proof` / `...-txlog-committed-binding` tickets.
39
+ *
40
+ * **Deviation from the ticket sketch (documented):** `verifyMessage` takes the cohort `tier`. A coord
41
+ * is an opaque hash, so the T0/T1-vs-T2/T3 source dispatch the same ticket mandates cannot be derived
42
+ * from the coord alone; the caller already knows the tier (it computed the coord from the message's
43
+ * claimed tier/topic). The `tier` is threaded into the gate so the direct anchor is consulted with the
44
+ * same tier the router used (the binding is tier-scoped).
45
+ */
46
+ import type { IMembershipTrustAnchor, RingCoord, TrustRoot } from "../ports.js";
47
+ import type { MembershipCertV1 } from "../wire/types.js";
48
+ import { type CohortSigner } from "../sig/threshold.js";
49
+ import type { IMembershipSourceRouter } from "./source.js";
50
+ /** Outcome of verifying a threshold-signed message against cohort membership. */
51
+ export type VerifyResult = "verified" | "untrusted";
52
+ /** Caches certs per coord and verifies threshold-signed messages with one stale-cert refetch. */
53
+ export interface MembershipVerifier {
54
+ /** Cache `cert` as the latest known membership for its coord. */
55
+ cache(cert: MembershipCertV1): void;
56
+ /**
57
+ * Verify a threshold-signed message. `expectedCoord` is the cohort the `signers` should belong to;
58
+ * `tier` selects the membership source. Performs the single refetch+retry internally.
59
+ *
60
+ * `opts` bounds the network amplification a flood-exposed caller (the `promote` handler) can suffer:
61
+ * when **both** `minRefetchIntervalMs` and `now` are given, the stale-cert `source.fetch()` retry is
62
+ * **rate-limited per coord** — at most one refetch per coord per interval — so a stream of verify-misses
63
+ * (e.g. forged notices) drives a bounded membership-fetch rate rather than one dial per message.
64
+ * Eventual refetch is *preserved*: a cold cache or a membership rotation still re-fetches once the
65
+ * interval elapses (unlike outright suppression). Omit `opts` (the default, and every existing caller)
66
+ * for the unbounded exactly-one-refetch behavior.
67
+ */
68
+ verifyMessage(signers: readonly Uint8Array[], expectedCoord: RingCoord, tier: number, payload: Uint8Array, sig: Uint8Array, opts?: RefetchBound): Promise<VerifyResult>;
69
+ }
70
+ /**
71
+ * Caller-supplied bound on the membership-cert refetch rate (anti-amplification on a flood-exposed verify
72
+ * path). Both fields are required to take effect; omit either for unbounded refetch.
73
+ */
74
+ export interface RefetchBound {
75
+ /** Minimum wall-clock gap (ms) between `source.fetch()` refetches for the same coord. */
76
+ readonly minRefetchIntervalMs?: number;
77
+ /** Current wall clock (ms) for the interval comparison. */
78
+ readonly now?: number;
79
+ }
80
+ export interface MembershipVerifierDeps {
81
+ signer: CohortSigner;
82
+ router: IMembershipSourceRouter;
83
+ minSigs?: number;
84
+ maxMessageBytes?: number;
85
+ /**
86
+ * Direct (base-case) trust anchor for a cert's `coord → keyset` binding. Defaults to
87
+ * {@link noAuthorityTrustAnchor} (every coord `"unknown"`), which preserves the interim TOFU behavior.
88
+ * db-p2p injects the FRET-ring-backed anchor.
89
+ */
90
+ anchor?: IMembershipTrustAnchor;
91
+ /** Out-of-band-seeded genesis trust roots (the base case of every attestation chain). Defaults to `[]`. */
92
+ trustRoots?: readonly TrustRoot[];
93
+ }
94
+ /** Build a participant-side {@link MembershipVerifier}. */
95
+ export declare function createMembershipVerifier(deps: MembershipVerifierDeps): MembershipVerifier;
96
+ //# sourceMappingURL=verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AAEpD,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IAClC,iEAAiE;IACjE,KAAK,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACxK;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,uBAAuB,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,2GAA2G;IAC3G,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CAClC;AAgPD,2DAA2D;AAC3D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,CAEzF"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Cohort-topic substrate — participant-side membership verification with a trust-anchor gate.
3
+ *
4
+ * Per `docs/cohort-topic.md` §Membership snapshots and §Bootstrapping trust. A participant verifying
5
+ * a threshold-signed message:
6
+ *
7
+ * 1. takes the message's `signers`, the cohort `coord` the signers should belong to, and the tier;
8
+ * 2. looks up the cached `MembershipCertV1` for that coord (or pulls the source's `current`);
9
+ * 3. checks the signers are a `≥ minSigs` subset of the cert's members and the signature verifies;
10
+ * 4. **on failure against a cached/stale cert, re-fetches the cert from any cohort member exactly
11
+ * once and retries**; still failing → the message is untrusted.
12
+ *
13
+ * **Trust anchoring (the gate this module adds).** Self-consistency (a cert's own threshold signature
14
+ * is a `≥ minSigs` quorum over its own `members`) proves only internal well-formedness — *not* that the
15
+ * attesting key set is the legitimate cohort for the coord. An adversary controlling `k − x` keys could
16
+ * mint a self-consistent cert over a coord it does not own. So before a (re)fetched cert is believed,
17
+ * {@link CachingMembershipVerifier.certIsTrusted} requires it to be self-consistent **AND** anchored by
18
+ * at least one of:
19
+ *
20
+ * - **Trust root** — `(coord, epoch, member-set)` is in the out-of-band-seeded {@link TrustRoot} set
21
+ * (the genesis-block cohorts). Base case of every chain; checked before the direct anchor, so a
22
+ * configured root is authoritative.
23
+ * - **Direct anchor** — the injected {@link IMembershipTrustAnchor} vouches for the binding from a
24
+ * source the node directly trusts (FRET ring agreement / tx-log commit cert, bound in db-p2p). A
25
+ * `"rejected"` verdict is **fatal** (a forgery, even if self-consistent) and overrides the fallback.
26
+ * - **Attestation chain** — a cert carrying a rotation attestation (`prevEpoch`/`rotationSig`/
27
+ * `rotationSigners`) inherits trust when the node already holds a **trusted** predecessor for the same
28
+ * coord at `prevEpoch` whose members form a `≥ minSigs` quorum over this cert's signing payload.
29
+ *
30
+ * **Interim TOFU fallback (documented limit).** For a coord the node cannot anchor (the direct anchor
31
+ * returns `"unknown"` and there is no trust root / chain) and that has **no trusted cert yet**, the
32
+ * verifier falls back to trust-on-first-use of any self-consistent cert — identical to the pre-anchor
33
+ * behavior, so there is strictly no regression on coords no node can verify today (distant T2/T3, and
34
+ * T0/T1 until the committed-index binding lands). Once a coord *does* hold a trusted cert, the chain
35
+ * governs successors: an un-anchored cert for an already-trusted coord is rejected (no TOFU downgrade),
36
+ * which is what gives the rotation chain its teeth. The FRET / tx-log direct-anchor bindings that close
37
+ * the remaining TOFU gap are tracked in `cohort-topic-trust-anchor-fret-binding` and the backlog
38
+ * `...-fret-stabilization-proof` / `...-txlog-committed-binding` tickets.
39
+ *
40
+ * **Deviation from the ticket sketch (documented):** `verifyMessage` takes the cohort `tier`. A coord
41
+ * is an opaque hash, so the T0/T1-vs-T2/T3 source dispatch the same ticket mandates cannot be derived
42
+ * from the coord alone; the caller already knows the tier (it computed the coord from the message's
43
+ * claimed tier/topic). The `tier` is threaded into the gate so the direct anchor is consulted with the
44
+ * same tier the router used (the binding is tier-scoped).
45
+ */
46
+ import { noAuthorityTrustAnchor } from "../ports.js";
47
+ import { b64urlToBytes, bytesToB64url, decodeMembershipCertV1 } from "../wire/codec.js";
48
+ import { CohortWireError } from "../wire/validate.js";
49
+ import { DEFAULT_MIN_SIGS } from "../sig/threshold.js";
50
+ import { membershipCertSigningPayload } from "../sig/payloads.js";
51
+ class CachingMembershipVerifier {
52
+ deps;
53
+ byCoord = new Map();
54
+ /** Per-coord timestamp of the last `source.fetch()` attempt (the rate-limit clock for {@link RefetchBound}). */
55
+ lastFetchAt = new Map();
56
+ minSigs;
57
+ anchor;
58
+ trustRoots;
59
+ constructor(deps) {
60
+ this.deps = deps;
61
+ this.minSigs = deps.minSigs ?? DEFAULT_MIN_SIGS;
62
+ this.anchor = deps.anchor ?? noAuthorityTrustAnchor;
63
+ this.trustRoots = (deps.trustRoots ?? []).map(normalizeTrustRoot);
64
+ }
65
+ cache(cert) {
66
+ // The public cache feeds this node its OWN freshly-published cert — a node trusts a cert it itself
67
+ // published, so it is marked trusted and may anchor the next rotation in the attestation chain.
68
+ this.byCoord.set(cert.cohortCoord, { cert, trusted: true });
69
+ }
70
+ async verifyMessage(signers, expectedCoord, tier, payload, sig, opts) {
71
+ const coordKey = bytesToB64url(expectedCoord);
72
+ const source = this.deps.router.for(tier);
73
+ // Seed from the cheap cached view if we hold nothing yet. A cached cert already passed the gate when
74
+ // it was loaded (or was self-published via `cache`), so it is used directly for message verification.
75
+ let cert = this.byCoord.get(coordKey)?.cert;
76
+ if (cert === undefined) {
77
+ cert = await this.loadFrom(source.current(expectedCoord), tier);
78
+ }
79
+ if (cert !== undefined && this.messageVerifies(cert, signers, payload, sig)) {
80
+ return "verified";
81
+ }
82
+ // Single fetch-and-retry: a stale or missing cert forces a network refresh. A flood-exposed caller
83
+ // (the ungated `promote` handler) bounds the amplification via {@link RefetchBound}: the refetch is
84
+ // then rate-limited to at most one per coord per interval, so a stream of verify-misses (forged
85
+ // notices) cannot turn into a storm of membership dials. Eventual refetch survives — a cold cache or a
86
+ // membership rotation still refreshes once the interval elapses.
87
+ if (!this.refetchAllowed(coordKey, opts)) {
88
+ return "untrusted";
89
+ }
90
+ const refreshed = await this.loadFrom(source.fetch(expectedCoord), tier);
91
+ if (refreshed !== undefined && this.messageVerifies(refreshed, signers, payload, sig)) {
92
+ return "verified";
93
+ }
94
+ return "untrusted";
95
+ }
96
+ /**
97
+ * Whether a `source.fetch()` refetch is permitted for `coordKey` now. Unbounded (always `true`) unless
98
+ * the caller supplies both `minRefetchIntervalMs` and `now`, in which case at most one refetch per coord
99
+ * per interval is allowed — the per-coord fetch-rate bound that caps flood amplification. Records the
100
+ * attempt time when it returns `true` (the dial is about to happen).
101
+ */
102
+ refetchAllowed(coordKey, opts) {
103
+ const minInterval = opts?.minRefetchIntervalMs;
104
+ const now = opts?.now;
105
+ if (minInterval === undefined || now === undefined) {
106
+ return true;
107
+ }
108
+ const last = this.lastFetchAt.get(coordKey);
109
+ if (last !== undefined && now - last < minInterval) {
110
+ return false;
111
+ }
112
+ this.lastFetchAt.set(coordKey, now);
113
+ return true;
114
+ }
115
+ /**
116
+ * Decode an encoded cert, run it through the trust gate, cache it (with its trusted status), and return
117
+ * it for message verification; `undefined` if absent, malformed, or rejected by the gate. A rejected
118
+ * cert (failed self-consistency, a `"rejected"` direct anchor, or an un-anchored cert for an
119
+ * already-trusted coord) is treated exactly like an absent cert, so the single refetch still fires.
120
+ */
121
+ async loadFrom(pending, tier) {
122
+ const encoded = await pending;
123
+ if (encoded === undefined) {
124
+ return undefined;
125
+ }
126
+ let cert;
127
+ let trust;
128
+ try {
129
+ cert = decodeMembershipCertV1(encoded, this.deps.maxMessageBytes);
130
+ trust = this.certIsTrusted(cert, tier);
131
+ }
132
+ catch (err) {
133
+ if (err instanceof CohortWireError) {
134
+ return undefined; // a malformed cert (or non-base64url signer) is treated as no cert
135
+ }
136
+ throw err;
137
+ }
138
+ if (trust === "reject") {
139
+ return undefined;
140
+ }
141
+ // Only a `"trusted"` cert may anchor a successor in the attestation chain; a `"tofu"` cert is cached
142
+ // for message verification but must never launder trust into a rotation.
143
+ this.byCoord.set(cert.cohortCoord, { cert, trusted: trust === "trusted" });
144
+ return cert;
145
+ }
146
+ /**
147
+ * The trust gate (see the module header). A cert is accepted iff it is self-consistent **and** anchored
148
+ * by a trust root, the direct anchor, or the attestation chain; otherwise it falls to the interim TOFU
149
+ * fallback (first-use only). Returns whether the cert is a trusted anchor (`"trusted"`), an interim
150
+ * TOFU acceptance (`"tofu"`), or rejected (`"reject"`).
151
+ */
152
+ certIsTrusted(cert, tier) {
153
+ if (!this.certIsSelfConsistent(cert)) {
154
+ return "reject"; // internal well-formedness is the precondition for any trust path
155
+ }
156
+ if (this.matchesTrustRoot(cert)) {
157
+ return "trusted"; // a configured genesis root is authoritative, checked before the direct anchor
158
+ }
159
+ const verdict = this.anchor.directAnchor(cert, tier);
160
+ if (verdict === "anchored") {
161
+ return "trusted";
162
+ }
163
+ if (verdict === "rejected") {
164
+ return "reject"; // a contradicted binding is a forgery — fatal, overrides the TOFU fallback
165
+ }
166
+ // verdict === "unknown": no local authority for this coord. Try the attestation chain, else fall back.
167
+ if (this.hasRotationAttestation(cert) && this.chainGrantsTrust(cert)) {
168
+ return "trusted";
169
+ }
170
+ return this.fallbackTrust(cert);
171
+ }
172
+ /**
173
+ * The interim fallback for a coord with no trust-root / anchor / chain coverage. Trust-on-first-use:
174
+ * accept a self-consistent cert when the coord holds **no trusted cert yet**, preserving the pre-anchor
175
+ * behavior on coords no node can verify today. But once a coord *is* trust-established, an un-anchored
176
+ * cert (a failed/absent rotation, including a forged rotation off a trusted predecessor) is **rejected**
177
+ * — no silent TOFU downgrade — which is what gives the attestation chain its teeth.
178
+ */
179
+ fallbackTrust(cert) {
180
+ return this.byCoord.get(cert.cohortCoord)?.trusted ? "reject" : "tofu";
181
+ }
182
+ /** Whether a cert carries a full rotation attestation (all three fields; validated all-or-nothing on the wire). */
183
+ hasRotationAttestation(cert) {
184
+ return cert.prevEpoch !== undefined && cert.rotationSig !== undefined && cert.rotationSigners !== undefined;
185
+ }
186
+ /**
187
+ * Whether `cert`'s rotation attestation is valid: a **trusted** predecessor for the same coord is cached
188
+ * at `prevEpoch`, the rotation is not self-referential, and the predecessor's members form a `≥ minSigs`
189
+ * quorum over this cert's signing payload via `rotationSig`. A predecessor that only reached the cache via
190
+ * TOFU (not trusted) must not anchor the successor — the trusted-cache invariant.
191
+ */
192
+ chainGrantsTrust(cert) {
193
+ const prevEpoch = cert.prevEpoch;
194
+ if (prevEpoch === cert.cohortEpoch) {
195
+ return false; // a cert cannot rotate from itself
196
+ }
197
+ const predecessor = this.byCoord.get(cert.cohortCoord);
198
+ if (predecessor === undefined || !predecessor.trusted || predecessor.cert.cohortEpoch !== prevEpoch) {
199
+ return false;
200
+ }
201
+ // `rotationSigners` is validated only as a string array, so `b64urlToBytes` may throw `CohortWireError`
202
+ // on a malformed signer — `loadFrom`'s try/catch turns that into "no cert", as for `certIsSelfConsistent`.
203
+ return this.deps.signer.verifyThreshold(membershipCertSigningPayload(cert), b64urlToBytes(cert.rotationSig), cert.rotationSigners.map((s) => b64urlToBytes(s)), predecessor.cert, this.minSigs);
204
+ }
205
+ /** Whether `cert` matches a configured trust root by `(coord, epoch)` and an order-independent member set. */
206
+ matchesTrustRoot(cert) {
207
+ for (const root of this.trustRoots) {
208
+ if (root.coord === cert.cohortCoord && root.epoch === cert.cohortEpoch && setEqualsArray(root.members, cert.members)) {
209
+ return true;
210
+ }
211
+ }
212
+ return false;
213
+ }
214
+ /** A cert is self-consistent only if its own threshold signature is a valid quorum of its members. */
215
+ certIsSelfConsistent(cert) {
216
+ // `signers` is validated only as a string array (not per-element base64url), so `b64urlToBytes`
217
+ // below may throw `CohortWireError` on a malformed signer — `loadFrom`'s try/catch turns that
218
+ // into "no cert" rather than letting it escape.
219
+ return this.deps.signer.verifyThreshold(membershipCertSigningPayload(cert), b64urlToBytes(cert.thresholdSig), cert.signers.map((s) => b64urlToBytes(s)), cert, this.minSigs);
220
+ }
221
+ messageVerifies(cert, signers, payload, sig) {
222
+ return this.deps.signer.verifyThreshold(payload, sig, signers, cert, this.minSigs);
223
+ }
224
+ }
225
+ /** Pre-normalize a {@link TrustRoot} (raw bytes) to the cert's base64url form for cheap matching. */
226
+ function normalizeTrustRoot(root) {
227
+ return {
228
+ coord: bytesToB64url(root.coord),
229
+ epoch: bytesToB64url(root.epoch),
230
+ members: new Set(root.members.map(bytesToB64url)),
231
+ };
232
+ }
233
+ /** Order-independent set equality between a trust-root member set and a cert's member array (duplicate-safe). */
234
+ function setEqualsArray(set, members) {
235
+ const seen = new Set();
236
+ for (const m of members) {
237
+ if (!set.has(m)) {
238
+ return false; // a member not in the root → not a root match
239
+ }
240
+ seen.add(m);
241
+ }
242
+ // Cover both directions: every distinct cert member is in the root AND every root member is covered,
243
+ // so a duplicate-inflated member list cannot masquerade as a full-set match.
244
+ return seen.size === set.size;
245
+ }
246
+ /** Build a participant-side {@link MembershipVerifier}. */
247
+ export function createMembershipVerifier(deps) {
248
+ return new CachingMembershipVerifier(deps);
249
+ }
250
+ //# sourceMappingURL=verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../../../src/cohort-topic/membership/verifier.ts"],"names":[],"mappings":"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"}