@optimystic/db-core 0.13.5 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cluster/structs.d.ts +13 -0
- package/dist/src/cluster/structs.d.ts.map +1 -1
- package/dist/src/cohort-topic/addressing.d.ts +53 -0
- package/dist/src/cohort-topic/addressing.d.ts.map +1 -0
- package/dist/src/cohort-topic/addressing.js +95 -0
- package/dist/src/cohort-topic/addressing.js.map +1 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts +105 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts.map +1 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js +197 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js.map +1 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts +50 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts.map +1 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.js +62 -0
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.js.map +1 -0
- package/dist/src/cohort-topic/antidos/index.d.ts +6 -0
- package/dist/src/cohort-topic/antidos/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/antidos/index.js +6 -0
- package/dist/src/cohort-topic/antidos/index.js.map +1 -0
- package/dist/src/cohort-topic/antidos/rate-limiter.d.ts +95 -0
- package/dist/src/cohort-topic/antidos/rate-limiter.d.ts.map +1 -0
- package/dist/src/cohort-topic/antidos/rate-limiter.js +146 -0
- package/dist/src/cohort-topic/antidos/rate-limiter.js.map +1 -0
- package/dist/src/cohort-topic/antidos/replay-guard.d.ts +37 -0
- package/dist/src/cohort-topic/antidos/replay-guard.d.ts.map +1 -0
- package/dist/src/cohort-topic/antidos/replay-guard.js +78 -0
- package/dist/src/cohort-topic/antidos/replay-guard.js.map +1 -0
- package/dist/src/cohort-topic/antidos/topic-budget.d.ts +50 -0
- package/dist/src/cohort-topic/antidos/topic-budget.d.ts.map +1 -0
- package/dist/src/cohort-topic/antidos/topic-budget.js +95 -0
- package/dist/src/cohort-topic/antidos/topic-budget.js.map +1 -0
- package/dist/src/cohort-topic/antiflood/index.d.ts +3 -0
- package/dist/src/cohort-topic/antiflood/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/antiflood/index.js +3 -0
- package/dist/src/cohort-topic/antiflood/index.js.map +1 -0
- package/dist/src/cohort-topic/antiflood/invariants.d.ts +70 -0
- package/dist/src/cohort-topic/antiflood/invariants.d.ts.map +1 -0
- package/dist/src/cohort-topic/antiflood/invariants.js +86 -0
- package/dist/src/cohort-topic/antiflood/invariants.js.map +1 -0
- package/dist/src/cohort-topic/antiflood/jitter.d.ts +65 -0
- package/dist/src/cohort-topic/antiflood/jitter.d.ts.map +1 -0
- package/dist/src/cohort-topic/antiflood/jitter.js +75 -0
- package/dist/src/cohort-topic/antiflood/jitter.js.map +1 -0
- package/dist/src/cohort-topic/coldstart.d.ts +117 -0
- package/dist/src/cohort-topic/coldstart.d.ts.map +1 -0
- package/dist/src/cohort-topic/coldstart.js +127 -0
- package/dist/src/cohort-topic/coldstart.js.map +1 -0
- package/dist/src/cohort-topic/dmax.d.ts +44 -0
- package/dist/src/cohort-topic/dmax.d.ts.map +1 -0
- package/dist/src/cohort-topic/dmax.js +70 -0
- package/dist/src/cohort-topic/dmax.js.map +1 -0
- package/dist/src/cohort-topic/gossip/bus.d.ts +85 -0
- package/dist/src/cohort-topic/gossip/bus.d.ts.map +1 -0
- package/dist/src/cohort-topic/gossip/bus.js +146 -0
- package/dist/src/cohort-topic/gossip/bus.js.map +1 -0
- package/dist/src/cohort-topic/gossip/index.d.ts +4 -0
- package/dist/src/cohort-topic/gossip/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/gossip/index.js +4 -0
- package/dist/src/cohort-topic/gossip/index.js.map +1 -0
- package/dist/src/cohort-topic/gossip/records.d.ts +12 -0
- package/dist/src/cohort-topic/gossip/records.d.ts.map +1 -0
- package/dist/src/cohort-topic/gossip/records.js +41 -0
- package/dist/src/cohort-topic/gossip/records.js.map +1 -0
- package/dist/src/cohort-topic/gossip/view.d.ts +39 -0
- package/dist/src/cohort-topic/gossip/view.d.ts.map +1 -0
- package/dist/src/cohort-topic/gossip/view.js +30 -0
- package/dist/src/cohort-topic/gossip/view.js.map +1 -0
- package/dist/src/cohort-topic/index.d.ts +21 -0
- package/dist/src/cohort-topic/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/index.js +21 -0
- package/dist/src/cohort-topic/index.js.map +1 -0
- package/dist/src/cohort-topic/load/barometer.d.ts +78 -0
- package/dist/src/cohort-topic/load/barometer.d.ts.map +1 -0
- package/dist/src/cohort-topic/load/barometer.js +93 -0
- package/dist/src/cohort-topic/load/barometer.js.map +1 -0
- package/dist/src/cohort-topic/load/index.d.ts +2 -0
- package/dist/src/cohort-topic/load/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/load/index.js +2 -0
- package/dist/src/cohort-topic/load/index.js.map +1 -0
- package/dist/src/cohort-topic/member-engine.d.ts +134 -0
- package/dist/src/cohort-topic/member-engine.d.ts.map +1 -0
- package/dist/src/cohort-topic/member-engine.js +264 -0
- package/dist/src/cohort-topic/member-engine.js.map +1 -0
- package/dist/src/cohort-topic/membership/index.d.ts +4 -0
- package/dist/src/cohort-topic/membership/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership/index.js +4 -0
- package/dist/src/cohort-topic/membership/index.js.map +1 -0
- package/dist/src/cohort-topic/membership/publisher.d.ts +82 -0
- package/dist/src/cohort-topic/membership/publisher.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership/publisher.js +107 -0
- package/dist/src/cohort-topic/membership/publisher.js.map +1 -0
- package/dist/src/cohort-topic/membership/source.d.ts +31 -0
- package/dist/src/cohort-topic/membership/source.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership/source.js +32 -0
- package/dist/src/cohort-topic/membership/source.js.map +1 -0
- package/dist/src/cohort-topic/membership/verifier.d.ts +96 -0
- package/dist/src/cohort-topic/membership/verifier.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership/verifier.js +250 -0
- package/dist/src/cohort-topic/membership/verifier.js.map +1 -0
- package/dist/src/cohort-topic/ports.d.ts +149 -0
- package/dist/src/cohort-topic/ports.d.ts.map +1 -0
- package/dist/src/cohort-topic/ports.js +25 -0
- package/dist/src/cohort-topic/ports.js.map +1 -0
- package/dist/src/cohort-topic/promotion.d.ts +135 -0
- package/dist/src/cohort-topic/promotion.d.ts.map +1 -0
- package/dist/src/cohort-topic/promotion.js +269 -0
- package/dist/src/cohort-topic/promotion.js.map +1 -0
- package/dist/src/cohort-topic/registration/bytes.d.ts +16 -0
- package/dist/src/cohort-topic/registration/bytes.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/bytes.js +32 -0
- package/dist/src/cohort-topic/registration/bytes.js.map +1 -0
- package/dist/src/cohort-topic/registration/handoff.d.ts +69 -0
- package/dist/src/cohort-topic/registration/handoff.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/handoff.js +98 -0
- package/dist/src/cohort-topic/registration/handoff.js.map +1 -0
- package/dist/src/cohort-topic/registration/index.d.ts +7 -0
- package/dist/src/cohort-topic/registration/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/index.js +7 -0
- package/dist/src/cohort-topic/registration/index.js.map +1 -0
- package/dist/src/cohort-topic/registration/renewal.d.ts +115 -0
- package/dist/src/cohort-topic/registration/renewal.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/renewal.js +306 -0
- package/dist/src/cohort-topic/registration/renewal.js.map +1 -0
- package/dist/src/cohort-topic/registration/sharding.d.ts +31 -0
- package/dist/src/cohort-topic/registration/sharding.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/sharding.js +48 -0
- package/dist/src/cohort-topic/registration/sharding.js.map +1 -0
- package/dist/src/cohort-topic/registration/store.d.ts +13 -0
- package/dist/src/cohort-topic/registration/store.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/store.js +72 -0
- package/dist/src/cohort-topic/registration/store.js.map +1 -0
- package/dist/src/cohort-topic/registration/types.d.ts +71 -0
- package/dist/src/cohort-topic/registration/types.d.ts.map +1 -0
- package/dist/src/cohort-topic/registration/types.js +27 -0
- package/dist/src/cohort-topic/registration/types.js.map +1 -0
- package/dist/src/cohort-topic/ring-hash.d.ts +27 -0
- package/dist/src/cohort-topic/ring-hash.d.ts.map +1 -0
- package/dist/src/cohort-topic/ring-hash.js +45 -0
- package/dist/src/cohort-topic/ring-hash.js.map +1 -0
- package/dist/src/cohort-topic/service.d.ts +157 -0
- package/dist/src/cohort-topic/service.d.ts.map +1 -0
- package/dist/src/cohort-topic/service.js +237 -0
- package/dist/src/cohort-topic/service.js.map +1 -0
- package/dist/src/cohort-topic/sig/index.d.ts +3 -0
- package/dist/src/cohort-topic/sig/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/sig/index.js +3 -0
- package/dist/src/cohort-topic/sig/index.js.map +1 -0
- package/dist/src/cohort-topic/sig/payloads.d.ts +25 -0
- package/dist/src/cohort-topic/sig/payloads.d.ts.map +1 -0
- package/dist/src/cohort-topic/sig/payloads.js +25 -0
- package/dist/src/cohort-topic/sig/payloads.js.map +1 -0
- package/dist/src/cohort-topic/sig/threshold.d.ts +33 -0
- package/dist/src/cohort-topic/sig/threshold.d.ts.map +1 -0
- package/dist/src/cohort-topic/sig/threshold.js +51 -0
- package/dist/src/cohort-topic/sig/threshold.js.map +1 -0
- package/dist/src/cohort-topic/tiers.d.ts +58 -0
- package/dist/src/cohort-topic/tiers.d.ts.map +1 -0
- package/dist/src/cohort-topic/tiers.js +49 -0
- package/dist/src/cohort-topic/tiers.js.map +1 -0
- package/dist/src/cohort-topic/traffic.d.ts +90 -0
- package/dist/src/cohort-topic/traffic.d.ts.map +1 -0
- package/dist/src/cohort-topic/traffic.js +146 -0
- package/dist/src/cohort-topic/traffic.js.map +1 -0
- package/dist/src/cohort-topic/walk.d.ts +123 -0
- package/dist/src/cohort-topic/walk.d.ts.map +1 -0
- package/dist/src/cohort-topic/walk.js +150 -0
- package/dist/src/cohort-topic/walk.js.map +1 -0
- package/dist/src/cohort-topic/willingness.d.ts +123 -0
- package/dist/src/cohort-topic/willingness.d.ts.map +1 -0
- package/dist/src/cohort-topic/willingness.js +143 -0
- package/dist/src/cohort-topic/willingness.js.map +1 -0
- package/dist/src/cohort-topic/wire/codec.d.ts +42 -0
- package/dist/src/cohort-topic/wire/codec.d.ts.map +1 -0
- package/dist/src/cohort-topic/wire/codec.js +163 -0
- package/dist/src/cohort-topic/wire/codec.js.map +1 -0
- package/dist/src/cohort-topic/wire/index.d.ts +6 -0
- package/dist/src/cohort-topic/wire/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/wire/index.js +6 -0
- package/dist/src/cohort-topic/wire/index.js.map +1 -0
- package/dist/src/cohort-topic/wire/payloads.d.ts +38 -0
- package/dist/src/cohort-topic/wire/payloads.d.ts.map +1 -0
- package/dist/src/cohort-topic/wire/payloads.js +102 -0
- package/dist/src/cohort-topic/wire/payloads.js.map +1 -0
- package/dist/src/cohort-topic/wire/types.d.ts +304 -0
- package/dist/src/cohort-topic/wire/types.d.ts.map +1 -0
- package/dist/src/cohort-topic/wire/types.js +16 -0
- package/dist/src/cohort-topic/wire/types.js.map +1 -0
- package/dist/src/cohort-topic/wire/validate.d.ts +25 -0
- package/dist/src/cohort-topic/wire/validate.d.ts.map +1 -0
- package/dist/src/cohort-topic/wire/validate.js +427 -0
- package/dist/src/cohort-topic/wire/validate.js.map +1 -0
- package/dist/src/collection/collection.d.ts +58 -1
- package/dist/src/collection/collection.d.ts.map +1 -1
- package/dist/src/collection/collection.js +76 -0
- package/dist/src/collection/collection.js.map +1 -1
- package/dist/src/collections/tree/tree.d.ts +58 -2
- package/dist/src/collections/tree/tree.d.ts.map +1 -1
- package/dist/src/collections/tree/tree.js +59 -2
- package/dist/src/collections/tree/tree.js.map +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/log/log.d.ts +42 -4
- package/dist/src/log/log.d.ts.map +1 -1
- package/dist/src/log/log.js +71 -3
- package/dist/src/log/log.js.map +1 -1
- package/dist/src/log/struct.d.ts +122 -2
- package/dist/src/log/struct.d.ts.map +1 -1
- package/dist/src/log/struct.js.map +1 -1
- package/dist/src/matchmaking/capability-filter.d.ts +24 -0
- package/dist/src/matchmaking/capability-filter.d.ts.map +1 -0
- package/dist/src/matchmaking/capability-filter.js +37 -0
- package/dist/src/matchmaking/capability-filter.js.map +1 -0
- package/dist/src/matchmaking/config.d.ts +77 -0
- package/dist/src/matchmaking/config.d.ts.map +1 -0
- package/dist/src/matchmaking/config.js +69 -0
- package/dist/src/matchmaking/config.js.map +1 -0
- package/dist/src/matchmaking/index.d.ts +21 -0
- package/dist/src/matchmaking/index.d.ts.map +1 -0
- package/dist/src/matchmaking/index.js +21 -0
- package/dist/src/matchmaking/index.js.map +1 -0
- package/dist/src/matchmaking/multi-cohort-seeker.d.ts +133 -0
- package/dist/src/matchmaking/multi-cohort-seeker.d.ts.map +1 -0
- package/dist/src/matchmaking/multi-cohort-seeker.js +142 -0
- package/dist/src/matchmaking/multi-cohort-seeker.js.map +1 -0
- package/dist/src/matchmaking/provider.d.ts +70 -0
- package/dist/src/matchmaking/provider.d.ts.map +1 -0
- package/dist/src/matchmaking/provider.js +93 -0
- package/dist/src/matchmaking/provider.js.map +1 -0
- package/dist/src/matchmaking/query-eval.d.ts +53 -0
- package/dist/src/matchmaking/query-eval.d.ts.map +1 -0
- package/dist/src/matchmaking/query-eval.js +69 -0
- package/dist/src/matchmaking/query-eval.js.map +1 -0
- package/dist/src/matchmaking/seeker-walk.d.ts +95 -0
- package/dist/src/matchmaking/seeker-walk.d.ts.map +1 -0
- package/dist/src/matchmaking/seeker-walk.js +75 -0
- package/dist/src/matchmaking/seeker-walk.js.map +1 -0
- package/dist/src/matchmaking/seeker.d.ts +51 -0
- package/dist/src/matchmaking/seeker.d.ts.map +1 -0
- package/dist/src/matchmaking/seeker.js +62 -0
- package/dist/src/matchmaking/seeker.js.map +1 -0
- package/dist/src/matchmaking/topic-anchor.d.ts +54 -0
- package/dist/src/matchmaking/topic-anchor.d.ts.map +1 -0
- package/dist/src/matchmaking/topic-anchor.js +67 -0
- package/dist/src/matchmaking/topic-anchor.js.map +1 -0
- package/dist/src/matchmaking/voting-quorum.d.ts +233 -0
- package/dist/src/matchmaking/voting-quorum.d.ts.map +1 -0
- package/dist/src/matchmaking/voting-quorum.js +238 -0
- package/dist/src/matchmaking/voting-quorum.js.map +1 -0
- package/dist/src/matchmaking/wire.d.ts +259 -0
- package/dist/src/matchmaking/wire.d.ts.map +1 -0
- package/dist/src/matchmaking/wire.js +484 -0
- package/dist/src/matchmaking/wire.js.map +1 -0
- package/dist/src/network/i-repo.d.ts +9 -0
- package/dist/src/network/i-repo.d.ts.map +1 -1
- package/dist/src/network/repo-protocol.d.ts +3 -1
- package/dist/src/network/repo-protocol.d.ts.map +1 -1
- package/dist/src/network/struct.d.ts +23 -1
- package/dist/src/network/struct.d.ts.map +1 -1
- package/dist/src/reactivity/backfill.d.ts +118 -0
- package/dist/src/reactivity/backfill.d.ts.map +1 -0
- package/dist/src/reactivity/backfill.js +137 -0
- package/dist/src/reactivity/backfill.js.map +1 -0
- package/dist/src/reactivity/backpressure.d.ts +99 -0
- package/dist/src/reactivity/backpressure.d.ts.map +1 -0
- package/dist/src/reactivity/backpressure.js +153 -0
- package/dist/src/reactivity/backpressure.js.map +1 -0
- package/dist/src/reactivity/checkpoint.d.ts +165 -0
- package/dist/src/reactivity/checkpoint.d.ts.map +1 -0
- package/dist/src/reactivity/checkpoint.js +232 -0
- package/dist/src/reactivity/checkpoint.js.map +1 -0
- package/dist/src/reactivity/config.d.ts +131 -0
- package/dist/src/reactivity/config.d.ts.map +1 -0
- package/dist/src/reactivity/config.js +135 -0
- package/dist/src/reactivity/config.js.map +1 -0
- package/dist/src/reactivity/dedupe.d.ts +51 -0
- package/dist/src/reactivity/dedupe.d.ts.map +1 -0
- package/dist/src/reactivity/dedupe.js +90 -0
- package/dist/src/reactivity/dedupe.js.map +1 -0
- package/dist/src/reactivity/forwarder.d.ts +50 -0
- package/dist/src/reactivity/forwarder.d.ts.map +1 -0
- package/dist/src/reactivity/forwarder.js +52 -0
- package/dist/src/reactivity/forwarder.js.map +1 -0
- package/dist/src/reactivity/index.d.ts +34 -0
- package/dist/src/reactivity/index.d.ts.map +1 -0
- package/dist/src/reactivity/index.js +34 -0
- package/dist/src/reactivity/index.js.map +1 -0
- package/dist/src/reactivity/notification.d.ts +72 -0
- package/dist/src/reactivity/notification.d.ts.map +1 -0
- package/dist/src/reactivity/notification.js +92 -0
- package/dist/src/reactivity/notification.js.map +1 -0
- package/dist/src/reactivity/policy.d.ts +59 -0
- package/dist/src/reactivity/policy.d.ts.map +1 -0
- package/dist/src/reactivity/policy.js +64 -0
- package/dist/src/reactivity/policy.js.map +1 -0
- package/dist/src/reactivity/push-state.d.ts +140 -0
- package/dist/src/reactivity/push-state.d.ts.map +1 -0
- package/dist/src/reactivity/push-state.js +270 -0
- package/dist/src/reactivity/push-state.js.map +1 -0
- package/dist/src/reactivity/recover.d.ts +75 -0
- package/dist/src/reactivity/recover.d.ts.map +1 -0
- package/dist/src/reactivity/recover.js +105 -0
- package/dist/src/reactivity/recover.js.map +1 -0
- package/dist/src/reactivity/replay-buffer.d.ts +57 -0
- package/dist/src/reactivity/replay-buffer.d.ts.map +1 -0
- package/dist/src/reactivity/replay-buffer.js +88 -0
- package/dist/src/reactivity/replay-buffer.js.map +1 -0
- package/dist/src/reactivity/resume.d.ts +214 -0
- package/dist/src/reactivity/resume.d.ts.map +1 -0
- package/dist/src/reactivity/resume.js +358 -0
- package/dist/src/reactivity/resume.js.map +1 -0
- package/dist/src/reactivity/rotation.d.ts +283 -0
- package/dist/src/reactivity/rotation.d.ts.map +1 -0
- package/dist/src/reactivity/rotation.js +265 -0
- package/dist/src/reactivity/rotation.js.map +1 -0
- package/dist/src/reactivity/subscriber.d.ts +66 -0
- package/dist/src/reactivity/subscriber.d.ts.map +1 -0
- package/dist/src/reactivity/subscriber.js +75 -0
- package/dist/src/reactivity/subscriber.js.map +1 -0
- package/dist/src/reactivity/subscription.d.ts +52 -0
- package/dist/src/reactivity/subscription.d.ts.map +1 -0
- package/dist/src/reactivity/subscription.js +28 -0
- package/dist/src/reactivity/subscription.js.map +1 -0
- package/dist/src/reactivity/topic-anchor.d.ts +46 -0
- package/dist/src/reactivity/topic-anchor.d.ts.map +1 -0
- package/dist/src/reactivity/topic-anchor.js +61 -0
- package/dist/src/reactivity/topic-anchor.js.map +1 -0
- package/dist/src/reactivity/verify.d.ts +41 -0
- package/dist/src/reactivity/verify.d.ts.map +1 -0
- package/dist/src/reactivity/verify.js +48 -0
- package/dist/src/reactivity/verify.js.map +1 -0
- package/dist/src/reactivity/wire-validate.d.ts +28 -0
- package/dist/src/reactivity/wire-validate.d.ts.map +1 -0
- package/dist/src/reactivity/wire-validate.js +79 -0
- package/dist/src/reactivity/wire-validate.js.map +1 -0
- package/dist/src/reactivity/wire.d.ts +102 -0
- package/dist/src/reactivity/wire.d.ts.map +1 -0
- package/dist/src/reactivity/wire.js +129 -0
- package/dist/src/reactivity/wire.js.map +1 -0
- package/dist/src/transaction/coordinator.d.ts +9 -5
- package/dist/src/transaction/coordinator.d.ts.map +1 -1
- package/dist/src/transaction/coordinator.js +48 -25
- package/dist/src/transaction/coordinator.js.map +1 -1
- package/dist/src/transactor/change-notifier.d.ts +74 -0
- package/dist/src/transactor/change-notifier.d.ts.map +1 -0
- package/dist/src/transactor/change-notifier.js +4 -0
- package/dist/src/transactor/change-notifier.js.map +1 -0
- package/dist/src/transactor/index.d.ts +1 -0
- package/dist/src/transactor/index.d.ts.map +1 -1
- package/dist/src/transactor/index.js +1 -0
- package/dist/src/transactor/index.js.map +1 -1
- package/dist/src/transactor/network-transactor.d.ts +34 -2
- package/dist/src/transactor/network-transactor.d.ts.map +1 -1
- package/dist/src/transactor/network-transactor.js +113 -13
- package/dist/src/transactor/network-transactor.js.map +1 -1
- package/package.json +2 -2
- package/src/cluster/structs.ts +13 -0
- package/src/cohort-topic/addressing.ts +112 -0
- package/src/cohort-topic/antidos/bootstrap-evidence-envelope.ts +253 -0
- package/src/cohort-topic/antidos/bootstrap-evidence.ts +94 -0
- package/src/cohort-topic/antidos/index.ts +5 -0
- package/src/cohort-topic/antidos/rate-limiter.ts +210 -0
- package/src/cohort-topic/antidos/replay-guard.ts +109 -0
- package/src/cohort-topic/antidos/topic-budget.ts +145 -0
- package/src/cohort-topic/antiflood/index.ts +2 -0
- package/src/cohort-topic/antiflood/invariants.ts +108 -0
- package/src/cohort-topic/antiflood/jitter.ts +117 -0
- package/src/cohort-topic/coldstart.ts +204 -0
- package/src/cohort-topic/dmax.ts +88 -0
- package/src/cohort-topic/gossip/bus.ts +217 -0
- package/src/cohort-topic/gossip/index.ts +3 -0
- package/src/cohort-topic/gossip/records.ts +45 -0
- package/src/cohort-topic/gossip/view.ts +66 -0
- package/src/cohort-topic/index.ts +20 -0
- package/src/cohort-topic/load/barometer.ts +134 -0
- package/src/cohort-topic/load/index.ts +1 -0
- package/src/cohort-topic/member-engine.ts +409 -0
- package/src/cohort-topic/membership/index.ts +3 -0
- package/src/cohort-topic/membership/publisher.ts +171 -0
- package/src/cohort-topic/membership/source.ts +41 -0
- package/src/cohort-topic/membership/verifier.ts +345 -0
- package/src/cohort-topic/ports.ts +157 -0
- package/src/cohort-topic/promotion.ts +384 -0
- package/src/cohort-topic/registration/bytes.ts +37 -0
- package/src/cohort-topic/registration/handoff.ts +154 -0
- package/src/cohort-topic/registration/index.ts +6 -0
- package/src/cohort-topic/registration/renewal.ts +423 -0
- package/src/cohort-topic/registration/sharding.ts +61 -0
- package/src/cohort-topic/registration/store.ts +81 -0
- package/src/cohort-topic/registration/types.ts +76 -0
- package/src/cohort-topic/ring-hash.ts +50 -0
- package/src/cohort-topic/service.ts +390 -0
- package/src/cohort-topic/sig/index.ts +2 -0
- package/src/cohort-topic/sig/payloads.ts +39 -0
- package/src/cohort-topic/sig/threshold.ts +64 -0
- package/src/cohort-topic/tiers.ts +74 -0
- package/src/cohort-topic/traffic.ts +211 -0
- package/src/cohort-topic/walk.ts +255 -0
- package/src/cohort-topic/willingness.ts +237 -0
- package/src/cohort-topic/wire/codec.ts +204 -0
- package/src/cohort-topic/wire/index.ts +16 -0
- package/src/cohort-topic/wire/payloads.ts +117 -0
- package/src/cohort-topic/wire/types.ts +343 -0
- package/src/cohort-topic/wire/validate.ts +478 -0
- package/src/collection/collection.ts +93 -1
- package/src/collections/tree/tree.ts +84 -3
- package/src/index.ts +3 -0
- package/src/log/log.ts +86 -7
- package/src/log/struct.ts +126 -2
- package/src/matchmaking/capability-filter.ts +45 -0
- package/src/matchmaking/config.ts +98 -0
- package/src/matchmaking/index.ts +21 -0
- package/src/matchmaking/multi-cohort-seeker.ts +234 -0
- package/src/matchmaking/provider.ts +123 -0
- package/src/matchmaking/query-eval.ts +105 -0
- package/src/matchmaking/seeker-walk.ts +127 -0
- package/src/matchmaking/seeker.ts +86 -0
- package/src/matchmaking/topic-anchor.ts +90 -0
- package/src/matchmaking/voting-quorum.ts +394 -0
- package/src/matchmaking/wire.ts +680 -0
- package/src/network/i-repo.ts +9 -0
- package/src/network/repo-protocol.ts +3 -2
- package/src/network/struct.ts +24 -1
- package/src/reactivity/backfill.ts +220 -0
- package/src/reactivity/backpressure.ts +191 -0
- package/src/reactivity/checkpoint.ts +308 -0
- package/src/reactivity/config.ts +172 -0
- package/src/reactivity/dedupe.ts +132 -0
- package/src/reactivity/forwarder.ts +87 -0
- package/src/reactivity/index.ts +34 -0
- package/src/reactivity/notification.ts +123 -0
- package/src/reactivity/policy.ts +79 -0
- package/src/reactivity/push-state.ts +343 -0
- package/src/reactivity/recover.ts +153 -0
- package/src/reactivity/replay-buffer.ts +141 -0
- package/src/reactivity/resume.ts +549 -0
- package/src/reactivity/rotation.ts +415 -0
- package/src/reactivity/subscriber.ts +132 -0
- package/src/reactivity/subscription.ts +66 -0
- package/src/reactivity/topic-anchor.ts +71 -0
- package/src/reactivity/verify.ts +73 -0
- package/src/reactivity/wire-validate.ts +87 -0
- package/src/reactivity/wire.ts +224 -0
- package/src/transaction/coordinator.ts +53 -27
- package/src/transactor/change-notifier.ts +80 -0
- package/src/transactor/index.ts +1 -0
- package/src/transactor/network-transactor.ts +133 -15
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../../src/cohort-topic/walk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort-topic substrate — per-member willingness / admission control.
|
|
3
|
+
*
|
|
4
|
+
* Transcribed from `docs/cohort-topic.md` §Willingness and §Tier ladder, folded back from the
|
|
5
|
+
* simulator-validated `packages/substrate-simulator/src/{willingness,backoff}.ts`. When FRET's
|
|
6
|
+
* `RouteAndMaybeAct` lands a `RegisterV1` on a member, that member runs this check and returns one
|
|
7
|
+
* of three outcomes:
|
|
8
|
+
*
|
|
9
|
+
* - **{@link AcceptedOutcome}** — the routed member is willing; it becomes `primary`.
|
|
10
|
+
* - **{@link UnwillingMemberOutcome}** — the routed member is personally unwilling, but the gossiped
|
|
11
|
+
* willingness vector says siblings will serve this tier; the caller retries a named sibling at the
|
|
12
|
+
* *same* coord (spatial move within the cohort).
|
|
13
|
+
* - **{@link UnwillingCohortOutcome}** — fewer than a quorum of members are willing to serve the
|
|
14
|
+
* tier, so the cohort declines the tier entirely; the caller backs off in *time* (no spatial
|
|
15
|
+
* move — see §Why the caller doesn't walk on UnwillingCohort). The `retryAfterMs` follows the
|
|
16
|
+
* capped-doubling curve in {@link backoffRetryMs}.
|
|
17
|
+
*
|
|
18
|
+
* A member's *live* willingness for a tier is: its profile serves the tier, the tier's load bucket
|
|
19
|
+
* is below `overloadBucket`, **and** it is under its per-tier primary-topic budget. The coarse 1-bit
|
|
20
|
+
* gossiped willingness vector ({@link selfWillingnessBits}) carries only profile-∧-load — the budget
|
|
21
|
+
* is a per-registration gate applied live at the routed member. (Resolved open question: willingness
|
|
22
|
+
* stays at **1 bit per tier** — no finer T3 gradations; the load bucket already supplies coarse load.)
|
|
23
|
+
*/
|
|
24
|
+
import { type LoadBarometerState } from "./load/barometer.js";
|
|
25
|
+
import type { CohortView } from "./gossip/view.js";
|
|
26
|
+
import type { RegisterV1 } from "./wire/types.js";
|
|
27
|
+
import { type NodeProfile, type Tier } from "./tiers.js";
|
|
28
|
+
/** The routed member is willing and will serve as `primary`. */
|
|
29
|
+
export interface AcceptedOutcome {
|
|
30
|
+
readonly kind: "accepted";
|
|
31
|
+
}
|
|
32
|
+
/** Routed member unwilling; these siblings (raw peer-id bytes) will serve — retry one at the same coord. */
|
|
33
|
+
export interface UnwillingMemberOutcome {
|
|
34
|
+
readonly kind: "unwilling_member";
|
|
35
|
+
readonly candidateMembers: Uint8Array[];
|
|
36
|
+
}
|
|
37
|
+
/** No quorum of willing members; back off `retryAfterMs` in time and retry from `d_max`. */
|
|
38
|
+
export interface UnwillingCohortOutcome {
|
|
39
|
+
readonly kind: "unwilling_cohort";
|
|
40
|
+
readonly retryAfterMs: number;
|
|
41
|
+
}
|
|
42
|
+
export type WillingnessOutcome = AcceptedOutcome | UnwillingMemberOutcome | UnwillingCohortOutcome;
|
|
43
|
+
/** Per-member willingness / admission check. */
|
|
44
|
+
export interface WillingnessCheck {
|
|
45
|
+
/** Classify `reg` routed onto this member, given the member's static profile and the clock. */
|
|
46
|
+
evaluate(reg: RegisterV1, self: NodeProfile, now: number): WillingnessOutcome;
|
|
47
|
+
}
|
|
48
|
+
/** Test bit `tier` (T0 = bit 0 … T3 = bit 3) of a packed 4-bit willingness vector. */
|
|
49
|
+
export declare function tierBit(bits: number, tier: Tier): boolean;
|
|
50
|
+
/** Pack a per-tier predicate into a 4-bit willingness vector (bit `t` set iff `willing(t)`). */
|
|
51
|
+
export declare function packWillingnessBits(willing: (tier: Tier) => boolean): number;
|
|
52
|
+
/** The packed vector as a single hex nibble — the `CohortGossipV1.willingnessBits` wire form. */
|
|
53
|
+
export declare function willingnessBitsHex(bits: number): string;
|
|
54
|
+
/**
|
|
55
|
+
* This member's gossiped (coarse) willingness vector: bit `t` set iff the profile serves `t` and the
|
|
56
|
+
* tier is not shed under load. The per-tier primary-topic budget is deliberately **not** folded in
|
|
57
|
+
* — it is a live per-registration gate, not a gossiped signal (§Willingness: the gossiped vector is
|
|
58
|
+
* "one bit per tier per member… refreshed every gossip round").
|
|
59
|
+
*/
|
|
60
|
+
export declare function selfWillingnessBits(self: NodeProfile, barometer: LoadBarometerState): number;
|
|
61
|
+
export interface BackoffConfig {
|
|
62
|
+
/** First-rejection delay (ms). Default 1000. */
|
|
63
|
+
readonly baseMs: number;
|
|
64
|
+
/** Geometric growth per rejection. Default 2 (doubling). */
|
|
65
|
+
readonly factor: number;
|
|
66
|
+
/** Hard ceiling on a single delay (ms). Default 60000. */
|
|
67
|
+
readonly capMs: number;
|
|
68
|
+
}
|
|
69
|
+
/** Settled back-off curve (`docs/cohort-topic.md` §Willingness): `base = 1 s`, `factor = 2`, `cap = 60 s`. */
|
|
70
|
+
export declare const DEFAULT_BACKOFF_CONFIG: BackoffConfig;
|
|
71
|
+
/**
|
|
72
|
+
* `retryAfter` for the `attempt`-th rejection (0-based): `⌊base · factor^attempt⌋` capped at `capMs`.
|
|
73
|
+
* The capped doubling bounds the rejections a participant suffers across an overload window at
|
|
74
|
+
* `O(log(window/base))` (≤ ~6 to span 60 s) rather than the `window/base` a fixed interval incurs.
|
|
75
|
+
* As survivors of a burst back off geometrically, offered load sheds and accepted/sec holds at the
|
|
76
|
+
* willing-quorum capacity without a cascade.
|
|
77
|
+
*/
|
|
78
|
+
export declare function backoffRetryMs(attempt: number, config?: BackoffConfig): number;
|
|
79
|
+
export interface WillingnessConfig {
|
|
80
|
+
/** Cohort size `k` (drives the default quorum). Default 16. */
|
|
81
|
+
cohortSize?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Members that must be willing to serve a tier for the cohort to take it on. Default: strict
|
|
84
|
+
* majority of `cohortSize` (`⌊k/2⌋ + 1`). Not pinned by `docs/cohort-topic.md` — §Tier ladder
|
|
85
|
+
* only requires "a quorum"; configurable here, revisitable by the Edge/Core policy ticket.
|
|
86
|
+
*/
|
|
87
|
+
quorum?: number;
|
|
88
|
+
/** Load bucket at/above which a tier is shed. Default {@link DEFAULT_OVERLOAD_BUCKET} (6). */
|
|
89
|
+
overloadBucket?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Max topics this member may be `primary` for at a single tier. Default 2048 (`topics_max`).
|
|
92
|
+
* The doc names the per-member per-tier budget but pins no number; configurable here.
|
|
93
|
+
*/
|
|
94
|
+
maxPrimaryTopicsPerTier?: number;
|
|
95
|
+
/** Back-off curve for `unwilling_cohort` retries. Default {@link DEFAULT_BACKOFF_CONFIG}. */
|
|
96
|
+
backoff?: BackoffConfig;
|
|
97
|
+
}
|
|
98
|
+
export interface WillingnessDeps {
|
|
99
|
+
/** This member's own per-tier load barometer (live willingness uses its buckets). */
|
|
100
|
+
barometer: LoadBarometerState;
|
|
101
|
+
/** Merged per-member gossip view — the sibling willingness vectors. */
|
|
102
|
+
view: CohortView;
|
|
103
|
+
/** This member's own id, base64url (the `fromMember` key) — excluded from the sibling scan. */
|
|
104
|
+
selfMember: string;
|
|
105
|
+
/** Count of topics this member is already `primary` for at `tier` (the budget gate input). */
|
|
106
|
+
primaryTopicCount: (tier: Tier) => number;
|
|
107
|
+
/**
|
|
108
|
+
* Rejection-attempt count for `reg`, driving the `retryAfter` curve. The anti-DoS rate limiter
|
|
109
|
+
* owns the counter; the *curve* lives here. Default `() => 0` (first-rejection delay).
|
|
110
|
+
*/
|
|
111
|
+
attempts?: (reg: RegisterV1) => number;
|
|
112
|
+
config?: WillingnessConfig;
|
|
113
|
+
}
|
|
114
|
+
/** Default quorum: strict majority of the cohort. */
|
|
115
|
+
export declare function defaultQuorum(cohortSize: number): number;
|
|
116
|
+
/** Build a {@link WillingnessCheck} over the injected barometer + gossip view + budget source. */
|
|
117
|
+
export declare function createWillingnessCheck(deps: WillingnessDeps): WillingnessCheck;
|
|
118
|
+
/** Convenience: a willingness check with a fresh idle barometer (tests / single-tier callers). */
|
|
119
|
+
export declare function createWillingnessCheckWithIdleBarometer(deps: Omit<WillingnessDeps, "barometer">): {
|
|
120
|
+
check: WillingnessCheck;
|
|
121
|
+
barometer: LoadBarometerState;
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=willingness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"willingness.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/willingness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort-topic substrate — per-member willingness / admission control.
|
|
3
|
+
*
|
|
4
|
+
* Transcribed from `docs/cohort-topic.md` §Willingness and §Tier ladder, folded back from the
|
|
5
|
+
* simulator-validated `packages/substrate-simulator/src/{willingness,backoff}.ts`. When FRET's
|
|
6
|
+
* `RouteAndMaybeAct` lands a `RegisterV1` on a member, that member runs this check and returns one
|
|
7
|
+
* of three outcomes:
|
|
8
|
+
*
|
|
9
|
+
* - **{@link AcceptedOutcome}** — the routed member is willing; it becomes `primary`.
|
|
10
|
+
* - **{@link UnwillingMemberOutcome}** — the routed member is personally unwilling, but the gossiped
|
|
11
|
+
* willingness vector says siblings will serve this tier; the caller retries a named sibling at the
|
|
12
|
+
* *same* coord (spatial move within the cohort).
|
|
13
|
+
* - **{@link UnwillingCohortOutcome}** — fewer than a quorum of members are willing to serve the
|
|
14
|
+
* tier, so the cohort declines the tier entirely; the caller backs off in *time* (no spatial
|
|
15
|
+
* move — see §Why the caller doesn't walk on UnwillingCohort). The `retryAfterMs` follows the
|
|
16
|
+
* capped-doubling curve in {@link backoffRetryMs}.
|
|
17
|
+
*
|
|
18
|
+
* A member's *live* willingness for a tier is: its profile serves the tier, the tier's load bucket
|
|
19
|
+
* is below `overloadBucket`, **and** it is under its per-tier primary-topic budget. The coarse 1-bit
|
|
20
|
+
* gossiped willingness vector ({@link selfWillingnessBits}) carries only profile-∧-load — the budget
|
|
21
|
+
* is a per-registration gate applied live at the routed member. (Resolved open question: willingness
|
|
22
|
+
* stays at **1 bit per tier** — no finer T3 gradations; the load bucket already supplies coarse load.)
|
|
23
|
+
*/
|
|
24
|
+
import { createLoadBarometer, DEFAULT_OVERLOAD_BUCKET } from "./load/barometer.js";
|
|
25
|
+
import { b64urlToBytes } from "./wire/codec.js";
|
|
26
|
+
import { ALL_TIERS } from "./tiers.js";
|
|
27
|
+
// --- willingness-vector bit packing (folded back from simulator `willingnessBits`) ---
|
|
28
|
+
/** Test bit `tier` (T0 = bit 0 … T3 = bit 3) of a packed 4-bit willingness vector. */
|
|
29
|
+
export function tierBit(bits, tier) {
|
|
30
|
+
return (bits & (1 << tier)) !== 0;
|
|
31
|
+
}
|
|
32
|
+
/** Pack a per-tier predicate into a 4-bit willingness vector (bit `t` set iff `willing(t)`). */
|
|
33
|
+
export function packWillingnessBits(willing) {
|
|
34
|
+
let bits = 0;
|
|
35
|
+
for (const t of ALL_TIERS) {
|
|
36
|
+
if (willing(t))
|
|
37
|
+
bits |= 1 << t;
|
|
38
|
+
}
|
|
39
|
+
return bits;
|
|
40
|
+
}
|
|
41
|
+
/** The packed vector as a single hex nibble — the `CohortGossipV1.willingnessBits` wire form. */
|
|
42
|
+
export function willingnessBitsHex(bits) {
|
|
43
|
+
return (bits & 0xf).toString(16);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* This member's gossiped (coarse) willingness vector: bit `t` set iff the profile serves `t` and the
|
|
47
|
+
* tier is not shed under load. The per-tier primary-topic budget is deliberately **not** folded in
|
|
48
|
+
* — it is a live per-registration gate, not a gossiped signal (§Willingness: the gossiped vector is
|
|
49
|
+
* "one bit per tier per member… refreshed every gossip round").
|
|
50
|
+
*/
|
|
51
|
+
export function selfWillingnessBits(self, barometer) {
|
|
52
|
+
return packWillingnessBits((t) => self.willingTiers.has(t) && barometer.loadWilling(t));
|
|
53
|
+
}
|
|
54
|
+
/** Settled back-off curve (`docs/cohort-topic.md` §Willingness): `base = 1 s`, `factor = 2`, `cap = 60 s`. */
|
|
55
|
+
export const DEFAULT_BACKOFF_CONFIG = {
|
|
56
|
+
baseMs: 1000,
|
|
57
|
+
factor: 2,
|
|
58
|
+
capMs: 60_000,
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* `retryAfter` for the `attempt`-th rejection (0-based): `⌊base · factor^attempt⌋` capped at `capMs`.
|
|
62
|
+
* The capped doubling bounds the rejections a participant suffers across an overload window at
|
|
63
|
+
* `O(log(window/base))` (≤ ~6 to span 60 s) rather than the `window/base` a fixed interval incurs.
|
|
64
|
+
* As survivors of a burst back off geometrically, offered load sheds and accepted/sec holds at the
|
|
65
|
+
* willing-quorum capacity without a cascade.
|
|
66
|
+
*/
|
|
67
|
+
export function backoffRetryMs(attempt, config = DEFAULT_BACKOFF_CONFIG) {
|
|
68
|
+
if (!Number.isInteger(attempt) || attempt < 0) {
|
|
69
|
+
throw new RangeError(`attempt must be a non-negative integer, got ${attempt}`);
|
|
70
|
+
}
|
|
71
|
+
const raw = config.baseMs * Math.pow(config.factor, attempt);
|
|
72
|
+
return Math.min(Math.floor(raw), config.capMs);
|
|
73
|
+
}
|
|
74
|
+
/** Default quorum: strict majority of the cohort. */
|
|
75
|
+
export function defaultQuorum(cohortSize) {
|
|
76
|
+
return Math.floor(cohortSize / 2) + 1;
|
|
77
|
+
}
|
|
78
|
+
class GossipWillingnessCheck {
|
|
79
|
+
deps;
|
|
80
|
+
quorum;
|
|
81
|
+
overloadBucket;
|
|
82
|
+
maxPrimaryTopicsPerTier;
|
|
83
|
+
backoff;
|
|
84
|
+
attempts;
|
|
85
|
+
constructor(deps) {
|
|
86
|
+
this.deps = deps;
|
|
87
|
+
const cfg = deps.config ?? {};
|
|
88
|
+
const cohortSize = cfg.cohortSize ?? 16;
|
|
89
|
+
this.quorum = cfg.quorum ?? defaultQuorum(cohortSize);
|
|
90
|
+
this.overloadBucket = cfg.overloadBucket ?? DEFAULT_OVERLOAD_BUCKET;
|
|
91
|
+
this.maxPrimaryTopicsPerTier = cfg.maxPrimaryTopicsPerTier ?? 2048;
|
|
92
|
+
this.backoff = cfg.backoff ?? DEFAULT_BACKOFF_CONFIG;
|
|
93
|
+
this.attempts = deps.attempts ?? (() => 0);
|
|
94
|
+
}
|
|
95
|
+
evaluate(reg, self, now) {
|
|
96
|
+
const tier = reg.tier;
|
|
97
|
+
if (!ALL_TIERS.includes(tier)) {
|
|
98
|
+
// An op tier outside T0..T3 is not serviceable; treat as a cohort-level decline.
|
|
99
|
+
return { kind: "unwilling_cohort", retryAfterMs: backoffRetryMs(this.attempts(reg), this.backoff) };
|
|
100
|
+
}
|
|
101
|
+
const selfWilling = this.selfLiveWilling(self, tier);
|
|
102
|
+
const siblings = this.willingSiblings(tier);
|
|
103
|
+
const willingCount = siblings.length + (selfWilling ? 1 : 0);
|
|
104
|
+
// Quorum gate (§Tier ladder): the cohort takes on tier-T duties only if a quorum of members
|
|
105
|
+
// is willing; otherwise registrations get UnwillingCohort and the caller backs off in time.
|
|
106
|
+
if (willingCount < this.quorum) {
|
|
107
|
+
return { kind: "unwilling_cohort", retryAfterMs: backoffRetryMs(this.attempts(reg), this.backoff) };
|
|
108
|
+
}
|
|
109
|
+
if (selfWilling) {
|
|
110
|
+
return { kind: "accepted" };
|
|
111
|
+
}
|
|
112
|
+
// Quorum holds and self is unwilling → some sibling will serve.
|
|
113
|
+
return { kind: "unwilling_member", candidateMembers: siblings.map((m) => b64urlToBytes(m)) };
|
|
114
|
+
}
|
|
115
|
+
/** Live willingness of *this* member for `tier`: profile ∧ load-under-threshold ∧ under budget. */
|
|
116
|
+
selfLiveWilling(self, tier) {
|
|
117
|
+
return (self.willingTiers.has(tier) &&
|
|
118
|
+
this.deps.barometer.bucket(tier) < this.overloadBucket &&
|
|
119
|
+
this.deps.primaryTopicCount(tier) < this.maxPrimaryTopicsPerTier);
|
|
120
|
+
}
|
|
121
|
+
/** Sibling member keys (base64url) whose *gossiped* willingness vector serves `tier`. */
|
|
122
|
+
willingSiblings(tier) {
|
|
123
|
+
const out = [];
|
|
124
|
+
for (const [member, contribution] of this.deps.view.all()) {
|
|
125
|
+
if (member === this.deps.selfMember)
|
|
126
|
+
continue; // self counted via live willingness
|
|
127
|
+
if (tierBit(contribution.willingness, tier)) {
|
|
128
|
+
out.push(member);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/** Build a {@link WillingnessCheck} over the injected barometer + gossip view + budget source. */
|
|
135
|
+
export function createWillingnessCheck(deps) {
|
|
136
|
+
return new GossipWillingnessCheck(deps);
|
|
137
|
+
}
|
|
138
|
+
/** Convenience: a willingness check with a fresh idle barometer (tests / single-tier callers). */
|
|
139
|
+
export function createWillingnessCheckWithIdleBarometer(deps) {
|
|
140
|
+
const barometer = createLoadBarometer({ overloadBucket: deps.config?.overloadBucket });
|
|
141
|
+
return { check: createWillingnessCheck({ ...deps, barometer }), barometer };
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=willingness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"willingness.js","sourceRoot":"","sources":["../../../src/cohort-topic/willingness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort-topic substrate — wire codec.
|
|
3
|
+
*
|
|
4
|
+
* Framing: every message is a 4-byte big-endian unsigned length prefix followed by the UTF-8
|
|
5
|
+
* JSON body, so a framed message is self-delimiting on a stream. Frames whose declared body
|
|
6
|
+
* length exceeds {@link DEFAULT_MAX_MESSAGE_BYTES} (or a caller-supplied ceiling) are rejected
|
|
7
|
+
* with {@link CohortWireError} before any allocation against the declared size.
|
|
8
|
+
*
|
|
9
|
+
* Byte fields travel as base64url (no padding); {@link bytesToB64url} / {@link b64urlToBytes}
|
|
10
|
+
* are the shared, cross-platform (browser/node/RN) helpers — no Node `Buffer`.
|
|
11
|
+
*/
|
|
12
|
+
import type { CohortGossipV1, DemotionNoticeV1, MembershipCertV1, PromotionNoticeV1, RegisterReplyV1, RegisterV1, RenewReplyV1, RenewV1, SignRequestV1, SignReplyV1 } from "./types.js";
|
|
13
|
+
/**
|
|
14
|
+
* Default ceiling on a framed body, in bytes. Sized conservatively at 1 MiB until the
|
|
15
|
+
* simulator-validated cohort-gossip worst case (`topics_max` topic summaries, see
|
|
16
|
+
* `docs/cohort-topic.md` §Configuration) is converted into an exact bound.
|
|
17
|
+
*
|
|
18
|
+
* TODO(cohort-topic): derive the exact ceiling from `topics_max` (2048) × the per-summary JSON
|
|
19
|
+
* size plus the willingness/load header, rather than this flat 1 MiB cap.
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_MAX_MESSAGE_BYTES: number;
|
|
22
|
+
/** Encode bytes as base64url with no padding. */
|
|
23
|
+
export declare function bytesToB64url(b: Uint8Array): string;
|
|
24
|
+
/** Decode a base64url string (no padding) to bytes. Throws {@link CohortWireError} on bad input. */
|
|
25
|
+
export declare function b64urlToBytes(s: string): Uint8Array;
|
|
26
|
+
/** Encode a V1 message as a length-prefixed UTF-8 JSON frame. */
|
|
27
|
+
export declare function encodeCohortMessage<T extends {
|
|
28
|
+
v: 1;
|
|
29
|
+
}>(msg: T, maxMessageBytes?: number): Uint8Array;
|
|
30
|
+
/** Strip the length prefix and `JSON.parse` the body. Throws {@link CohortWireError} on a malformed frame. */
|
|
31
|
+
export declare function decodeCohortMessage(bytes: Uint8Array, maxMessageBytes?: number): unknown;
|
|
32
|
+
export declare function decodeRegisterV1(bytes: Uint8Array, maxMessageBytes?: number): RegisterV1;
|
|
33
|
+
export declare function decodeRegisterReplyV1(bytes: Uint8Array, maxMessageBytes?: number): RegisterReplyV1;
|
|
34
|
+
export declare function decodeRenewV1(bytes: Uint8Array, maxMessageBytes?: number): RenewV1;
|
|
35
|
+
export declare function decodeRenewReplyV1(bytes: Uint8Array, maxMessageBytes?: number): RenewReplyV1;
|
|
36
|
+
export declare function decodePromotionNoticeV1(bytes: Uint8Array, maxMessageBytes?: number): PromotionNoticeV1;
|
|
37
|
+
export declare function decodeDemotionNoticeV1(bytes: Uint8Array, maxMessageBytes?: number): DemotionNoticeV1;
|
|
38
|
+
export declare function decodeCohortGossipV1(bytes: Uint8Array, maxMessageBytes?: number): CohortGossipV1;
|
|
39
|
+
export declare function decodeMembershipCertV1(bytes: Uint8Array, maxMessageBytes?: number): MembershipCertV1;
|
|
40
|
+
export declare function decodeSignRequestV1(bytes: Uint8Array, maxMessageBytes?: number): SignRequestV1;
|
|
41
|
+
export declare function decodeSignReplyV1(bytes: Uint8Array, maxMessageBytes?: number): SignReplyV1;
|
|
42
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/wire/codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAeH,OAAO,KAAK,EACX,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,OAAO,EACP,aAAa,EACb,WAAW,EACX,MAAM,YAAY,CAAC;AAEpB;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,QAAc,CAAC;AAmBrD,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAgBnD;AAED,oGAAoG;AACpG,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAkCnD;AAID,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,CAAC,EAAE,CAAC,CAAA;CAAE,EAAE,GAAG,EAAE,CAAC,EAAE,eAAe,GAAE,MAAkC,GAAG,UAAU,CAU/H;AAED,8GAA8G;AAC9G,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,GAAE,MAAkC,GAAG,OAAO,CAwBnH;AAID,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,UAAU,CAExF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,eAAe,CAElG;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAElF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,YAAY,CAE5F;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAEtG;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAEpG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,cAAc,CAEhG;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAEpG;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,aAAa,CAE9F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,WAAW,CAE1F"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort-topic substrate — wire codec.
|
|
3
|
+
*
|
|
4
|
+
* Framing: every message is a 4-byte big-endian unsigned length prefix followed by the UTF-8
|
|
5
|
+
* JSON body, so a framed message is self-delimiting on a stream. Frames whose declared body
|
|
6
|
+
* length exceeds {@link DEFAULT_MAX_MESSAGE_BYTES} (or a caller-supplied ceiling) are rejected
|
|
7
|
+
* with {@link CohortWireError} before any allocation against the declared size.
|
|
8
|
+
*
|
|
9
|
+
* Byte fields travel as base64url (no padding); {@link bytesToB64url} / {@link b64urlToBytes}
|
|
10
|
+
* are the shared, cross-platform (browser/node/RN) helpers — no Node `Buffer`.
|
|
11
|
+
*/
|
|
12
|
+
import { CohortWireError } from "./validate.js";
|
|
13
|
+
import { validateCohortGossipV1, validateDemotionNoticeV1, validateMembershipCertV1, validatePromotionNoticeV1, validateRegisterReplyV1, validateRegisterV1, validateRenewReplyV1, validateRenewV1, validateSignRequestV1, validateSignReplyV1, } from "./validate.js";
|
|
14
|
+
/**
|
|
15
|
+
* Default ceiling on a framed body, in bytes. Sized conservatively at 1 MiB until the
|
|
16
|
+
* simulator-validated cohort-gossip worst case (`topics_max` topic summaries, see
|
|
17
|
+
* `docs/cohort-topic.md` §Configuration) is converted into an exact bound.
|
|
18
|
+
*
|
|
19
|
+
* TODO(cohort-topic): derive the exact ceiling from `topics_max` (2048) × the per-summary JSON
|
|
20
|
+
* size plus the willingness/load header, rather than this flat 1 MiB cap.
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_MAX_MESSAGE_BYTES = 1024 * 1024;
|
|
23
|
+
const LENGTH_PREFIX_BYTES = 4;
|
|
24
|
+
const utf8Encoder = new TextEncoder();
|
|
25
|
+
const utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
26
|
+
// --- base64url helpers (no padding, cross-platform) ---
|
|
27
|
+
const B64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
28
|
+
const B64URL_LOOKUP = (() => {
|
|
29
|
+
const table = new Array(128).fill(-1);
|
|
30
|
+
for (let i = 0; i < B64URL_ALPHABET.length; i++) {
|
|
31
|
+
table[B64URL_ALPHABET.charCodeAt(i)] = i;
|
|
32
|
+
}
|
|
33
|
+
return table;
|
|
34
|
+
})();
|
|
35
|
+
/** Encode bytes as base64url with no padding. */
|
|
36
|
+
export function bytesToB64url(b) {
|
|
37
|
+
let out = "";
|
|
38
|
+
let i = 0;
|
|
39
|
+
for (; i + 3 <= b.length; i += 3) {
|
|
40
|
+
const n = (b[i] << 16) | (b[i + 1] << 8) | b[i + 2];
|
|
41
|
+
out += B64URL_ALPHABET[(n >> 18) & 63] + B64URL_ALPHABET[(n >> 12) & 63] + B64URL_ALPHABET[(n >> 6) & 63] + B64URL_ALPHABET[n & 63];
|
|
42
|
+
}
|
|
43
|
+
const rem = b.length - i;
|
|
44
|
+
if (rem === 1) {
|
|
45
|
+
const n = b[i] << 16;
|
|
46
|
+
out += B64URL_ALPHABET[(n >> 18) & 63] + B64URL_ALPHABET[(n >> 12) & 63];
|
|
47
|
+
}
|
|
48
|
+
else if (rem === 2) {
|
|
49
|
+
const n = (b[i] << 16) | (b[i + 1] << 8);
|
|
50
|
+
out += B64URL_ALPHABET[(n >> 18) & 63] + B64URL_ALPHABET[(n >> 12) & 63] + B64URL_ALPHABET[(n >> 6) & 63];
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
/** Decode a base64url string (no padding) to bytes. Throws {@link CohortWireError} on bad input. */
|
|
55
|
+
export function b64urlToBytes(s) {
|
|
56
|
+
const len = s.length;
|
|
57
|
+
if (len % 4 === 1) {
|
|
58
|
+
throw new CohortWireError("base64url: invalid length");
|
|
59
|
+
}
|
|
60
|
+
const fullGroups = len >> 2;
|
|
61
|
+
const rem = len & 3;
|
|
62
|
+
const outLen = fullGroups * 3 + (rem === 0 ? 0 : rem - 1);
|
|
63
|
+
const out = new Uint8Array(outLen);
|
|
64
|
+
let si = 0;
|
|
65
|
+
let oi = 0;
|
|
66
|
+
const sext = (ch) => {
|
|
67
|
+
const v = ch < 128 ? B64URL_LOOKUP[ch] : -1;
|
|
68
|
+
if (v < 0) {
|
|
69
|
+
throw new CohortWireError("base64url: invalid character");
|
|
70
|
+
}
|
|
71
|
+
return v;
|
|
72
|
+
};
|
|
73
|
+
for (let g = 0; g < fullGroups; g++) {
|
|
74
|
+
const n = (sext(s.charCodeAt(si)) << 18) | (sext(s.charCodeAt(si + 1)) << 12) | (sext(s.charCodeAt(si + 2)) << 6) | sext(s.charCodeAt(si + 3));
|
|
75
|
+
out[oi++] = (n >> 16) & 0xff;
|
|
76
|
+
out[oi++] = (n >> 8) & 0xff;
|
|
77
|
+
out[oi++] = n & 0xff;
|
|
78
|
+
si += 4;
|
|
79
|
+
}
|
|
80
|
+
if (rem === 2) {
|
|
81
|
+
const n = (sext(s.charCodeAt(si)) << 18) | (sext(s.charCodeAt(si + 1)) << 12);
|
|
82
|
+
out[oi++] = (n >> 16) & 0xff;
|
|
83
|
+
}
|
|
84
|
+
else if (rem === 3) {
|
|
85
|
+
const n = (sext(s.charCodeAt(si)) << 18) | (sext(s.charCodeAt(si + 1)) << 12) | (sext(s.charCodeAt(si + 2)) << 6);
|
|
86
|
+
out[oi++] = (n >> 16) & 0xff;
|
|
87
|
+
out[oi++] = (n >> 8) & 0xff;
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
// --- framing ---
|
|
92
|
+
/** Encode a V1 message as a length-prefixed UTF-8 JSON frame. */
|
|
93
|
+
export function encodeCohortMessage(msg, maxMessageBytes = DEFAULT_MAX_MESSAGE_BYTES) {
|
|
94
|
+
const body = utf8Encoder.encode(JSON.stringify(msg));
|
|
95
|
+
if (body.length > maxMessageBytes) {
|
|
96
|
+
throw new CohortWireError(`message body ${body.length} exceeds max_message_bytes ${maxMessageBytes}`);
|
|
97
|
+
}
|
|
98
|
+
const frame = new Uint8Array(LENGTH_PREFIX_BYTES + body.length);
|
|
99
|
+
const view = new DataView(frame.buffer);
|
|
100
|
+
view.setUint32(0, body.length, false);
|
|
101
|
+
frame.set(body, LENGTH_PREFIX_BYTES);
|
|
102
|
+
return frame;
|
|
103
|
+
}
|
|
104
|
+
/** Strip the length prefix and `JSON.parse` the body. Throws {@link CohortWireError} on a malformed frame. */
|
|
105
|
+
export function decodeCohortMessage(bytes, maxMessageBytes = DEFAULT_MAX_MESSAGE_BYTES) {
|
|
106
|
+
if (bytes.length < LENGTH_PREFIX_BYTES) {
|
|
107
|
+
throw new CohortWireError("frame too short for length prefix");
|
|
108
|
+
}
|
|
109
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
110
|
+
const declared = view.getUint32(0, false);
|
|
111
|
+
if (declared > maxMessageBytes) {
|
|
112
|
+
throw new CohortWireError(`declared body length ${declared} exceeds max_message_bytes ${maxMessageBytes}`);
|
|
113
|
+
}
|
|
114
|
+
if (LENGTH_PREFIX_BYTES + declared !== bytes.length) {
|
|
115
|
+
throw new CohortWireError(`frame length mismatch: declared ${declared}, have ${bytes.length - LENGTH_PREFIX_BYTES}`);
|
|
116
|
+
}
|
|
117
|
+
const body = bytes.subarray(LENGTH_PREFIX_BYTES, LENGTH_PREFIX_BYTES + declared);
|
|
118
|
+
let text;
|
|
119
|
+
try {
|
|
120
|
+
text = utf8Decoder.decode(body);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
throw new CohortWireError("frame body is not valid UTF-8");
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
return JSON.parse(text);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
throw new CohortWireError("frame body is not valid JSON");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// --- typed decoders (decode frame → validate → narrow) ---
|
|
133
|
+
export function decodeRegisterV1(bytes, maxMessageBytes) {
|
|
134
|
+
return validateRegisterV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
135
|
+
}
|
|
136
|
+
export function decodeRegisterReplyV1(bytes, maxMessageBytes) {
|
|
137
|
+
return validateRegisterReplyV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
138
|
+
}
|
|
139
|
+
export function decodeRenewV1(bytes, maxMessageBytes) {
|
|
140
|
+
return validateRenewV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
141
|
+
}
|
|
142
|
+
export function decodeRenewReplyV1(bytes, maxMessageBytes) {
|
|
143
|
+
return validateRenewReplyV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
144
|
+
}
|
|
145
|
+
export function decodePromotionNoticeV1(bytes, maxMessageBytes) {
|
|
146
|
+
return validatePromotionNoticeV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
147
|
+
}
|
|
148
|
+
export function decodeDemotionNoticeV1(bytes, maxMessageBytes) {
|
|
149
|
+
return validateDemotionNoticeV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
150
|
+
}
|
|
151
|
+
export function decodeCohortGossipV1(bytes, maxMessageBytes) {
|
|
152
|
+
return validateCohortGossipV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
153
|
+
}
|
|
154
|
+
export function decodeMembershipCertV1(bytes, maxMessageBytes) {
|
|
155
|
+
return validateMembershipCertV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
156
|
+
}
|
|
157
|
+
export function decodeSignRequestV1(bytes, maxMessageBytes) {
|
|
158
|
+
return validateSignRequestV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
159
|
+
}
|
|
160
|
+
export function decodeSignReplyV1(bytes, maxMessageBytes) {
|
|
161
|
+
return validateSignReplyV1(decodeCohortMessage(bytes, maxMessageBytes));
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../../../../src/cohort-topic/wire/codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACN,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAcvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,GAAG,IAAI,CAAC;AAErD,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE9D,yDAAyD;AAEzD,MAAM,eAAe,GAAG,kEAAkE,CAAC;AAE3F,MAAM,aAAa,GAA0B,CAAC,GAAa,EAAE;IAC5D,MAAM,KAAK,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC,EAAE,CAAC;AAEL,iDAAiD;AACjD,MAAM,UAAU,aAAa,CAAC,CAAa;IAC1C,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QACvD,GAAG,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAE,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAE,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAE,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAAE,CAAC;IACzI,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,IAAI,EAAE,CAAC;QACtB,GAAG,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAE,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAE,CAAC;IAC5E,CAAC;SAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,CAAC;QAC3C,GAAG,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAE,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAE,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAE,CAAC;IAC9G,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,aAAa,CAAC,CAAS;IACtC,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;IACrB,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,eAAe,CAAC,2BAA2B,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IACpB,MAAM,MAAM,GAAG,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,MAAM,IAAI,GAAG,CAAC,EAAU,EAAU,EAAE;QACnC,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,eAAe,CAAC,8BAA8B,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,CAAC,CAAC;IACV,CAAC,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/I,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QAC7B,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QAC5B,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACrB,EAAE,IAAI,CAAC,CAAC;IACT,CAAC;IACD,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9E,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IAC9B,CAAC;SAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAClH,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QAC7B,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,kBAAkB;AAElB,iEAAiE;AACjE,MAAM,UAAU,mBAAmB,CAAqB,GAAM,EAAE,kBAA0B,yBAAyB;IAClH,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,IAAI,IAAI,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACnC,MAAM,IAAI,eAAe,CAAC,gBAAgB,IAAI,CAAC,MAAM,8BAA8B,eAAe,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACtC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC;AACd,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,mBAAmB,CAAC,KAAiB,EAAE,kBAA0B,yBAAyB;IACzG,IAAI,KAAK,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACxC,MAAM,IAAI,eAAe,CAAC,mCAAmC,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,QAAQ,GAAG,eAAe,EAAE,CAAC;QAChC,MAAM,IAAI,eAAe,CAAC,wBAAwB,QAAQ,8BAA8B,eAAe,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,mBAAmB,GAAG,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;QACrD,MAAM,IAAI,eAAe,CAAC,mCAAmC,QAAQ,UAAU,KAAK,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC,CAAC;IACtH,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,QAAQ,CAAC,CAAC;IACjF,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACJ,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,eAAe,CAAC,+BAA+B,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,eAAe,CAAC,8BAA8B,CAAC,CAAC;IAC3D,CAAC;AACF,CAAC;AAED,4DAA4D;AAE5D,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAE,eAAwB;IAC3E,OAAO,kBAAkB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAiB,EAAE,eAAwB;IAChF,OAAO,uBAAuB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAiB,EAAE,eAAwB;IACxE,OAAO,eAAe,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAiB,EAAE,eAAwB;IAC7E,OAAO,oBAAoB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAiB,EAAE,eAAwB;IAClF,OAAO,yBAAyB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAiB,EAAE,eAAwB;IACjF,OAAO,wBAAwB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAiB,EAAE,eAAwB;IAC/E,OAAO,sBAAsB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAiB,EAAE,eAAwB;IACjF,OAAO,wBAAwB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAiB,EAAE,eAAwB;IAC9E,OAAO,qBAAqB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAiB,EAAE,eAAwB;IAC5E,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./codec.js";
|
|
3
|
+
export * from "./payloads.js";
|
|
4
|
+
export { CohortWireError } from "./validate.js";
|
|
5
|
+
export { validateRegisterV1, validateRegisterReplyV1, validateRenewV1, validateRenewReplyV1, validatePromotionNoticeV1, validateDemotionNoticeV1, validateCohortGossipV1, validateMembershipCertV1, validateSignRequestV1, validateSignReplyV1, } from "./validate.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/wire/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./codec.js";
|
|
3
|
+
export * from "./payloads.js";
|
|
4
|
+
export { CohortWireError } from "./validate.js";
|
|
5
|
+
export { validateRegisterV1, validateRegisterReplyV1, validateRenewV1, validateRenewReplyV1, validatePromotionNoticeV1, validateDemotionNoticeV1, validateCohortGossipV1, validateMembershipCertV1, validateSignRequestV1, validateSignReplyV1, } from "./validate.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cohort-topic/wire/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort-topic substrate — canonical participant-signature payloads.
|
|
3
|
+
*
|
|
4
|
+
* A participant peer-key-signs its outbound `RegisterV1` / `RenewV1` bodies (db-p2p supplies the
|
|
5
|
+
* libp2p peer key); a cohort member recomputes the identical byte image to verify that signature
|
|
6
|
+
* before admitting a register (anti-DoS) or honoring a crash-failover `reattach` attestation (so a
|
|
7
|
+
* stray/MITM'd ping cannot usurp a live primary — `docs/cohort-topic.md` §TTL and renewal).
|
|
8
|
+
*
|
|
9
|
+
* Signer and verifier must agree byte-for-byte. Exactly like {@link import("../sig/payloads.js")}
|
|
10
|
+
* for the threshold-signed notices, determinism comes from encoding an explicitly-ordered JSON
|
|
11
|
+
* array (array order is stable, unlike object key order) as UTF-8 — never the `signature` envelope.
|
|
12
|
+
* Optional fields are normalized to a fixed placeholder (`bootstrap`→`false`, `probe`→`false`,
|
|
13
|
+
* `appPayload`→`null`, `bootstrapEvidence`→`null` with an empty string treated as absent,
|
|
14
|
+
* `reattach`→`false`, `withdraw`→`false`) so an absent optional and a present-but-default optional can
|
|
15
|
+
* never disagree across the wire round-trip.
|
|
16
|
+
*/
|
|
17
|
+
import type { CohortGossipV1, RegisterV1, RenewV1 } from "./types.js";
|
|
18
|
+
/** A `RegisterV1` minus its `signature` envelope — the bytes the participant peer-key-signs. */
|
|
19
|
+
export type RegisterSignable = Omit<RegisterV1, "signature">;
|
|
20
|
+
/** A `RenewV1` minus its `signature` envelope — the bytes the participant peer-key-signs. */
|
|
21
|
+
export type RenewSignable = Omit<RenewV1, "signature">;
|
|
22
|
+
/** Canonical signed byte image of a `RegisterV1` body (every field except `signature`). */
|
|
23
|
+
export declare function registerSigningPayload(body: RegisterSignable): Uint8Array;
|
|
24
|
+
/** Canonical signed byte image of a `RenewV1` body (every field except `signature`). */
|
|
25
|
+
export declare function renewSigningPayload(body: RenewSignable): Uint8Array;
|
|
26
|
+
/** A `CohortGossipV1` minus its `signature` envelope — the bytes the gossiping member peer-key-signs. */
|
|
27
|
+
export type CohortGossipSignable = Omit<CohortGossipV1, "signature">;
|
|
28
|
+
/**
|
|
29
|
+
* Canonical signed byte image of a `CohortGossipV1` (every field except `signature`). Intra-cohort
|
|
30
|
+
* gossip is peer-key-signed by the originating member so a receiver can drop a frame whose `fromMember`
|
|
31
|
+
* signature does not verify or that comes from a non-cohort member (it can never spoof willingness/load
|
|
32
|
+
* or replicate forged records). Like the other payload helpers, determinism comes from an
|
|
33
|
+
* explicitly-ordered array — nested records/summaries/evictions are emitted as fixed ordered tuples so
|
|
34
|
+
* the signer and the receiver (which re-derives this image from the validated frame) agree byte-for-byte.
|
|
35
|
+
* Absent optionals (`records`/`evicted`) normalize to `[]`, and `appState` to `null`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function cohortGossipSigningPayload(g: CohortGossipSignable): Uint8Array;
|
|
38
|
+
//# sourceMappingURL=payloads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payloads.d.ts","sourceRoot":"","sources":["../../../../src/cohort-topic/wire/payloads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAItE,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAE7D,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAOvD,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,UAAU,CAkBzE;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,UAAU,CAenE;AAED,yGAAyG;AACzG,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAErE;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,oBAAoB,GAAG,UAAU,CAiC9E"}
|