@optimystic/db-core 0.22.0 → 0.24.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.
Files changed (141) hide show
  1. package/README.md +336 -336
  2. package/dist/src/cluster/structs.d.ts +39 -1
  3. package/dist/src/cluster/structs.d.ts.map +1 -1
  4. package/dist/src/cluster/structs.js +24 -0
  5. package/dist/src/cluster/structs.js.map +1 -1
  6. package/dist/src/collection/collection.d.ts +17 -0
  7. package/dist/src/collection/collection.d.ts.map +1 -1
  8. package/dist/src/collection/collection.js +24 -2
  9. package/dist/src/collection/collection.js.map +1 -1
  10. package/dist/src/collections/tree/tree.d.ts +5 -0
  11. package/dist/src/collections/tree/tree.d.ts.map +1 -1
  12. package/dist/src/collections/tree/tree.js +7 -0
  13. package/dist/src/collections/tree/tree.js.map +1 -1
  14. package/dist/src/network/i-peer-network.d.ts +16 -0
  15. package/dist/src/network/i-peer-network.d.ts.map +1 -1
  16. package/dist/src/network/struct.d.ts +39 -2
  17. package/dist/src/network/struct.d.ts.map +1 -1
  18. package/dist/src/network/struct.js +18 -0
  19. package/dist/src/network/struct.js.map +1 -1
  20. package/dist/src/testing/test-transactor.d.ts +95 -8
  21. package/dist/src/testing/test-transactor.d.ts.map +1 -1
  22. package/dist/src/testing/test-transactor.js +121 -8
  23. package/dist/src/testing/test-transactor.js.map +1 -1
  24. package/dist/src/transaction/transaction.d.ts +1 -1
  25. package/dist/src/transaction/transaction.js +1 -1
  26. package/dist/src/transactor/network-transactor.d.ts.map +1 -1
  27. package/dist/src/transactor/network-transactor.js +48 -13
  28. package/dist/src/transactor/network-transactor.js.map +1 -1
  29. package/dist/src/transactor/transactor-source.d.ts.map +1 -1
  30. package/dist/src/transactor/transactor-source.js +25 -2
  31. package/dist/src/transactor/transactor-source.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/cluster/membership.ts +85 -85
  34. package/src/cluster/structs.ts +43 -4
  35. package/src/cohort-topic/addressing.ts +120 -120
  36. package/src/cohort-topic/antidos/bootstrap-evidence-envelope.ts +253 -253
  37. package/src/cohort-topic/antidos/bootstrap-evidence.ts +106 -106
  38. package/src/cohort-topic/antidos/index.ts +5 -5
  39. package/src/cohort-topic/antidos/rate-limiter.ts +210 -210
  40. package/src/cohort-topic/antidos/replay-guard.ts +146 -146
  41. package/src/cohort-topic/antidos/topic-budget.ts +160 -160
  42. package/src/cohort-topic/antiflood/index.ts +2 -2
  43. package/src/cohort-topic/antiflood/invariants.ts +108 -108
  44. package/src/cohort-topic/antiflood/jitter.ts +117 -117
  45. package/src/cohort-topic/coldstart.ts +237 -237
  46. package/src/cohort-topic/dmax.ts +88 -88
  47. package/src/cohort-topic/gossip/bus.ts +254 -254
  48. package/src/cohort-topic/gossip/index.ts +3 -3
  49. package/src/cohort-topic/gossip/records.ts +45 -45
  50. package/src/cohort-topic/gossip/view.ts +91 -91
  51. package/src/cohort-topic/index.ts +20 -20
  52. package/src/cohort-topic/load/barometer.ts +134 -134
  53. package/src/cohort-topic/load/index.ts +1 -1
  54. package/src/cohort-topic/member-engine.ts +430 -430
  55. package/src/cohort-topic/membership/index.ts +3 -3
  56. package/src/cohort-topic/membership/publisher.ts +163 -163
  57. package/src/cohort-topic/membership/source.ts +41 -41
  58. package/src/cohort-topic/membership/verifier.ts +461 -461
  59. package/src/cohort-topic/ports.ts +157 -157
  60. package/src/cohort-topic/promotion.ts +405 -405
  61. package/src/cohort-topic/registration/bytes.ts +37 -37
  62. package/src/cohort-topic/registration/handoff.ts +154 -154
  63. package/src/cohort-topic/registration/index.ts +6 -6
  64. package/src/cohort-topic/registration/renewal.ts +495 -495
  65. package/src/cohort-topic/registration/sharding.ts +61 -61
  66. package/src/cohort-topic/registration/store.ts +81 -81
  67. package/src/cohort-topic/registration/types.ts +91 -91
  68. package/src/cohort-topic/ring-hash.ts +50 -50
  69. package/src/cohort-topic/service.ts +416 -416
  70. package/src/cohort-topic/sig/index.ts +2 -2
  71. package/src/cohort-topic/sig/payloads.ts +59 -59
  72. package/src/cohort-topic/sig/threshold.ts +64 -64
  73. package/src/cohort-topic/tiers.ts +74 -74
  74. package/src/cohort-topic/traffic.ts +233 -233
  75. package/src/cohort-topic/walk.ts +326 -326
  76. package/src/cohort-topic/willingness.ts +237 -237
  77. package/src/cohort-topic/wire/codec.ts +216 -216
  78. package/src/cohort-topic/wire/index.ts +18 -18
  79. package/src/cohort-topic/wire/payloads.ts +126 -126
  80. package/src/cohort-topic/wire/primitives.ts +188 -188
  81. package/src/cohort-topic/wire/types.ts +475 -475
  82. package/src/cohort-topic/wire/validate.ts +512 -512
  83. package/src/collection/collection-type-registry.ts +37 -37
  84. package/src/collection/collection.ts +25 -2
  85. package/src/collections/diary/diary.ts +68 -68
  86. package/src/collections/tree/readme.md +4 -0
  87. package/src/collections/tree/tree.ts +320 -312
  88. package/src/matchmaking/capability-filter.ts +45 -45
  89. package/src/matchmaking/config.ts +98 -98
  90. package/src/matchmaking/index.ts +21 -21
  91. package/src/matchmaking/multi-cohort-seeker.ts +234 -234
  92. package/src/matchmaking/provider.ts +123 -123
  93. package/src/matchmaking/query-eval.ts +105 -105
  94. package/src/matchmaking/seeker-walk.ts +127 -127
  95. package/src/matchmaking/seeker.ts +86 -86
  96. package/src/matchmaking/topic-anchor.ts +90 -90
  97. package/src/matchmaking/voting-quorum.ts +394 -394
  98. package/src/matchmaking/wire.ts +603 -603
  99. package/src/network/i-peer-network.ts +17 -0
  100. package/src/network/stale-failure.ts +43 -43
  101. package/src/network/struct.ts +41 -2
  102. package/src/network/types.ts +37 -37
  103. package/src/reactivity/backfill.ts +220 -220
  104. package/src/reactivity/backpressure.ts +191 -191
  105. package/src/reactivity/checkpoint.ts +308 -308
  106. package/src/reactivity/config.ts +172 -172
  107. package/src/reactivity/dedupe.ts +132 -132
  108. package/src/reactivity/forwarder.ts +87 -87
  109. package/src/reactivity/index.ts +34 -34
  110. package/src/reactivity/notification.ts +123 -123
  111. package/src/reactivity/policy.ts +79 -79
  112. package/src/reactivity/push-state.ts +310 -310
  113. package/src/reactivity/recover.ts +153 -153
  114. package/src/reactivity/replay-buffer.ts +141 -141
  115. package/src/reactivity/resume.ts +549 -549
  116. package/src/reactivity/rotation.ts +415 -415
  117. package/src/reactivity/subscriber.ts +132 -132
  118. package/src/reactivity/subscription.ts +66 -66
  119. package/src/reactivity/topic-anchor.ts +71 -71
  120. package/src/reactivity/verify.ts +73 -73
  121. package/src/reactivity/wire-validate.ts +13 -13
  122. package/src/reactivity/wire.ts +224 -224
  123. package/src/testing/async-wait.ts +65 -65
  124. package/src/testing/index.ts +2 -2
  125. package/src/testing/test-transactor.ts +638 -502
  126. package/src/transaction/errors.ts +91 -91
  127. package/src/transaction/operations-hash.ts +196 -196
  128. package/src/transaction/read-dependency-collector.ts +78 -78
  129. package/src/transaction/transaction.ts +1 -1
  130. package/src/transactor/change-notifier.ts +80 -80
  131. package/src/transactor/index.ts +5 -5
  132. package/src/transactor/network-transactor.ts +49 -14
  133. package/src/transactor/transactor-source.ts +25 -2
  134. package/src/transform/atomic-proxy.ts +92 -92
  135. package/src/transform/helpers.ts +159 -159
  136. package/src/utility/backoff.ts +95 -95
  137. package/src/utility/batch-coordinator.ts +191 -191
  138. package/dist/src/transaction/context.d.ts +0 -60
  139. package/dist/src/transaction/context.d.ts.map +0 -1
  140. package/dist/src/transaction/context.js +0 -91
  141. package/dist/src/transaction/context.js.map +0 -1
