@serfab/quereus-plugin-sereus 1.4.0 → 1.6.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.
@@ -5,6 +5,82 @@ import type { NodeOptions } from '@optimystic/db-p2p';
5
5
  * local storage without forming a cluster). A validation floor, not a default.
6
6
  */
7
7
  export declare const MIN_CLUSTER_SIZE = 2;
8
+ /**
9
+ * How long ONE cohort peer gets to answer ONE read-path request, in milliseconds — both
10
+ * networks' `clusterPolicy.cohortQueryTimeoutMs`. It sets the latest-revision query a read
11
+ * runs when its local copy may be stale (`CoordinatorRepo.queryClusterForLatest`) and the
12
+ * archive fetch that follows it (`fetchArchiveFromPeer`); Optimystic ties the two to one
13
+ * field because they are the same round trip to the same peer. Optimystic's own default is
14
+ * 1000 ms, a LAN-shaped budget, and it deliberately left that default alone — choosing the
15
+ * value for a deployment of phones is the embedder's job.
16
+ *
17
+ * **Why 5000.** Optimystic GitHub #22, reported by a sereus-based chat app: two parties that
18
+ * reach each other only through a public circuit relay have a round trip near 1.8 s, and a
19
+ * fresh stream (dial or reuse, protocol select, send, receive) cannot finish inside a second.
20
+ * At a cohort of two there is exactly one peer to ask, so one late answer leaves the read with
21
+ * nothing to corroborate against and it is declined. 5000 covers 1.8 s with room for the Noise
22
+ * handshake, the relay hops and a phone's pure-JS crypto (cadre-core's
23
+ * `NetworkConfig.noiseCrypto`), and it is the value Optimystic's own note advises for that
24
+ * link. The whole-pass reconcile bound Optimystic derives from it (`max(5000, 5 x this)`)
25
+ * becomes 25 s.
26
+ *
27
+ * **Measured** 2026-09-26, one Windows developer machine, two relay-only `CadreNode`s on one
28
+ * shared loopback dedicated relay, the one-way outbound frame delay raised to 900 ms
29
+ * (`pipelined` mode — see `docs/testing.md` → "Where measurements live") AFTER the strand had
30
+ * formed and first synced, for a round trip near 1.8 s. A machine that had joined, gone away
31
+ * while the other wrote, then re-attached over its own stale store and read the row written
32
+ * while it was away. Declined reads over that journey, after the delay was raised: **18 at
33
+ * Optimystic's 1000 ms, 2 at 5000 ms.** A declined read is
34
+ * `cluster-fetch:peers-silent { silent: 1, consulted: 2 }` followed by
35
+ * `cluster-fetch:no-quorum`, retried about a second later until one lands; at 5000 the
36
+ * corroboration succeeded instead (`cluster-fetch:local-current`). Both journeys COMPLETED at
37
+ * either value, which is why no committed scenario gates this — 900 ms is not where it breaks,
38
+ * and above it a run breaks on redialling instead. The recipe for re-measuring is in
39
+ * `docs/testing.md` → "Where measurements live".
40
+ *
41
+ * **What it costs**, in the terms Optimystic's own field doc uses: a peer that is truly gone
42
+ * now holds a read of a block missing locally for up to 5 s before the read is declined
43
+ * instead of 1 s. A joining machine's first sync runs several such consults, so it is the cost
44
+ * that binds — and the first-sync band measured at BOTH deadlines, against the budget it has
45
+ * to fit, is recorded once, on `DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS` in cadre-core's
46
+ * `strand-first-sync-gate.ts`. At 5000 against the 30 s budget that preceded it, this change
47
+ * would have turned a slow-but-working join into the very `StrandAwaitingFirstSyncError` the
48
+ * report named. 3000 is the fallback if that margin ever goes — still 1.7x the reported round
49
+ * trip, and a doomed consult costs 40% less.
50
+ *
51
+ * **What else it lengthens, which the first-sync budget is only the largest case of.** Every
52
+ * cadre-core deadline that wraps an Optimystic read or commit was sized when one silent peer
53
+ * cost 1 s and a whole reconcile pass cost 5 s; those are now 5 s and 25 s. Two consequences
54
+ * are already true rather than hypothetical:
55
+ *
56
+ * - The inbound membership admission gate reads the control database uncached and FAILS OPEN
57
+ * after 2 s (`ADMISSION_DECISION_TIMEOUT_MS`, cadre-core's
58
+ * `membership-connection-gater.ts`), so a decision whose read consults a silent peer can no
59
+ * longer settle inside that deadline at all: an unplaced peer is admitted at the connection
60
+ * layer for the whole 5 s instead of roughly 1 s. It is admitted to nothing more than a
61
+ * connection — the per-protocol stream gates still decide, and unplaced relay reservations
62
+ * stay capped (`MAX_UNAUTHORIZED_RELAY_RESERVATIONS`) — which is why this is a widened cost
63
+ * and not a hole. `backlog/debt-cadre-deadlines-sized-against-old-optimystic-bounds` owns
64
+ * the audit of the rest.
65
+ * - `CONTROL_READ_RETRY_BUDGET_MS` (1500 ms) now terminates the control-read retry loop after
66
+ * the FIRST attempt whenever that attempt burned this deadline, so a read failing that way
67
+ * gets no second presentation. Its own doc carries the coupling.
68
+ *
69
+ * **One value for both networks, not two.** The reason to widen is the link, and a phone's
70
+ * control node and its strand nodes share it; nothing about control traffic or strand traffic
71
+ * argues for different numbers. A host that needs another value moves both at once —
72
+ * cadre-core's `NetworkConfig.cohortQueryTimeoutMs`, threaded to {@link controlClusterPolicy}
73
+ * and {@link strandClusterPolicy}.
74
+ *
75
+ * NOTE: this number and the first-sync budget are coupled; the margin between that budget and
76
+ * the slowest first sync measured is stated on it. Re-measure the first-sync band before raising
77
+ * this again, or when a deployment's first sync grows more collections than the two-table
78
+ * scenario measured above — `DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS` carries the result and
79
+ * `docs/testing.md` the recipe.
80
+ * Nothing warns when the margin goes; the symptom is `StrandAwaitingFirstSyncError` on a join
81
+ * that was progressing normally, which is the failure this pair of numbers exists to end.
82
+ */
83
+ export declare const COHORT_READ_DEADLINE_MS = 5000;
8
84
  /**
9
85
  * How many nodes each block of the **control** (cadre membership) database is replicated
10
86
  * to. Chosen to exceed any party's node count, so in practice every control block lands
@@ -110,6 +186,10 @@ export declare const CONTROL_REPLICATION_BREADTH = 16;
110
186
  * whether this node believes a repair answer), which is exactly why the two are now separate
111
187
  * numbers rather than one.
112
188
  *
189
+ * `cohortQueryTimeoutMs` is declared for the same reason it is declared on the strand policy —
190
+ * the link, not the network ({@link COHORT_READ_DEADLINE_MS}). Absent it, Optimystic's LAN-shaped
191
+ * 1000 ms would leave a control read over a relayed link with no corroborating answer in time.
192
+ *
113
193
  * The `satisfies` is load-bearing: without it a mistyped or obsolete key would compile at both
114
194
  * this definition and every consumer, because TypeScript only excess-property-checks fresh
115
195
  * object literals, not a shared constant handed to `clusterPolicy`.
@@ -118,6 +198,7 @@ export declare const CONTROL_CLUSTER_POLICY: Readonly<{
118
198
  allowDownsize: true;
119
199
  sizeTolerance: number;
120
200
  assumedClusterSize: number;
201
+ cohortQueryTimeoutMs: number;
121
202
  }>;
122
203
  /**
123
204
  * Default number of nodes a **strand** network is told its replication cluster should have.
@@ -258,12 +339,18 @@ export declare const DEFAULT_STRAND_CLUSTER_SIZE = 4;
258
339
  * promise that `ceil(0.75 x N)` of its machines are awake, and the admission gate would refuse
259
340
  * its writes. Same reason and same warning as {@link CONTROL_CLUSTER_POLICY}'s.
260
341
  *
342
+ * `cohortQueryTimeoutMs` is {@link COHORT_READ_DEADLINE_MS}, the same value the control policy
343
+ * declares. That is the one field the two networks deliberately agree on by argument rather than
344
+ * by coincidence: it is a property of the LINK, and a phone's control node and its strand nodes
345
+ * ride the same one.
346
+ *
261
347
  * The `satisfies` is load-bearing for the same reason as {@link CONTROL_CLUSTER_POLICY}'s.
262
348
  */
