@serfab/cadre-core 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +8 -6
  2. package/dist/cadre-node.d.ts +527 -206
  3. package/dist/cadre-node.js +1084 -528
  4. package/dist/cadre-node.js.map +1 -1
  5. package/dist/control-authorization.d.ts +2 -2
  6. package/dist/control-authorization.js +1 -0
  7. package/dist/control-authorization.js.map +1 -1
  8. package/dist/control-cohort.d.ts +6 -0
  9. package/dist/control-cohort.js +6 -0
  10. package/dist/control-cohort.js.map +1 -1
  11. package/dist/control-database.d.ts +46 -8
  12. package/dist/control-database.js +97 -18
  13. package/dist/control-database.js.map +1 -1
  14. package/dist/control-formation-recorder.d.ts +37 -14
  15. package/dist/control-formation-recorder.js +60 -10
  16. package/dist/control-formation-recorder.js.map +1 -1
  17. package/dist/control-read-retry.d.ts +13 -12
  18. package/dist/control-read-retry.js +14 -12
  19. package/dist/control-read-retry.js.map +1 -1
  20. package/dist/control-schema.d.ts +1 -1
  21. package/dist/control-schema.js +67 -5
  22. package/dist/control-schema.js.map +1 -1
  23. package/dist/control-stream.d.ts +9 -1
  24. package/dist/control-stream.js +24 -1
  25. package/dist/control-stream.js.map +1 -1
  26. package/dist/control-write-retry.d.ts +12 -2
  27. package/dist/control-write-retry.js +13 -2
  28. package/dist/control-write-retry.js.map +1 -1
  29. package/dist/delegate-admission.d.ts +11 -8
  30. package/dist/delegate-admission.js +19 -11
  31. package/dist/delegate-admission.js.map +1 -1
  32. package/dist/diagnostics/connection-path.d.ts +0 -7
  33. package/dist/diagnostics/connection-path.js +0 -7
  34. package/dist/diagnostics/connection-path.js.map +1 -1
  35. package/dist/formation-approval.d.ts +7 -0
  36. package/dist/formation-approval.js +9 -3
  37. package/dist/formation-approval.js.map +1 -1
  38. package/dist/fs-atomic.d.ts +11 -2
  39. package/dist/fs-atomic.js +13 -3
  40. package/dist/fs-atomic.js.map +1 -1
  41. package/dist/hibernation-manager.d.ts +111 -8
  42. package/dist/hibernation-manager.js +234 -49
  43. package/dist/hibernation-manager.js.map +1 -1
  44. package/dist/index.d.ts +10 -10
  45. package/dist/index.js +25 -20
  46. package/dist/index.js.map +1 -1
  47. package/dist/joined-strand-store.d.ts +90 -25
  48. package/dist/joined-strand-store.js +223 -55
  49. package/dist/joined-strand-store.js.map +1 -1
  50. package/dist/key-store-file.js +14 -5
  51. package/dist/key-store-file.js.map +1 -1
  52. package/dist/link-budget.d.ts +367 -69
  53. package/dist/link-budget.js +375 -72
  54. package/dist/link-budget.js.map +1 -1
  55. package/dist/membership-connection-gater.d.ts +30 -43
  56. package/dist/membership-connection-gater.js +31 -42
  57. package/dist/membership-connection-gater.js.map +1 -1
  58. package/dist/node-local-snapshot.d.ts +6 -4
  59. package/dist/node-local-snapshot.js +7 -3
  60. package/dist/node-local-snapshot.js.map +1 -1
  61. package/dist/peer-dial.d.ts +24 -4
  62. package/dist/peer-dial.js +74 -5
  63. package/dist/peer-dial.js.map +1 -1
  64. package/dist/peer-join-backfill.d.ts +2 -10
  65. package/dist/peer-join-backfill.js +8 -8
  66. package/dist/peer-join-backfill.js.map +1 -1
  67. package/dist/push-fanout.d.ts +6 -0
  68. package/dist/push-fanout.js +6 -0
  69. package/dist/push-fanout.js.map +1 -1
  70. package/dist/relay-reservation.d.ts +3 -1
  71. package/dist/relay-reservation.js +3 -1
  72. package/dist/relay-reservation.js.map +1 -1
  73. package/dist/relay-server.d.ts +79 -0
  74. package/dist/relay-server.js +74 -0
  75. package/dist/relay-server.js.map +1 -0
  76. package/dist/seed-bootstrap.d.ts +57 -4
  77. package/dist/seed-bootstrap.js +107 -83
  78. package/dist/seed-bootstrap.js.map +1 -1
  79. package/dist/storage-scope.d.ts +33 -17
  80. package/dist/storage-scope.js +44 -23
  81. package/dist/storage-scope.js.map +1 -1
  82. package/dist/strand-addr-protocol.d.ts +58 -21
  83. package/dist/strand-addr-protocol.js +133 -85
  84. package/dist/strand-addr-protocol.js.map +1 -1
  85. package/dist/strand-database.d.ts +20 -2
  86. package/dist/strand-database.js +42 -5
  87. package/dist/strand-database.js.map +1 -1
  88. package/dist/strand-first-sync-gate.d.ts +59 -21
  89. package/dist/strand-first-sync-gate.js +58 -19
  90. package/dist/strand-first-sync-gate.js.map +1 -1
  91. package/dist/strand-formation-deadlines.d.ts +151 -0
  92. package/dist/strand-formation-deadlines.js +171 -0
  93. package/dist/strand-formation-deadlines.js.map +1 -0
  94. package/dist/strand-formation-manager.d.ts +63 -30
  95. package/dist/strand-formation-manager.js +67 -41
  96. package/dist/strand-formation-manager.js.map +1 -1
  97. package/dist/strand-formation-protocol.d.ts +45 -46
  98. package/dist/strand-formation-protocol.js +62 -126
  99. package/dist/strand-formation-protocol.js.map +1 -1
  100. package/dist/strand-fret-addrs.d.ts +54 -0
  101. package/dist/strand-fret-addrs.js +108 -0
  102. package/dist/strand-fret-addrs.js.map +1 -0
  103. package/dist/strand-instance-manager.d.ts +122 -44
  104. package/dist/strand-instance-manager.js +270 -114
  105. package/dist/strand-instance-manager.js.map +1 -1
  106. package/dist/strand-membership-writer.d.ts +6 -0
  107. package/dist/strand-membership-writer.js +11 -0
  108. package/dist/strand-membership-writer.js.map +1 -1
  109. package/dist/strand-network-state-file.d.ts +12 -0
  110. package/dist/strand-network-state-file.js +38 -0
  111. package/dist/strand-network-state-file.js.map +1 -0
  112. package/dist/strand-network-state.d.ts +111 -0
  113. package/dist/strand-network-state.js +191 -0
  114. package/dist/strand-network-state.js.map +1 -0
  115. package/dist/strand-revocation-enforcer.js +2 -1
  116. package/dist/strand-revocation-enforcer.js.map +1 -1
  117. package/dist/strand-solicitation.d.ts +36 -20
  118. package/dist/strand-solicitation.js +4 -4
  119. package/dist/strand-solicitation.js.map +1 -1
  120. package/dist/strand-wake-protocol.d.ts +80 -23
  121. package/dist/strand-wake-protocol.js +89 -64
  122. package/dist/strand-wake-protocol.js.map +1 -1
  123. package/dist/types.d.ts +148 -61
  124. package/dist/types.js +4 -3
  125. package/dist/types.js.map +1 -1
  126. package/package.json +11 -10
  127. package/src/cadre-node.ts +8400 -7776
  128. package/src/control-authorization.ts +2 -1
  129. package/src/control-cohort.ts +6 -0
  130. package/src/control-database.ts +122 -18
  131. package/src/control-formation-recorder.ts +354 -305
  132. package/src/control-read-retry.ts +14 -12
  133. package/src/control-schema.ts +67 -5
  134. package/src/control-stream.ts +25 -1
  135. package/src/control-write-retry.ts +13 -2
  136. package/src/delegate-admission.ts +23 -13
  137. package/src/diagnostics/connection-path.ts +0 -7
  138. package/src/formation-approval.ts +610 -604
  139. package/src/fs-atomic.ts +14 -4
  140. package/src/hibernation-manager.ts +638 -437
  141. package/src/index.ts +43 -65
  142. package/src/joined-strand-store.ts +247 -57
  143. package/src/key-store-file.ts +14 -5
  144. package/src/link-budget.ts +393 -74
  145. package/src/membership-connection-gater.ts +31 -45
  146. package/src/node-local-snapshot.ts +12 -7
  147. package/src/peer-dial.ts +81 -7
  148. package/src/peer-join-backfill.ts +10 -9
  149. package/src/push-fanout.ts +6 -0
  150. package/src/relay-reservation.ts +3 -1
  151. package/src/relay-server.ts +98 -0
  152. package/src/seed-bootstrap.ts +133 -91
  153. package/src/storage-scope.ts +44 -23
  154. package/src/strand-addr-protocol.ts +547 -458
  155. package/src/strand-database.ts +287 -242
  156. package/src/strand-first-sync-gate.ts +58 -19
  157. package/src/strand-formation-deadlines.ts +227 -0
  158. package/src/strand-formation-manager.ts +700 -647
  159. package/src/strand-formation-protocol.ts +106 -154
  160. package/src/strand-fret-addrs.ts +145 -0
  161. package/src/strand-instance-manager.ts +307 -140
  162. package/src/strand-membership-writer.ts +12 -0
  163. package/src/strand-network-state-file.ts +40 -0
  164. package/src/strand-network-state.ts +243 -0
  165. package/src/strand-revocation-enforcer.ts +2 -1
  166. package/src/strand-solicitation.ts +519 -500
  167. package/src/strand-wake-protocol.ts +401 -355
  168. package/src/types.ts +150 -61
  169. package/dist/strand-peer-book-file.d.ts +0 -12
  170. package/dist/strand-peer-book-file.js +0 -37
  171. package/dist/strand-peer-book-file.js.map +0 -1
  172. package/dist/strand-peer-book-protocol.d.ts +0 -159
  173. package/dist/strand-peer-book-protocol.js +0 -360
  174. package/dist/strand-peer-book-protocol.js.map +0 -1
  175. package/dist/strand-peer-book-swap.d.ts +0 -104
  176. package/dist/strand-peer-book-swap.js +0 -284
  177. package/dist/strand-peer-book-swap.js.map +0 -1
  178. package/dist/strand-peer-book.d.ts +0 -159
  179. package/dist/strand-peer-book.js +0 -354
  180. package/dist/strand-peer-book.js.map +0 -1
  181. package/dist/strand-peer-observer.d.ts +0 -88
  182. package/dist/strand-peer-observer.js +0 -180
  183. package/dist/strand-peer-observer.js.map +0 -1
  184. package/src/strand-peer-book-file.ts +0 -39
  185. package/src/strand-peer-book-protocol.ts +0 -463
  186. package/src/strand-peer-book-swap.ts +0 -338
  187. package/src/strand-peer-book.ts +0 -468
  188. package/src/strand-peer-observer.ts +0 -235