@@ -1,157 +1,157 @@
1
- /**
2
- * Cohort-topic substrate — transport ports.
3
- *
4
- * These are the seams that keep the cohort-topic substrate split cleanly across packages:
5
- * db-core defines the interfaces here (pure logic depends only on a hash function and
6
- * byte-array peer IDs), and db-p2p supplies the concrete FRET + libp2p implementations.
7
- *
8
- * **db-core never imports FRET or libp2p.** Every db-core substrate module takes these ports
9
- * by injection (constructor / factory args); db-p2p constructs the FRET-backed versions and
10
- * composes them with the db-core logic in `CohortTopicService`'s transport host.
11
- *
12
- * See `docs/cohort-topic.md` §FRET integration and `tickets` slug
13
- * `cohort-topic-package-layering` for the authoritative layering rule.
14
- */
15
-
16
- import type { MembershipCertV1 } from "./wire/types.js";
17
-
18
- /**
19
- * Ring coordinate — SHA-256 truncated to the ring width `B` (see {@link IRingHash}). db-core
20
- * owns this type; db-p2p maps it onto FRET's coordinate type, ensuring the byte representation
21
- * matches FRET's ring width so routing keys line up on the wire.
22
- */
23
- export type RingCoord = Uint8Array;
24
-
25
- /** A peer, referenced only by its opaque byte-array id. No multiaddr, no libp2p PeerId here. */
26
- export interface PeerRef {
27
- readonly id: Uint8Array;
28
- }
29
-
30
- /**
31
- * Wraps FRET's `RouteAndMaybeAct` so the walk / registration decision logic in db-core stays
32
- * transport-agnostic.
33
- */
34
- export interface ITopicRouter {
35
- /**
36
- * Route `activity` to the cohort owning `key` and run the cohort's activity callback,
37
- * collecting up to `wantK` participants and at least `minSigs` signatures.
38
- * @returns the encoded cohort reply.
39
- */
40
- routeAndAct(key: RingCoord, activity: Uint8Array, opts: { wantK: number; minSigs: number }): Promise<Uint8Array>;
41
- /** Direct dial to a cached primary; falls back to {@link routeAndAct} on failure (caller decides). */
42
- dialMember(member: PeerRef, activity: Uint8Array): Promise<Uint8Array>;
43
- }
44
-
45
- /** Intra-cohort gossip transport (FRET cohort gossip underneath). */
46
- export interface ICohortGossipTransport {
47
- /** Fire-and-forget broadcast of `msg` to the cohort at `coord`. */
48
- broadcast(coord: RingCoord, msg: Uint8Array): void;
49
- /** Subscribe to inbound cohort gossip; returns an unsubscribe handle. */
50
- onMessage(handler: (from: PeerRef, msg: Uint8Array) => void): () => void;
51
- }
52
-
53
- /** Authoritative cohort membership snapshots (FRET `MembershipCertV1` / stabilization underneath). */
54
- export interface IMembershipSource {
55
- /** Current cached membership cert for `coord`, encoded; `undefined` if none is cached. */
56
- current(coord: RingCoord): Promise<Uint8Array | undefined>;
57
- /** Force one refresh of `coord`'s membership cert (stale-cache retry); encoded, or `undefined`. */
58
- fetch(coord: RingCoord): Promise<Uint8Array | undefined>;
59
- }
60
-
61
- /**
62
- * Cohort threshold-signature primitive (FRET's `minSigs = k − x` cohort-signature assembly
63
- * underneath). db-core defines the seam; db-p2p binds FRET's signer/verifier without modifying it.
64
- * Peer ids are raw byte arrays here ({@link PeerRef}`.id`), matching the rest of the substrate; the
65
- * wire layer carries them as base64url strings.
66
- */
67
- export interface ICohortThresholdCrypto {
68
- /**
69
- * Assemble a cohort threshold signature over `payload`, collecting at least `minSigs` signers.
70
- * Resolves to the combined signature and the peers that contributed.
71
- */
72
- assemble(payload: Uint8Array, minSigs: number): Promise<{ thresholdSig: Uint8Array; signers: Uint8Array[] }>;
73
- /** Verify `thresholdSig` is a valid cohort signature over `payload` produced by `signers`. */
74
- verify(payload: Uint8Array, thresholdSig: Uint8Array, signers: readonly Uint8Array[]): boolean;
75
- }
76
-
77
- /**
78
- * Sink the cohort uses to publish a `MembershipCertV1` (over FRET's `/membership` protocol).
79
- * db-core's publisher builds + threshold-signs the cert and hands it here; db-p2p serves it.
80
- */
81
- export interface IMembershipPublishSink {
82
- /** Publish (advertise/serve) an already-signed membership certificate, encoded. */
83
- publish(encodedCert: Uint8Array): void;
84
- }
85
-
86
- /** Network-size estimate feeding `d_max`. */
87
- export interface ISizeEstimator {
88
- estimate(): { nEst: number; confidence: number };
89
- }
90
-
91
- /**
92
- * Verdict on whether a {@link MembershipCertV1}'s `(cohortCoord → members)` binding is vouched by a
93
- * source the verifying node *directly* trusts.
94
- *
95
- * - `"anchored"` — the binding is vouched (e.g. matches FRET `assembleCohort(coord)`, or the
96
- * tx-log commit certificate). The cert is trusted on this basis.
97
- * - `"rejected"` — the binding is contradicted (a known-different keyset owns this coord). A
98
- * `"rejected"` verdict is **fatal**: the cert is a forgery and is rejected even if it is
99
- * internally self-consistent, overriding the interim TOFU fallback.
100
- * - `"unknown"` — this node has no local authority over the coord, so it cannot judge. The
101
- * verifier falls through to the attestation chain / interim TOFU fallback.
102
- */
103
- export type TrustAnchorVerdict = "anchored" | "rejected" | "unknown";
104
-
105
- /**
106
- * Direct (base-case) trust anchor for a {@link MembershipCertV1}'s `coord → keyset` binding.
107
- *
108
- * db-core owns the chain-of-attestations and trust-root logic; the **direct** anchor is
109
- * tier/transport-specific (FRET ring agreement for T2/T3, tx-log commit certificate for T0/T1) and
110
- * is therefore delegated through this port. db-p2p binds it; **db-core never imports FRET**. A node
111
- * with no local authority for the coord returns `"unknown"` so the verifier falls through to the
112
- * chain / interim fallback instead of breaking distant verification. See {@link noAuthorityTrustAnchor}
113
- * for the db-core default (every coord `"unknown"`).
114
- */
115
- export interface IMembershipTrustAnchor {
116
- /** Judge, from a directly-trusted source, whether `cert.members` is authoritative for `cert.cohortCoord` at `tier`. */
117
- directAnchor(cert: MembershipCertV1, tier: number): TrustAnchorVerdict;
118
- }
119
-
120
- /**
121
- * An out-of-band-seeded trust root: the genesis-block-related cohorts a joining participant is told
122
- * to trust (validated against the genesis block hash by the caller before seeding). A trust root is
123
- * the base case of every attestation chain — a cert matching a root by `(coord, epoch, member-set)`
124
- * is trusted directly. Byte fields are raw (the verifier compares them against the cert's base64url
125
- * form internally).
126
- */
127
- export interface TrustRoot {
128
- /** Cohort coord (32 bytes). */
129
- readonly coord: Uint8Array;
130
- /** Cohort epoch (32 bytes) — required so a cert reusing a genesis coord with a swapped keyset is not a root. */
131
- readonly epoch: Uint8Array;
132
- /** Authoritative cohort members (any order; matched as a set). */
133
- readonly members: readonly Uint8Array[];
134
- }
135
-
136
- /**
137
- * The db-core default {@link IMembershipTrustAnchor}: it has no local authority over any coord, so it
138
- * returns `"unknown"` for every cert. Existing verifier callers that inject no anchor get this, keeping
139
- * the interim TOFU behavior (no regression) until db-p2p binds a real anchor.
140
- */
141
- export const noAuthorityTrustAnchor: IMembershipTrustAnchor = {
142
- directAnchor(_cert: MembershipCertV1, _tier: number): TrustAnchorVerdict {
143
- return "unknown";
144
- },
145
- };
146
-
147
- /**
148
- * Hash + ring math. db-core supplies its OWN SHA-256 (it already hashes logs and block ids);
149
- * the ring width is configuration. db-p2p, when mapping {@link RingCoord} onto FRET's coordinate
150
- * type, ensures `ringBits` matches FRET's ring width so coords are byte-compatible.
151
- */
152
- export interface IRingHash {
153
- /** SHA-256 of `bytes`, truncated to the ring width `B` ({@link ringBits}). */
154
- H(bytes: Uint8Array): RingCoord;
155
- /** Ring width in bits. */
156
- readonly ringBits: number;
157
- }
1
+ /**
2
+ * Cohort-topic substrate — transport ports.
3
+ *
4
+ * These are the seams that keep the cohort-topic substrate split cleanly across packages:
5
+ * db-core defines the interfaces here (pure logic depends only on a hash function and
6
+ * byte-array peer IDs), and db-p2p supplies the concrete FRET + libp2p implementations.
7
+ *
8
+ * **db-core never imports FRET or libp2p.** Every db-core substrate module takes these ports
9
+ * by injection (constructor / factory args); db-p2p constructs the FRET-backed versions and
10
+ * composes them with the db-core logic in `CohortTopicService`'s transport host.
11
+ *
12
+ * See `docs/cohort-topic.md` §FRET integration and `tickets` slug
13
+ * `cohort-topic-package-layering` for the authoritative layering rule.
14
+ */
15
+
16
+ import type { MembershipCertV1 } from "./wire/types.js";
17
+
18
+ /**
19
+ * Ring coordinate — SHA-256 truncated to the ring width `B` (see {@link IRingHash}). db-core
20
+ * owns this type; db-p2p maps it onto FRET's coordinate type, ensuring the byte representation
21
+ * matches FRET's ring width so routing keys line up on the wire.
22
+ */
23
+ export type RingCoord = Uint8Array;
24
+
25
+ /** A peer, referenced only by its opaque byte-array id. No multiaddr, no libp2p PeerId here. */
26
+ export interface PeerRef {
27
+ readonly id: Uint8Array;
28
+ }
29
+
30
+ /**
31
+ * Wraps FRET's `RouteAndMaybeAct` so the walk / registration decision logic in db-core stays
32
+ * transport-agnostic.
33
+ */
34
+ export interface ITopicRouter {
35
+ /**
36
+ * Route `activity` to the cohort owning `key` and run the cohort's activity callback,
37
+ * collecting up to `wantK` participants and at least `minSigs` signatures.
38
+ * @returns the encoded cohort reply.
39
+ */
40
+ routeAndAct(key: RingCoord, activity: Uint8Array, opts: { wantK: number; minSigs: number }): Promise<Uint8Array>;
41
+ /** Direct dial to a cached primary; falls back to {@link routeAndAct} on failure (caller decides). */
42
+ dialMember(member: PeerRef, activity: Uint8Array): Promise<Uint8Array>;
43
+ }
44
+
45
+ /** Intra-cohort gossip transport (FRET cohort gossip underneath). */
46
+ export interface ICohortGossipTransport {
47
+ /** Fire-and-forget broadcast of `msg` to the cohort at `coord`. */
48
+ broadcast(coord: RingCoord, msg: Uint8Array): void;
49
+ /** Subscribe to inbound cohort gossip; returns an unsubscribe handle. */
50
+ onMessage(handler: (from: PeerRef, msg: Uint8Array) => void): () => void;
51
+ }
52
+
53
+ /** Authoritative cohort membership snapshots (FRET `MembershipCertV1` / stabilization underneath). */
54
+ export interface IMembershipSource {
55
+ /** Current cached membership cert for `coord`, encoded; `undefined` if none is cached. */
56
+ current(coord: RingCoord): Promise<Uint8Array | undefined>;
57
+ /** Force one refresh of `coord`'s membership cert (stale-cache retry); encoded, or `undefined`. */
58
+ fetch(coord: RingCoord): Promise<Uint8Array | undefined>;
59
+ }
60
+
61
+ /**
62
+ * Cohort threshold-signature primitive (FRET's `minSigs = k − x` cohort-signature assembly
63
+ * underneath). db-core defines the seam; db-p2p binds FRET's signer/verifier without modifying it.
64
+ * Peer ids are raw byte arrays here ({@link PeerRef}`.id`), matching the rest of the substrate; the
65
+ * wire layer carries them as base64url strings.
66
+ */
67
+ export interface ICohortThresholdCrypto {
68
+ /**
69
+ * Assemble a cohort threshold signature over `payload`, collecting at least `minSigs` signers.
70
+ * Resolves to the combined signature and the peers that contributed.
71
+ */
72
+ assemble(payload: Uint8Array, minSigs: number): Promise<{ thresholdSig: Uint8Array; signers: Uint8Array[] }>;
73
+ /** Verify `thresholdSig` is a valid cohort signature over `payload` produced by `signers`. */
74
+ verify(payload: Uint8Array, thresholdSig: Uint8Array, signers: readonly Uint8Array[]): boolean;
75
+ }
76
+
77
+ /**
78
+ * Sink the cohort uses to publish a `MembershipCertV1` (over FRET's `/membership` protocol).
79
+ * db-core's publisher builds + threshold-signs the cert and hands it here; db-p2p serves it.
80
+ */
81
+ export interface IMembershipPublishSink {
82
+ /** Publish (advertise/serve) an already-signed membership certificate, encoded. */
83
+ publish(encodedCert: Uint8Array): void;
84
+ }
85
+
86
+ /** Network-size estimate feeding `d_max`. */
87
+ export interface ISizeEstimator {
88
+ estimate(): { nEst: number; confidence: number };
89
+ }
90
+
91
+ /**
92
+ * Verdict on whether a {@link MembershipCertV1}'s `(cohortCoord → members)` binding is vouched by a
93
+ * source the verifying node *directly* trusts.
94
+ *
95
+ * - `"anchored"` — the binding is vouched (e.g. matches FRET `assembleCohort(coord)`, or the
96
+ * tx-log commit certificate). The cert is trusted on this basis.
97
+ * - `"rejected"` — the binding is contradicted (a known-different keyset owns this coord). A
98
+ * `"rejected"` verdict is **fatal**: the cert is a forgery and is rejected even if it is
99
+ * internally self-consistent, overriding the interim TOFU fallback.
100
+ * - `"unknown"` — this node has no local authority over the coord, so it cannot judge. The
101
+ * verifier falls through to the attestation chain / interim TOFU fallback.
102
+ */
103
+ export type TrustAnchorVerdict = "anchored" | "rejected" | "unknown";
104
+
105
+ /**
106
+ * Direct (base-case) trust anchor for a {@link MembershipCertV1}'s `coord → keyset` binding.
107
+ *
108
+ * db-core owns the chain-of-attestations and trust-root logic; the **direct** anchor is
109
+ * tier/transport-specific (FRET ring agreement for T2/T3, tx-log commit certificate for T0/T1) and
110
+ * is therefore delegated through this port. db-p2p binds it; **db-core never imports FRET**. A node
111
+ * with no local authority for the coord returns `"unknown"` so the verifier falls through to the
112
+ * chain / interim fallback instead of breaking distant verification. See {@link noAuthorityTrustAnchor}
113
+ * for the db-core default (every coord `"unknown"`).
114
+ */
115
+ export interface IMembershipTrustAnchor {
116
+ /** Judge, from a directly-trusted source, whether `cert.members` is authoritative for `cert.cohortCoord` at `tier`. */
117
+ directAnchor(cert: MembershipCertV1, tier: number): TrustAnchorVerdict;
118
+ }
119
+
120
+ /**
121
+ * An out-of-band-seeded trust root: the genesis-block-related cohorts a joining participant is told
122
+ * to trust (validated against the genesis block hash by the caller before seeding). A trust root is
123
+ * the base case of every attestation chain — a cert matching a root by `(coord, epoch, member-set)`
124
+ * is trusted directly. Byte fields are raw (the verifier compares them against the cert's base64url
125
+ * form internally).
126
+ */
127
+ export interface TrustRoot {
128
+ /** Cohort coord (32 bytes). */
129
+ readonly coord: Uint8Array;
130
+ /** Cohort epoch (32 bytes) — required so a cert reusing a genesis coord with a swapped keyset is not a root. */
131
+ readonly epoch: Uint8Array;
132
+ /** Authoritative cohort members (any order; matched as a set). */
133
+ readonly members: readonly Uint8Array[];
134
+ }
135
+
136
+ /**
137
+ * The db-core default {@link IMembershipTrustAnchor}: it has no local authority over any coord, so it
138
+ * returns `"unknown"` for every cert. Existing verifier callers that inject no anchor get this, keeping
139
+ * the interim TOFU behavior (no regression) until db-p2p binds a real anchor.
140
+ */
141
+ export const noAuthorityTrustAnchor: IMembershipTrustAnchor = {
142
+ directAnchor(_cert: MembershipCertV1, _tier: number): TrustAnchorVerdict {
143
+ return "unknown";
144
+ },
145
+ };
146
+
147
+ /**
148
+ * Hash + ring math. db-core supplies its OWN SHA-256 (it already hashes logs and block ids);
149
+ * the ring width is configuration. db-p2p, when mapping {@link RingCoord} onto FRET's coordinate
150
+ * type, ensures `ringBits` matches FRET's ring width so coords are byte-compatible.
151
+ */
152
+ export interface IRingHash {
153
+ /** SHA-256 of `bytes`, truncated to the ring width `B` ({@link ringBits}). */
154
+ H(bytes: Uint8Array): RingCoord;
155
+ /** Ring width in bits. */
156
+ readonly ringBits: number;
157
+ }