263
349
  export declare const STRAND_CLUSTER_POLICY: Readonly<{
264
350
  allowDownsize: true;
265
351
  sizeTolerance: number;
266
352
  assumedClusterSize: number;
353
+ cohortQueryTimeoutMs: number;
267
354
  }>;
268
355
  /**
269
356
  * Resolve the cluster size to hand `createLibp2pNode` for a **strand** network, applying
@@ -376,27 +463,37 @@ export declare function resolveStrandClusterSize(configured?: number): number;
376
463
  */
377
464
  export declare function resolveRepairYardstick(servingMachines: number, replicationBreadth: number): number;
378
465
  /**
379
- * {@link CONTROL_CLUSTER_POLICY} with the repair yardstick declared from `enrolledMachines`
380
- * (see {@link resolveRepairYardstick}); the frozen base object ITSELF when the count is unknown,
381
- * so the cold path is provably today's behaviour and identity assertions keep holding.
382
- *
383
- * The parameter keeps the name `enrolledMachines`, unlike {@link strandClusterPolicy}'s, because
384
- * for the CONTROL network the two quantities are one and the same by construction: every
385
- * enrolled machine runs the control node, so the machines enrolled in the party ARE the machines
386
- * serving this network.
466
+ * {@link CONTROL_CLUSTER_POLICY} with the block-repair corroboration yardstick declared from
467
+ * `enrolledMachines` (see {@link resolveRepairYardstick}) and the per-peer read deadline replaced
468
+ * by the host's `cohortQueryTimeoutMs`; the frozen base object ITSELF when neither is declared, so
469
+ * identity assertions keep holding — including for the host that passes a `network` block with
470
+ * neither field in it, whose declarations arrive present-but-`undefined`.
471
+ *
472
+ * The count is named `enrolledMachines` here, unlike {@link strandClusterPolicy}'s, because for the
473
+ * CONTROL network the two quantities are one and the same by construction: every enrolled machine
474
+ * runs the control node, so the machines enrolled in the party ARE the machines serving this
475
+ * network.
387
476
  */