@@ -1,6 +1,6 @@
1
1
  import { type ControlDatabase } from './control-database.js';
2
2
  import { type FormationApprover } from './formation-approval.js';
3
- import type { FormationUsageRecorder, ResolvedHostStrand } from './strand-solicitation.js';
3
+ import type { AuthorizedFormationUsage, FormationUsageParams, FormationUsageRecorder, ResolvedHostStrand } from './strand-solicitation.js';
4
4
  import type { OpenInvitation } from './types.js';
5
5
  /**
6
6
  * {@link FormationUsageRecorder} backed by the real `CadreControl` tables.
@@ -11,7 +11,8 @@ import type { OpenInvitation } from './types.js';
11
11
  *
12
12
  * - **Bound (provision-then-record):** the host strand already exists (owner-signed
13
13
  * up front and named by the invite's `StrandId`), so {@link resolveStrand} reports it
14
- * and {@link recordUsage} writes the consent row against that pre-existing strand
14
+ * and {@link authorizeUsage} then its `record()` (or {@link recordUsage}, both at once)
15
+ * writes the consent row against that pre-existing strand
15
16
  * (record-only) rather than inserting a new `Strand`.
16
17
  * - **Unbound (responder-provisions):** the invite carries no `StrandId`, so
17
18
  * {@link provisionAndRecord} mints a fresh strand and records consent against it
@@ -29,7 +30,10 @@ import type { OpenInvitation } from './types.js';
29
30
  * approval ({@link obtainApproval}) — the recorder is the one place where the nonce that is
30
31
  * SIGNED and the nonce that is INSERTED are trivially the same value, since it also performs
31
32
  * the write. That makes this class do network I/O; failures surface as
32
- * {@link FormationApprovalError}s the manager maps to protocol rejection reasons.
33
+ * {@link FormationApprovalError}s the manager maps to protocol rejection reasons. The bound
34
+ * path is split in two ({@link authorizeUsage}, then the returned `record()`) so the manager
35
+ * can issue the joiner's membership pass between the approval and the write; the handle
36
+ * carries the approved fields across, which keeps the signed and inserted nonce the same.
33
37
  */