388
- export declare function controlClusterPolicy(enrolledMachines?: number): NonNullable<NodeOptions['clusterPolicy']>;
477
+ export declare function controlClusterPolicy(declared?: {
478
+ enrolledMachines?: number;
479
+ cohortQueryTimeoutMs?: number;
480
+ }): NonNullable<NodeOptions['clusterPolicy']>;
389
481
  /**
390
- * {@link STRAND_CLUSTER_POLICY} with the repair yardstick declared from `servingMachines` — the
391
- * machines that serve THIS strand — and this strand's own `clusterSize` (already resolved by
392
- * {@link resolveStrandClusterSize}, so it is at least {@link MIN_CLUSTER_SIZE} and the formula's
393
- * two clamps can never cross); the frozen base object ITSELF when the count is unknown.
394
- *
395
- * **The unknown path is the production path today.** No authenticated per-strand serving count
482
+ * {@link STRAND_CLUSTER_POLICY} with the block-repair corroboration yardstick declared from
483
+ * `servingMachines` — the machines that serve THIS strand — capped at this strand's own
484
+ * `clusterSize` (already resolved by {@link resolveStrandClusterSize}, so it is at least
485
+ * {@link MIN_CLUSTER_SIZE} and the formula's two clamps can never cross), and the per-peer read
486
+ * deadline replaced by the host's `cohortQueryTimeoutMs`; the frozen base object ITSELF when
487
+ * neither is declared.
488
+ *
489
+ * **The no-count path is the production path today.** No authenticated per-strand serving count
396
490
  * exists, and the party's enrolled-machine count is emphatically not one (see
397
- * {@link resolveRepairYardstick}'s contract section), so cadre-core passes nothing and every
398
- * strand node runs the frozen constant. The parameter and its threading through
399
- * `StartStrandConfig.servingMachines` stay in place as the seam that
491
+ * {@link resolveRepairYardstick}'s contract section), so cadre-core declares no count and every
492
+ * strand node of a host that declared no deadline runs the frozen constant. The field and its
493
+ * threading through `StartStrandConfig.servingMachines` stay in place as the seam that
400
494
  * `backlog/feat-strand-yardstick-from-serving-machines` plugs a real count into.
401
495
  */
402
- export declare function strandClusterPolicy(clusterSize: number, servingMachines?: number): NonNullable<NodeOptions['clusterPolicy']>;
496
+ export declare function strandClusterPolicy(clusterSize: number, declared?: {
497
+ servingMachines?: number;
498
+ cohortQueryTimeoutMs?: number;
499
+ }): NonNullable<NodeOptions['clusterPolicy']>;
@@ -4,6 +4,82 @@
4
4
  * local storage without forming a cluster). A validation floor, not a default.
5
5
  */
6
6
  export const MIN_CLUSTER_SIZE = 2;
7
+ /**
8
+ * How long ONE cohort peer gets to answer ONE read-path request, in milliseconds — both
9
+ * networks' `clusterPolicy.cohortQueryTimeoutMs`. It sets the latest-revision query a read
10
+ * runs when its local copy may be stale (`CoordinatorRepo.queryClusterForLatest`) and the
11
+ * archive fetch that follows it (`fetchArchiveFromPeer`); Optimystic ties the two to one
12
+ * field because they are the same round trip to the same peer. Optimystic's own default is
13
+ * 1000 ms, a LAN-shaped budget, and it deliberately left that default alone — choosing the
14
+ * value for a deployment of phones is the embedder's job.
15
+ *
16
+ * **Why 5000.** Optimystic GitHub #22, reported by a sereus-based chat app: two parties that
17
+ * reach each other only through a public circuit relay have a round trip near 1.8 s, and a
18
+ * fresh stream (dial or reuse, protocol select, send, receive) cannot finish inside a second.
19
+ * At a cohort of two there is exactly one peer to ask, so one late answer leaves the read with
20
+ * nothing to corroborate against and it is declined. 5000 covers 1.8 s with room for the Noise
21
+ * handshake, the relay hops and a phone's pure-JS crypto (cadre-core's
22
+ * `NetworkConfig.noiseCrypto`), and it is the value Optimystic's own note advises for that
23
+ * link. The whole-pass reconcile bound Optimystic derives from it (`max(5000, 5 x this)`)
24
+ * becomes 25 s.
25
+ *
26
+ * **Measured** 2026-09-26, one Windows developer machine, two relay-only `CadreNode`s on one
27
+ * shared loopback dedicated relay, the one-way outbound frame delay raised to 900 ms
28
+ * (`pipelined` mode — see `docs/testing.md` → "Where measurements live") AFTER the strand had
29
+ * formed and first synced, for a round trip near 1.8 s. A machine that had joined, gone away
30
+ * while the other wrote, then re-attached over its own stale store and read the row written
31
+ * while it was away. Declined reads over that journey, after the delay was raised: **18 at
32
+ * Optimystic's 1000 ms, 2 at 5000 ms.** A declined read is
33
+ * `cluster-fetch:peers-silent { silent: 1, consulted: 2 }` followed by
34
+ * `cluster-fetch:no-quorum`, retried about a second later until one lands; at 5000 the
35
+ * corroboration succeeded instead (`cluster-fetch:local-current`). Both journeys COMPLETED at
36
+ * either value, which is why no committed scenario gates this — 900 ms is not where it breaks,
37
+ * and above it a run breaks on redialling instead. The recipe for re-measuring is in
38
+ * `docs/testing.md` → "Where measurements live".
39
+ *
40
+ * **What it costs**, in the terms Optimystic's own field doc uses: a peer that is truly gone
41
+ * now holds a read of a block missing locally for up to 5 s before the read is declined
42
+ * instead of 1 s. A joining machine's first sync runs several such consults, so it is the cost
43
+ * that binds — and the first-sync band measured at BOTH deadlines, against the budget it has
44
+ * to fit, is recorded once, on `DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS` in cadre-core's
45
+ * `strand-first-sync-gate.ts`. At 5000 against the 30 s budget that preceded it, this change
46
+ * would have turned a slow-but-working join into the very `StrandAwaitingFirstSyncError` the
47
+ * report named. 3000 is the fallback if that margin ever goes — still 1.7x the reported round
48
+ * trip, and a doomed consult costs 40% less.
49
+ *
50
+ * **What else it lengthens, which the first-sync budget is only the largest case of.** Every
51
+ * cadre-core deadline that wraps an Optimystic read or commit was sized when one silent peer
52
+ * cost 1 s and a whole reconcile pass cost 5 s; those are now 5 s and 25 s. Two consequences
53
+ * are already true rather than hypothetical:
54
+ *
55
+ * - The inbound membership admission gate reads the control database uncached and FAILS OPEN
56
+ * after 2 s (`ADMISSION_DECISION_TIMEOUT_MS`, cadre-core's
57
+ * `membership-connection-gater.ts`), so a decision whose read consults a silent peer can no
58
+ * longer settle inside that deadline at all: an unplaced peer is admitted at the connection
59
+ * layer for the whole 5 s instead of roughly 1 s. It is admitted to nothing more than a
60
+ * connection — the per-protocol stream gates still decide, and unplaced relay reservations
61
+ * stay capped (`MAX_UNAUTHORIZED_RELAY_RESERVATIONS`) — which is why this is a widened cost
62
+ * and not a hole. `backlog/debt-cadre-deadlines-sized-against-old-optimystic-bounds` owns
63
+ * the audit of the rest.
64
+ * - `CONTROL_READ_RETRY_BUDGET_MS` (1500 ms) now terminates the control-read retry loop after
65
+ * the FIRST attempt whenever that attempt burned this deadline, so a read failing that way
66
+ * gets no second presentation. Its own doc carries the coupling.
67
+ *
68
+ * **One value for both networks, not two.** The reason to widen is the link, and a phone's
69
+ * control node and its strand nodes share it; nothing about control traffic or strand traffic
70
+ * argues for different numbers. A host that needs another value moves both at once —
71
+ * cadre-core's `NetworkConfig.cohortQueryTimeoutMs`, threaded to {@link controlClusterPolicy}
72
+ * and {@link strandClusterPolicy}.
73
+ *
74
+ * NOTE: this number and the first-sync budget are coupled; the margin between that budget and
75
+ * the slowest first sync measured is stated on it. Re-measure the first-sync band before raising
76
+ * this again, or when a deployment's first sync grows more collections than the two-table
77
+ * scenario measured above — `DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS` carries the result and
78
+ * `docs/testing.md` the recipe.
79
+ * Nothing warns when the margin goes; the symptom is `StrandAwaitingFirstSyncError` on a join
80
+ * that was progressing normally, which is the failure this pair of numbers exists to end.
81
+ */
82
+ export const COHORT_READ_DEADLINE_MS = 5000;
7
83
  /**
8
84
  * How many nodes each block of the **control** (cadre membership) database is replicated
9
85
  * to. Chosen to exceed any party's node count, so in practice every control block lands
@@ -109,6 +185,10 @@ export const CONTROL_REPLICATION_BREADTH = 16;
109
185
  * whether this node believes a repair answer), which is exactly why the two are now separate
110
186
  * numbers rather than one.
111
187
  *
188
+ * `cohortQueryTimeoutMs` is declared for the same reason it is declared on the strand policy —
189
+ * the link, not the network ({@link COHORT_READ_DEADLINE_MS}). Absent it, Optimystic's LAN-shaped
190
+ * 1000 ms would leave a control read over a relayed link with no corroborating answer in time.
191
+ *
112
192
  * The `satisfies` is load-bearing: without it a mistyped or obsolete key would compile at both
113
193
  * this definition and every consumer, because TypeScript only excess-property-checks fresh
114
194
  * object literals, not a shared constant handed to `clusterPolicy`.
@@ -117,6 +197,7 @@ export const CONTROL_CLUSTER_POLICY = Object.freeze({
117
197
  allowDownsize: true,
118
198
  sizeTolerance: 0.5,
119
199
  assumedClusterSize: 2,
200
+ cohortQueryTimeoutMs: COHORT_READ_DEADLINE_MS,
120
201
  });
121
202
  /**
122
203
  * Default number of nodes a **strand** network is told its replication cluster should have.
@@ -257,12 +338,18 @@ export const DEFAULT_STRAND_CLUSTER_SIZE = 4;
257
338
  * promise that `ceil(0.75 x N)` of its machines are awake, and the admission gate would refuse
258
339
  * its writes. Same reason and same warning as {@link CONTROL_CLUSTER_POLICY}'s.
259
340
  *
341
+ * `cohortQueryTimeoutMs` is {@link COHORT_READ_DEADLINE_MS}, the same value the control policy
342
+ * declares. That is the one field the two networks deliberately agree on by argument rather than
343
+ * by coincidence: it is a property of the LINK, and a phone's control node and its strand nodes
344
+ * ride the same one.
345
+ *
260
346
  * The `satisfies` is load-bearing for the same reason as {@link CONTROL_CLUSTER_POLICY}'s.
261
347
  */