34
38
  export declare class ControlFormationUsageRecorder implements FormationUsageRecorder {
35
39
  private readonly controlDatabase;
@@ -101,18 +105,37 @@ export declare class ControlFormationUsageRecorder implements FormationUsageReco
101
105
  * spent on AND provably the joiner that agreed. Use
102
106
  * {@link ControlDatabase.redeemInvitation} for the consent-creates-strand path instead.
103
107
  *
104
- * Reads the invite first (one extra read per redemption) to learn its `ValidationUrl`, and
105
- * obtains the approval through {@link obtainApproval} when one is demanded.
108
+ * Authorizes ({@link authorizeUsage}) and writes in one step, for callers with nothing to do
109
+ * in between.
106
110
  */
107
- recordUsage(params: {
108
- token: string;
109
- peerKey: string;
110
- peerSignature: string;
111
- usageStampId: string;
112
- strandId: string;
113
- disclosure: string;
114
- signal?: AbortSignal;
115
- }): Promise<void>;
111
+ recordUsage(params: FormationUsageParams): Promise<void>;
112
+ /**
113
+ * Everything {@link recordUsage} does before its write, so the manager can issue the
114
+ * joiner's membership pass into the host strand only once the redemption is cleared, and
115
+ * spend the token only after that.
116
+ *
117
+ * Reads the invite first (one extra read per redemption) to learn its `ValidationUrl` and
118
+ * seat budget, obtains the approval through {@link obtainApproval} when one is demanded,
119
+ * re-checks the abort (the approval call may have been long), and pre-checks the seat
120
+ * budget ({@link assertSeatFree}). The returned `record()` closes over the captured fields
121
+ * and approval, so the nonce the approver signed is the nonce inserted without the caller
122
+ * ever passing it back.
123
+ */
124
+ authorizeUsage(params: FormationUsageParams): Promise<AuthorizedFormationUsage>;
125
+ /**
126
+ * Refuse a redemption whose invite has no seat left, BEFORE anything is written — the
127
+ * authoritative check is the one `recordFormationUsage` repeats inside its write lock.
128
+ * Catches a same-node rival that took the last seat while this redemption waited on the
129
+ * approval hook, which `runSession`'s up-front `isTokenUsed` check could not see.
130
+ *
131
+ * NOTE: two redemptions that both pass this check within the time one of them takes to
132
+ * issue its membership pass still both issue one, and the loser's pass is orphaned
133
+ * (expiry-bounded, never handed out). Holding the control write lock across issuance would
134
+ * close it, but `lockedWithRetry` re-runs locked bodies on transient failures (a re-run
135
+ * would double-issue) and every control write would stall behind a strand-database write.
136
+ * If orphaned passes from same-node races ever matter, reserve the seat before issuance.
137
+ */
138
+ private assertSeatFree;
116
139
  /**
117
140
  * Classify the host strand this invite binds to (see {@link ResolvedHostStrand}):
118
141
  *
@@ -1,5 +1,5 @@
1
1
  import debug from 'debug';
2
- import { FormationAbortedError } from './control-database.js';
2
+ import { FormationAbortedError, InvitationExhaustedError } from './control-database.js';
3
3
  import { mintStrandId } from './strand-id.js';
4
4
  import { createHttpFormationApprover, verifyFormationApproval, FormationApprovalError } from './formation-approval.js';
5
5
  const log = debug('sereus:cadre:formation-recorder');
@@ -14,7 +14,8 @@ const NEVER_EXPIRES = new Date(8640000000000000);
14
14
  *
15
15
  * - **Bound (provision-then-record):** the host strand already exists (owner-signed
16
16
  * up front and named by the invite's `StrandId`), so {@link resolveStrand} reports it
17
- * and {@link recordUsage} writes the consent row against that pre-existing strand
17
+ * and {@link authorizeUsage} then its `record()` (or {@link recordUsage}, both at once)
18
+ * writes the consent row against that pre-existing strand
18
19
  * (record-only) rather than inserting a new `Strand`.
19
20
  * - **Unbound (responder-provisions):** the invite carries no `StrandId`, so
20
21
  * {@link provisionAndRecord} mints a fresh strand and records consent against it
@@ -32,7 +33,10 @@ const NEVER_EXPIRES = new Date(8640000000000000);
32
33
  * approval ({@link obtainApproval}) — the recorder is the one place where the nonce that is
33
34
  * SIGNED and the nonce that is INSERTED are trivially the same value, since it also performs
34
35
  * the write. That makes this class do network I/O; failures surface as
35
- * {@link FormationApprovalError}s the manager maps to protocol rejection reasons.
36
+ * {@link FormationApprovalError}s the manager maps to protocol rejection reasons. The bound
37
+ * path is split in two ({@link authorizeUsage}, then the returned `record()`) so the manager
38
+ * can issue the joiner's membership pass between the approval and the write; the handle
39
+ * carries the approved fields across, which keeps the signed and inserted nonce the same.
36
40
  */
37
41
  export class ControlFormationUsageRecorder {
38
42
  /**
@@ -154,10 +158,25 @@ export class ControlFormationUsageRecorder {
154
158
  * spent on AND provably the joiner that agreed. Use
155
159
  * {@link ControlDatabase.redeemInvitation} for the consent-creates-strand path instead.
156
160
  *
157
- * Reads the invite first (one extra read per redemption) to learn its `ValidationUrl`, and
158
- * obtains the approval through {@link obtainApproval} when one is demanded.
161
+ * Authorizes ({@link authorizeUsage}) and writes in one step, for callers with nothing to do
162
+ * in between.
159
163
  */
160
164
  async recordUsage(params) {
165
+ await (await this.authorizeUsage(params)).record();
166
+ }
167
+ /**
168
+ * Everything {@link recordUsage} does before its write, so the manager can issue the
169
+ * joiner's membership pass into the host strand only once the redemption is cleared, and
170
+ * spend the token only after that.
171
+ *
172
+ * Reads the invite first (one extra read per redemption) to learn its `ValidationUrl` and
173
+ * seat budget, obtains the approval through {@link obtainApproval} when one is demanded,
174
+ * re-checks the abort (the approval call may have been long), and pre-checks the seat
175
+ * budget ({@link assertSeatFree}). The returned `record()` closes over the captured fields
176
+ * and approval, so the nonce the approver signed is the nonce inserted without the caller
177
+ * ever passing it back.
178
+ */
179
+ async authorizeUsage(params) {
161
180
  const { token, peerKey, peerSignature, usageStampId, strandId, disclosure, signal } = params;
162
181
  if (signal?.aborted) {
163
182
  throw new FormationAbortedError(token, 'usage recording');
@@ -172,11 +191,42 @@ export class ControlFormationUsageRecorder {
172
191
  token, usageStampId, strandId, peerKey, disclosure,
173
192
  validationUrl: invite?.validationUrl ?? null,
174
193
  }, signal);
175
- await this.controlDatabase.recordFormationUsage({
176
- token, strandId, peerKey, peerSignature, usageStampId, disclosure, signal,
177
- totalUses: invite?.totalUses ?? null, ...approval,
178
- });
179
- log('Recorded formation usage: token=%s strand=%s', token, strandId);
194
+ if (signal?.aborted) {
195
+ throw new FormationAbortedError(token, 'usage recording');
196
+ }
197
+ const totalUses = invite?.totalUses ?? null;
198
+ await this.assertSeatFree(token, totalUses);
199
+ return {
200
+ record: async () => {
201
+ await this.controlDatabase.recordFormationUsage({
202
+ token, strandId, peerKey, peerSignature, usageStampId, disclosure, signal,
203
+ totalUses, ...approval,
204
+ });
205
+ log('Recorded formation usage: token=%s strand=%s', token, strandId);
206
+ }
207
+ };
208
+ }
209
+ /**
210
+ * Refuse a redemption whose invite has no seat left, BEFORE anything is written — the
211
+ * authoritative check is the one `recordFormationUsage` repeats inside its write lock.
212
+ * Catches a same-node rival that took the last seat while this redemption waited on the
213
+ * approval hook, which `runSession`'s up-front `isTokenUsed` check could not see.
214
+ *
215
+ * NOTE: two redemptions that both pass this check within the time one of them takes to
216
+ * issue its membership pass still both issue one, and the loser's pass is orphaned
217
+ * (expiry-bounded, never handed out). Holding the control write lock across issuance would
218
+ * close it, but `lockedWithRetry` re-runs locked bodies on transient failures (a re-run
219
+ * would double-issue) and every control write would stall behind a strand-database write.
220
+ * If orphaned passes from same-node races ever matter, reserve the seat before issuance.
221
+ */
222
+ async assertSeatFree(token, totalUses) {
223
+ if (totalUses === null) {
224
+ return;
225
+ }
226
+ const used = await this.controlDatabase.countFormationUsage(token);
227
+ if (used >= totalUses) {
228
+ throw new InvitationExhaustedError(token, used, totalUses);
229
+ }
180
230
  }
181
231
  /**
182
232
  * Classify the host strand this invite binds to (see {@link ResolvedHostStrand}):
@@ -1 +1 @@
1
- {"version":3,"file":"control-formation-recorder.js","sourceRoot":"","sources":["../src/control-formation-recorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"control-formation-recorder.js","sourceRoot":"","sources":["../src/control-formation-recorder.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ import type { ControlRetryOptions } from './control-retry.js';
10
10
  * was absorbed). This module gives reads the same bounded re-presentation with a SHORTER
11
11
  * deadline and a NARROWER failure set, because the tightest caller deadline over a control
12
12
  * read is the inbound admission gate's 2 s fail-open timeout
13
- * (`ADMISSION_DECISION_TIMEOUT_MS`, `membership-connection-gater.ts`) — a read budget that
13
+ * (`ADMISSION_DECISION_TIMEOUT_MS`, `link-budget.ts`) — a read budget that
14
14
  * does not fit inside it with headroom spends its retries after the gate has already
15
15
  * admitted.
16
16
  *
@@ -60,17 +60,18 @@ export declare const CONTROL_READ_RETRY_DELAYS_MS: readonly number[];
60
60
  * 2 s only because each stays well under it. Do not raise these numbers without
61
61
  * re-checking against `ADMISSION_DECISION_TIMEOUT_MS`.
62
62
  *
63
- * NOTE: the obligation runs the other way too, and the number that dominates this budget is
64
- * declared in another package. One attempt whose cohort consult finds a silent peer costs
65
- * `clusterPolicy.cohortQueryTimeoutMs`, which sereus declares at 5000 ms
66
- * (`COHORT_READ_DEADLINE_MS`, `quereus-plugin-sereus/src/cluster-size.ts`) for relayed phone
67
- * links — more than three times this budget, so such an attempt is never retried and the
68
- * admission gate above it has already fail-opened. That is a widened cost of a deliberate
69
- * choice, not a hole (the stream gates still decide), and the whole ladder of cadre-core
70
- * deadlines against Optimystic's is audited by
71
- * `backlog/debt-cadre-deadlines-sized-against-old-optimystic-bounds`. What this budget still
72
- * buys is the failure it was built for: the ~25 ms transactor read-phase aggregate off a
73
- * stream still forming, which retries twice well inside 1500 ms.
63
+ * It cuts the loop off by design, so it does not grow with the link or with the number that
64
+ * dominates a slow attempt: an attempt whose cohort consult finds a silent peer costs
65
+ * `clusterPolicy.cohortQueryTimeoutMs`, two link round trips at the declared link
66
+ * (`cohortReadDeadlineMs` in `link-budget.ts`, 7 000 ms at the default declaration; the plugin's
67
+ * `COHORT_READ_DEADLINE_MS` is the same number). That is more than four times this budget, so
68
+ * such an attempt is never retried and the caller gets its error unchanged. That is deliberate:
69
+ * the caller this budget is sized for, the admission gate, has
70
+ * already taken its fail-open answer by then, and a retry would only spend time after it. What
71
+ * the budget still buys is the fast failures it was built for: the ~25 ms transactor read-phase
72
+ * aggregate off a stream still forming, and a `cohort-unreachable` read during bring-up, which
73
+ * fails fast because there is no connection to ask. Both retry twice well inside 1500 ms. See
74
+ * `docs/cadre-consistency.md` → "Deadlines Over Optimystic's Reads and Commits".
74
75
  */
75
76
  export declare const CONTROL_READ_RETRY_BUDGET_MS = 1500;
76
77
  /**
@@ -12,7 +12,7 @@ import { isUncommittedTransactorAggregate } from './control-write-retry.js';
12
12
  * was absorbed). This module gives reads the same bounded re-presentation with a SHORTER
13
13
  * deadline and a NARROWER failure set, because the tightest caller deadline over a control
14
14
  * read is the inbound admission gate's 2 s fail-open timeout
15
- * (`ADMISSION_DECISION_TIMEOUT_MS`, `membership-connection-gater.ts`) — a read budget that
15
+ * (`ADMISSION_DECISION_TIMEOUT_MS`, `link-budget.ts`) — a read budget that
16
16
  * does not fit inside it with headroom spends its retries after the gate has already
17
17
  * admitted.
18
18
  *
@@ -62,18 +62,20 @@ export const CONTROL_READ_RETRY_DELAYS_MS = [100, 400];
62
62
  * 2 s only because each stays well under it. Do not raise these numbers without
63
63
  * re-checking against `ADMISSION_DECISION_TIMEOUT_MS`.
64
64
  *
65
- * NOTE: the obligation runs the other way too, and the number that dominates this budget is
66
- * declared in another package. One attempt whose cohort consult finds a silent peer costs
67
- * `clusterPolicy.cohortQueryTimeoutMs`, which sereus declares at 5000 ms
68
- * (`COHORT_READ_DEADLINE_MS`, `quereus-plugin-sereus/src/cluster-size.ts`) for relayed phone
69
- * links — more than three times this budget, so such an attempt is never retried and the
70
- * admission gate above it has already fail-opened. That is a widened cost of a deliberate
71
- * choice, not a hole (the stream gates still decide), and the whole ladder of cadre-core
72
- * deadlines against Optimystic's is audited by
73
- * `backlog/debt-cadre-deadlines-sized-against-old-optimystic-bounds`. What this budget still
74
- * buys is the failure it was built for: the ~25 ms transactor read-phase aggregate off a
75
- * stream still forming, which retries twice well inside 1500 ms.
65
+ * It cuts the loop off by design, so it does not grow with the link or with the number that
66
+ * dominates a slow attempt: an attempt whose cohort consult finds a silent peer costs
67
+ * `clusterPolicy.cohortQueryTimeoutMs`, two link round trips at the declared link
68
+ * (`cohortReadDeadlineMs` in `link-budget.ts`, 7 000 ms at the default declaration; the plugin's
69
+ * `COHORT_READ_DEADLINE_MS` is the same number). That is more than four times this budget, so
70
+ * such an attempt is never retried and the caller gets its error unchanged. That is deliberate:
71
+ * the caller this budget is sized for, the admission gate, has
72
+ * already taken its fail-open answer by then, and a retry would only spend time after it. What
73
+ * the budget still buys is the fast failures it was built for: the ~25 ms transactor read-phase
74
+ * aggregate off a stream still forming, and a `cohort-unreachable` read during bring-up, which
75
+ * fails fast because there is no connection to ask. Both retry twice well inside 1500 ms. See
76
+ * `docs/cadre-consistency.md` → "Deadlines Over Optimystic's Reads and Commits".
76
77
  */
78
+ // eslint-disable-next-line no-restricted-syntax -- cuts off by design: a slow attempt is not retried, because the admission gate this budget is sized for has already failed open by then; see docs/cadre-consistency.md → "Deadlines Over Optimystic's Reads and Commits"
77
79
  export const CONTROL_READ_RETRY_BUDGET_MS = 1500;
78
80
  /**
79
81
  * The block-unavailability reasons a repeat read can actually improve on, matched against
@@ -1 +1 @@
1
- {"version":3,"file":"control-read-retry.js","sourceRoot":"","sources":["../src/control-read-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAK,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,2BAA2B,GAChC,uEAAuE,CAAC;AAEzE,kFAAkF;AAClF,SAAS,2BAA2B,CAAC,OAAe;IACnD,OAAO,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAWD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAAc;IAC3D,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAC1C,gCAAgC,CAAC,OAAO,CAAC,IAAI,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACrD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpC,IAAI,YAAY,qBAAqB,IAAI,IAAI,CAAC,MAAM,KAAK,oBAAoB,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,gBAAgB,CAC/B,OAAyB,EACzB,UAAmC,EAAE;IAErC,OAAO,qBAAqB,CAAC,OAAO,EAAE;QACrC,QAAQ,EAAE,qBAAqB;QAC/B,QAAQ,EAAE,4BAA4B;QACtC,QAAQ,EAAE,4BAA4B;QACtC,WAAW,EAAE,6BAA6B;QAC1C,SAAS,EAAE,cAAc;KACzB,EAAE,OAAO,CAAC,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"control-read-retry.js","sourceRoot":"","sources":["../src/control-read-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,2QAA2Q;AAC3Q,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAK,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,2BAA2B,GAChC,uEAAuE,CAAC;AAEzE,kFAAkF;AAClF,SAAS,2BAA2B,CAAC,OAAe;IACnD,OAAO,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAWD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAAc;IAC3D,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAC1C,gCAAgC,CAAC,OAAO,CAAC,IAAI,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACrD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpC,IAAI,YAAY,qBAAqB,IAAI,IAAI,CAAC,MAAM,KAAK,oBAAoB,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,gBAAgB,CAC/B,OAAyB,EACzB,UAAmC,EAAE;IAErC,OAAO,qBAAqB,CAAC,OAAO,EAAE;QACrC,QAAQ,EAAE,qBAAqB;QAC/B,QAAQ,EAAE,4BAA4B;QACtC,QAAQ,EAAE,4BAA4B;QACtC,WAAW,EAAE,6BAA6B;QAC1C,SAAS,EAAE,cAAc;KACzB,EAAE,OAAO,CAAC,CAAC;AACb,CAAC"}