262
348
  export const STRAND_CLUSTER_POLICY = Object.freeze({
263
349
  allowDownsize: true,
264
350
  sizeTolerance: 0.5,
265
351
  assumedClusterSize: MIN_CLUSTER_SIZE,
352
+ cohortQueryTimeoutMs: COHORT_READ_DEADLINE_MS,
266
353
  });
267
354
  /**
268
355
  * Resolve the cluster size to hand `createLibp2pNode` for a **strand** network, applying
@@ -398,46 +485,74 @@ function asKnownMachineCount(servingMachines) {
398
485
  : undefined;
399
486
  }
400
487
  /**
401
- * {@link CONTROL_CLUSTER_POLICY} with the repair yardstick declared from `enrolledMachines`
402
- * (see {@link resolveRepairYardstick}); the frozen base object ITSELF when the count is unknown,
403
- * so the cold path is provably today's behaviour and identity assertions keep holding.
404
- *
405
- * The parameter keeps the name `enrolledMachines`, unlike {@link strandClusterPolicy}'s, because
406
- * for the CONTROL network the two quantities are one and the same by construction: every
407
- * enrolled machine runs the control node, so the machines enrolled in the party ARE the machines
408
- * serving this network.
488
+ * The base policy with whatever was declared onto it — or the base object ITSELF, by identity,
489
+ * when nothing was, which is the production path for both networks today and so is provably
490
+ * byte-for-byte the old behaviour.
491
+ *
492
+ * The two spreads are independent, so neither declaration can shadow the other: they arrive from
493
+ * unrelated sources (a node-local machine record, the host's network config) and either may be
494
+ * present alone.
495
+ *
496
+ * `cohortQueryTimeoutMs` is passed through UNVALIDATED, by design. Optimystic already refuses a
497
+ * value that is not a finite number above zero, or is above its `MAX_COHORT_QUERY_TIMEOUT_MS`, and
498
+ * it THROWS where the libp2p node is constructed rather than falling back to its own default — so a
499
+ * second check here would only duplicate a message the host already gets, at a site that cannot
500
+ * name the node being built.
409
501
  */
410
- export function controlClusterPolicy(enrolledMachines) {
411
- const known = asKnownMachineCount(enrolledMachines);
412
- if (known === undefined) {
413
- return CONTROL_CLUSTER_POLICY;
502
+ function declarePolicy({ base, yardstickCap, machines, cohortQueryTimeoutMs }) {
503
+ const known = asKnownMachineCount(machines);
504
+ if (known === undefined && cohortQueryTimeoutMs === undefined) {
505
+ return base;
414
506
  }
415
507
  return Object.freeze({
416
- ...CONTROL_CLUSTER_POLICY,
417
- repairCorroborationClusterSize: resolveRepairYardstick(known, CONTROL_REPLICATION_BREADTH)
508
+ ...base,
509
+ ...(known !== undefined && {
510
+ repairCorroborationClusterSize: resolveRepairYardstick(known, yardstickCap)
511
+ }),
512
+ ...(cohortQueryTimeoutMs !== undefined && { cohortQueryTimeoutMs })
418
513
  });
419
514
  }
420
515
  /**
421
- * {@link STRAND_CLUSTER_POLICY} with the repair yardstick declared from `servingMachines` — the
422
- * machines that serve THIS strand — and this strand's own `clusterSize` (already resolved by
423
- * {@link resolveStrandClusterSize}, so it is at least {@link MIN_CLUSTER_SIZE} and the formula's
424
- * two clamps can never cross); the frozen base object ITSELF when the count is unknown.
425
- *
426
- * **The unknown path is the production path today.** No authenticated per-strand serving count
516
+ * {@link CONTROL_CLUSTER_POLICY} with the block-repair corroboration yardstick declared from
517
+ * `enrolledMachines` (see {@link resolveRepairYardstick}) and the per-peer read deadline replaced
518
+ * by the host's `cohortQueryTimeoutMs`; the frozen base object ITSELF when neither is declared, so
519
+ * identity assertions keep holding — including for the host that passes a `network` block with
520
+ * neither field in it, whose declarations arrive present-but-`undefined`.
521
+ *
522
+ * The count is named `enrolledMachines` here, unlike {@link strandClusterPolicy}'s, because for the
523
+ * CONTROL network the two quantities are one and the same by construction: every enrolled machine
524
+ * runs the control node, so the machines enrolled in the party ARE the machines serving this
525
+ * network.
526
+ */
527
+ export function controlClusterPolicy(declared = {}) {
528
+ return declarePolicy({
529
+ base: CONTROL_CLUSTER_POLICY,
530
+ yardstickCap: CONTROL_REPLICATION_BREADTH,
531
+ machines: declared.enrolledMachines,
532
+ cohortQueryTimeoutMs: declared.cohortQueryTimeoutMs
533
+ });
534
+ }
535
+ /**
536
+ * {@link STRAND_CLUSTER_POLICY} with the block-repair corroboration yardstick declared from
537
+ * `servingMachines` — the machines that serve THIS strand — capped at this strand's own
538
+ * `clusterSize` (already resolved by {@link resolveStrandClusterSize}, so it is at least
539
+ * {@link MIN_CLUSTER_SIZE} and the formula's two clamps can never cross), and the per-peer read
540
+ * deadline replaced by the host's `cohortQueryTimeoutMs`; the frozen base object ITSELF when
541
+ * neither is declared.
542
+ *
543
+ * **The no-count path is the production path today.** No authenticated per-strand serving count
427
544
  * exists, and the party's enrolled-machine count is emphatically not one (see
428
- * {@link resolveRepairYardstick}'s contract section), so cadre-core passes nothing and every
429
- * strand node runs the frozen constant. The parameter and its threading through
430
- * `StartStrandConfig.servingMachines` stay in place as the seam that
545
+ * {@link resolveRepairYardstick}'s contract section), so cadre-core declares no count and every
546
+ * strand node of a host that declared no deadline runs the frozen constant. The field and its
547
+ * threading through `StartStrandConfig.servingMachines` stay in place as the seam that
431
548
  * `backlog/feat-strand-yardstick-from-serving-machines` plugs a real count into.
432
549
  */
433
- export function strandClusterPolicy(clusterSize, servingMachines) {
434
- const known = asKnownMachineCount(servingMachines);
435
- if (known === undefined) {
436
- return STRAND_CLUSTER_POLICY;
437
- }
438
- return Object.freeze({
439
- ...STRAND_CLUSTER_POLICY,
440
- repairCorroborationClusterSize: resolveRepairYardstick(known, clusterSize)
550
+ export function strandClusterPolicy(clusterSize, declared = {}) {
551
+ return declarePolicy({
552
+ base: STRAND_CLUSTER_POLICY,
553
+ yardstickCap: clusterSize,
554
+ machines: declared.servingMachines,
555
+ cohortQueryTimeoutMs: declared.cohortQueryTimeoutMs
441
556
  });
442
557
  }
443
558
  //# sourceMappingURL=cluster-size.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cluster-size.js","sourceRoot":"","sources":["../src/cluster-size.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cluster-size.js","sourceRoot":"","sources":["../src/cluster-size.ts"],"names":[],"mappings":"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"}
@@ -113,6 +113,14 @@ export async function composeStrand(db, options, platform) {
113
113
  log('Using injected libp2p node');
114
114
  }
115
115
  else {
116
+ // NOTE: this path takes the frozen policy whole, so it takes COHORT_READ_DEADLINE_MS
117
+ // with no way to override it — `StrandConnectionOptions` has no counterpart to
118
+ // cadre-core's `NetworkConfig.cohortQueryTimeoutMs`. Fine today: every production
119
+ // strand comes up through cadre-core, which does thread the field, and this path is
120
+ // the plugin's own connect/e2e route where 5000 ms is the right answer anyway. If a
121
+ // plugin embedder ever needs a different deadline,
122
+ // `strandClusterPolicy(clusterSize, { cohortQueryTimeoutMs: <ms> })` is the call to
123
+ // reach for here.
116
124
  const created = await platform.createNode({ networkName, bootstrapNodes, fretProfile, port, clusterSize, clusterPolicy: STRAND_CLUSTER_POLICY, storage });
117
125
  createdNode = created;
118
126
  node = created;
@@ -168,6 +176,17 @@ export async function composeStrand(db, options, platform) {
168
176
  // SEAM: this and the Strand apply above are the single composition point
169
177
  // where strand-level declarative DDL is applied. Keep new schema wiring
170
178
  // here so it stays a one-location edit across Node, browser, and cadre-core.
179
+ //
180
+ // NOTE: neither apply is retried — a failure tears the strand down and throws,
181
+ // and a later connect builds a fresh `Database` and re-hydrates from storage. A
182
+ // failed apply is normally taken back whole (Quereus unwinds its migration steps
183
+ // and verifies the catalog against a pre-apply fingerprint), so the next connect
184
+ // diffs against the state the apply started from. The sApp schema is the one
185
+ // supplied by the EMBEDDER, and the steps that DISCARD data — dropping a table,
186
+ // dropping a column, narrowing a column's type — are irreversible to Quereus's
187
+ // differ: once one has run, any later step that fails leaves the schema partially
188
+ // migrated instead of restored. No schema in this repo evolves that way, so this
189
+ // is a note for whoever first ships a migration that does.
171
190
  if (schema) {
172
191
  log('Applying sApp schema for strand %s', strandId);
173
192
  await db.exec(`
@@ -1 +1 @@
1
- {"version":3,"file":"compose-strand.js","sourceRoot":"","sources":["../src/compose-strand.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compose-strand.js","sourceRoot":"","sources":["../src/compose-strand.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { connectToStrand } from './connect.js';
2
- export { MIN_CLUSTER_SIZE, CONTROL_REPLICATION_BREADTH, CONTROL_CLUSTER_POLICY, DEFAULT_STRAND_CLUSTER_SIZE, STRAND_CLUSTER_POLICY, resolveStrandClusterSize, resolveRepairYardstick, controlClusterPolicy, strandClusterPolicy } from './cluster-size.js';
2
+ export { MIN_CLUSTER_SIZE, COHORT_READ_DEADLINE_MS, CONTROL_REPLICATION_BREADTH, CONTROL_CLUSTER_POLICY, DEFAULT_STRAND_CLUSTER_SIZE, STRAND_CLUSTER_POLICY, resolveStrandClusterSize, resolveRepairYardstick, controlClusterPolicy, strandClusterPolicy } from './cluster-size.js';
3
3
  export { wrapStorageWithCache, disposeStorageCache } from './cached-storage.js';
4
4
  export type { StrandConnectionOptions, SereusPluginResult, StrandTransactor } from './types.js';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { connectToStrand } from './connect.js';
2
- export { MIN_CLUSTER_SIZE, CONTROL_REPLICATION_BREADTH, CONTROL_CLUSTER_POLICY, DEFAULT_STRAND_CLUSTER_SIZE, STRAND_CLUSTER_POLICY, resolveStrandClusterSize, resolveRepairYardstick, controlClusterPolicy, strandClusterPolicy } from './cluster-size.js';
2
+ export { MIN_CLUSTER_SIZE, COHORT_READ_DEADLINE_MS, CONTROL_REPLICATION_BREADTH, CONTROL_CLUSTER_POLICY, DEFAULT_STRAND_CLUSTER_SIZE, STRAND_CLUSTER_POLICY, resolveStrandClusterSize, resolveRepairYardstick, controlClusterPolicy, strandClusterPolicy } from './cluster-size.js';
3
3
  export { wrapStorageWithCache, disposeStorageCache } from './cached-storage.js';
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACN,gBAAgB,EAChB,2BAA2B,EAC3B,sBAAsB,EACtB,2BAA2B,EAC3B,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACN,gBAAgB,EAChB,uBAAuB,EACvB,2BAA2B,EAC3B,sBAAsB,EACtB,2BAA2B,EAC3B,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}