@serfab/cadre-core 0.9.0 → 0.11.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.
- package/README.md +255 -253
- package/dist/bootstrap-peer-store-file.d.ts +13 -0
- package/dist/bootstrap-peer-store-file.js +42 -0
- package/dist/bootstrap-peer-store-file.js.map +1 -0
- package/dist/bootstrap-peer-store.d.ts +73 -0
- package/dist/bootstrap-peer-store.js +128 -0
- package/dist/bootstrap-peer-store.js.map +1 -0
- package/dist/cadre-node.d.ts +1121 -81
- package/dist/cadre-node.js +2276 -262
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +93 -0
- package/dist/control-authorization.js +57 -0
- package/dist/control-authorization.js.map +1 -0
- package/dist/control-cohort.d.ts +26 -0
- package/dist/control-cohort.js +26 -0
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +959 -54
- package/dist/control-database.js +1421 -148
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +90 -10
- package/dist/control-formation-recorder.js +130 -14
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +651 -72
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +38 -4
- package/dist/control-stream.js +70 -4
- package/dist/control-stream.js.map +1 -1
- package/dist/control-write-retry.d.ts +161 -0
- package/dist/control-write-retry.js +412 -0
- package/dist/control-write-retry.js.map +1 -0
- package/dist/delegate-admission.d.ts +134 -0
- package/dist/delegate-admission.js +244 -0
- package/dist/delegate-admission.js.map +1 -0
- package/dist/device-token.d.ts +11 -11
- package/dist/device-token.js +14 -13
- package/dist/device-token.js.map +1 -1
- package/dist/ed25519-key.d.ts +26 -0
- package/dist/ed25519-key.js +56 -1
- package/dist/ed25519-key.js.map +1 -1
- package/dist/file-durable-slot.d.ts +20 -0
- package/dist/file-durable-slot.js +53 -0
- package/dist/file-durable-slot.js.map +1 -0
- package/dist/formation-approval.d.ts +157 -0
- package/dist/formation-approval.js +375 -0
- package/dist/formation-approval.js.map +1 -0
- package/dist/fs-atomic.d.ts +38 -0
- package/dist/fs-atomic.js +97 -0
- package/dist/fs-atomic.js.map +1 -0
- package/dist/identity-key.d.ts +49 -0
- package/dist/identity-key.js +81 -0
- package/dist/identity-key.js.map +1 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.js +40 -6
- package/dist/index.js.map +1 -1
- package/dist/key-store-file.d.ts +2 -24
- package/dist/key-store-file.js +10 -77
- package/dist/key-store-file.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +146 -0
- package/dist/membership-connection-gater.js +180 -0
- package/dist/membership-connection-gater.js.map +1 -0
- package/dist/node-local-snapshot.d.ts +109 -0
- package/dist/node-local-snapshot.js +182 -0
- package/dist/node-local-snapshot.js.map +1 -0
- package/dist/peer-addr-book.d.ts +92 -0
- package/dist/peer-addr-book.js +220 -0
- package/dist/peer-addr-book.js.map +1 -0
- package/dist/peer-authorization.d.ts +135 -18
- package/dist/peer-authorization.js +152 -21
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-record.d.ts +21 -8
- package/dist/peer-record.js +26 -10
- package/dist/peer-record.js.map +1 -1
- package/dist/relay-addrs.d.ts +45 -0
- package/dist/relay-addrs.js +103 -0
- package/dist/relay-addrs.js.map +1 -0
- package/dist/relay-reservation.d.ts +266 -0
- package/dist/relay-reservation.js +613 -0
- package/dist/relay-reservation.js.map +1 -0
- package/dist/seed-bootstrap.d.ts +228 -56
- package/dist/seed-bootstrap.js +340 -198
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +47 -21
- package/dist/seed-trust-policy.js +24 -15
- package/dist/seed-trust-policy.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +42 -13
- package/dist/strand-addr-protocol.js +58 -52
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-backfill.d.ts +109 -0
- package/dist/strand-backfill.js +279 -0
- package/dist/strand-backfill.js.map +1 -0
- package/dist/strand-cohort.d.ts +4 -37
- package/dist/strand-cohort.js +4 -15
- package/dist/strand-cohort.js.map +1 -1
- package/dist/strand-database.d.ts +11 -16
- package/dist/strand-database.js +19 -7
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-formation-manager.d.ts +36 -7
- package/dist/strand-formation-manager.js +115 -15
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +103 -4
- package/dist/strand-formation-protocol.js +232 -4
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +88 -19
- package/dist/strand-instance-manager.js +178 -34
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-member-registry.d.ts +5 -5
- package/dist/strand-member-registry.js +18 -10
- package/dist/strand-member-registry.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +484 -88
- package/dist/strand-membership-writer.js +751 -128
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-solicitation.d.ts +99 -33
- package/dist/strand-solicitation.js +100 -52
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-transport-key.d.ts +40 -0
- package/dist/strand-transport-key.js +56 -0
- package/dist/strand-transport-key.js.map +1 -0
- package/dist/strand-wake-protocol.d.ts +9 -7
- package/dist/strand-wake-protocol.js +22 -46
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/strand-watcher.d.ts +17 -2
- package/dist/strand-watcher.js +47 -3
- package/dist/strand-watcher.js.map +1 -1
- package/dist/trusted-owner-store-file.d.ts +12 -0
- package/dist/trusted-owner-store-file.js +39 -0
- package/dist/trusted-owner-store-file.js.map +1 -0
- package/dist/trusted-owner-store.d.ts +64 -0
- package/dist/trusted-owner-store.js +126 -0
- package/dist/trusted-owner-store.js.map +1 -0
- package/dist/types.d.ts +307 -44
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/package.json +20 -8
- package/src/arachnode-stub.ts +159 -159
- package/src/bootstrap-peer-store-file.ts +44 -0
- package/src/bootstrap-peer-store.ts +172 -0
- package/src/cadre-node.ts +5158 -2981
- package/src/canonical-json.ts +30 -30
- package/src/control-authorization.ts +114 -0
- package/src/control-cohort.ts +130 -103
- package/src/control-database.ts +2406 -948
- package/src/control-formation-recorder.ts +305 -151
- package/src/control-schema.ts +651 -72
- package/src/control-stream.ts +205 -128
- package/src/control-write-retry.ts +483 -0
- package/src/delegate-admission.ts +302 -0
- package/src/device-token.ts +94 -89
- package/src/diagnostics/connection-path.ts +277 -277
- package/src/diagnostics/webrtc-turn-tracker.ts +222 -222
- package/src/ed25519-key.ts +66 -1
- package/src/enrollment.ts +199 -199
- package/src/file-durable-slot.ts +61 -0
- package/src/formation-approval.ts +604 -0
- package/src/fs-atomic.ts +107 -0
- package/src/hibernation-manager.ts +437 -437
- package/src/identity-key.ts +109 -0
- package/src/index.ts +137 -5
- package/src/key-store-file.ts +132 -203
- package/src/key-store.ts +99 -99
- package/src/membership-connection-gater.ts +204 -0
- package/src/node-local-snapshot.ts +260 -0
- package/src/peer-addr-book.ts +250 -0
- package/src/peer-authorization.ts +259 -81
- package/src/peer-record.ts +164 -146
- package/src/push-credentials.ts +84 -84
- package/src/push-node.ts +64 -64
- package/src/push-notifier-apns.ts +247 -247
- package/src/push-notifier-fcm.ts +220 -220
- package/src/push-notifier-shared.ts +28 -28
- package/src/push-notifier.ts +52 -52
- package/src/relay-addrs.ts +111 -0
- package/src/relay-reservation.ts +823 -0
- package/src/seed-bootstrap.ts +409 -209
- package/src/seed-trust-policy.ts +140 -107
- package/src/strand-addr-protocol.ts +441 -410
- package/src/strand-backfill.ts +366 -0
- package/src/strand-cohort.ts +38 -77
- package/src/strand-database.ts +202 -204
- package/src/strand-formation-manager.ts +491 -368
- package/src/strand-formation-protocol.ts +692 -391
- package/src/strand-instance-manager.ts +201 -46
- package/src/strand-member-key.ts +39 -39
- package/src/strand-member-registry.ts +182 -177
- package/src/strand-membership-writer.ts +938 -146
- package/src/strand-solicitation.ts +472 -407
- package/src/strand-transport-key.ts +58 -0
- package/src/strand-wake-payload.ts +32 -32
- package/src/strand-wake-protocol.ts +314 -331
- package/src/strand-watcher.ts +314 -251
- package/src/trusted-owner-store-file.ts +41 -0
- package/src/trusted-owner-store.ts +171 -0
- package/src/types.ts +1309 -1032
|
@@ -20,16 +20,86 @@
|
|
|
20
20
|
import debug from 'debug';
|
|
21
21
|
import { multiaddr } from '@multiformats/multiaddr';
|
|
22
22
|
import { writeFrame, withTimeout } from './control-stream.js';
|
|
23
|
+
import { canonicalJson } from './canonical-json.js';
|
|
24
|
+
import { requireEd25519PublicKeyB64 } from './ed25519-key.js';
|
|
25
|
+
import { verifyFormationConsent } from './peer-authorization.js';
|
|
26
|
+
// seed-bootstrap imports neither this protocol nor the manager/solicitation layers,
|
|
27
|
+
// so this import introduces no cycle.
|
|
28
|
+
import { ed25519PublicKeyB64FromPeerId } from './seed-bootstrap.js';
|
|
23
29
|
const log = debug('sereus:cadre:formation-proto');
|
|
24
30
|
/** Protocol id for the native formation transport (parallel to `/sereus/seed/1.0.0`). */
|
|
25
31
|
export const FORMATION_PROTOCOL = '/sereus/formation/1.0.0';
|
|
32
|
+
/**
|
|
33
|
+
* Rejection reason for an invitation that cannot be redeemed at all — unknown, expired, or
|
|
34
|
+
* fully spent. Shared with `StrandFormationManager`, which reports an
|
|
35
|
+
* `InvitationExhaustedError` (an invite spent out from under a redemption already in flight)
|
|
36
|
+
* with this SAME wording on purpose: a joiner that lost the race must be indistinguishable
|
|
37
|
+
* from a non-racing latecomer, so the two sites must never drift apart.
|
|
38
|
+
*/
|
|
39
|
+
export const INVALID_TOKEN_REASON = 'Invalid token';
|
|
26
40
|
/** Maximum formation message size (1MB). */
|
|
27
41
|
const MAX_FORMATION_MSG_SIZE = 1024 * 1024;
|
|
28
42
|
/** Default whole-session timeout (ms). */
|
|
29
43
|
const DEFAULT_SESSION_TIMEOUT_MS = 30000;
|
|
30
44
|
/** Default per-step (single read/write) timeout (ms). */
|
|
31
45
|
const DEFAULT_STEP_TIMEOUT_MS = 5000;
|
|
32
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Default provisioning budget (ms) — distinct from {@link DEFAULT_STEP_TIMEOUT_MS} because
|
|
48
|
+
* `provisionStrand` is real work (DB writes, and an outbound approval-hook HTTP call when
|
|
49
|
+
* the invite carries a `ValidationUrl`), not a bare wire read/write.
|
|
50
|
+
*
|
|
51
|
+
* Ordering is deliberate — each layer must be able to fail and report before the layer above
|
|
52
|
+
* it gives up:
|
|
53
|
+
*
|
|
54
|
+
* approval hook (10 s, `formation-approval.ts`)
|
|
55
|
+
* < responder provisioning (12 s)
|
|
56
|
+
* < initiator await-response (15 s)
|
|
57
|
+
* < session (30 s)
|
|
58
|
+
*
|
|
59
|
+
* The 3 s margin between responder provisioning and initiator await-response is the wire
|
|
60
|
+
* latency budget for the result frame to travel back.
|
|
61
|
+
*
|
|
62
|
+
* The last {@link PROVISION_SETTLE_GRACE_MS} of this budget is a settle grace, so the default
|
|
63
|
+
* WORK budget (12 s − 2 s = 10 s) EQUALS the hook's own 10 s: a dead hook races 'Formation
|
|
64
|
+
* approval unavailable, retry' against 'Formation provisioning timed out'. Both are retryable
|
|
65
|
+
* and both leave the invite unspent, so the race is benign.
|
|
66
|
+
*/
|
|
67
|
+
const DEFAULT_PROVISION_TIMEOUT_MS = 12000;
|
|
68
|
+
/**
|
|
69
|
+
* Settle grace (ms), carved OUT of `provisionTimeoutMs` — never added on top, so the budget
|
|
70
|
+
* ladder above is untouched. The listener aborts the provisioning hook when the work budget
|
|
71
|
+
* ({@link splitProvisionBudget}) expires, then waits up to this grace for the work to settle
|
|
72
|
+
* anyway: once the `FormationUsage` insert has been issued nothing can un-spend it (the table
|
|
73
|
+
* is append-only), so a provisioning that lands late is ADOPTED and reported as a real
|
|
74
|
+
* approval rather than lying "timed out" over a spent invite. A hook that observes the
|
|
75
|
+
* abort before writing leaves the invite unspent.
|
|
76
|
+
*/
|
|
77
|
+
const PROVISION_SETTLE_GRACE_MS = 2000;
|
|
78
|
+
/**
|
|
79
|
+
* Wire-latency margin (ms) added to the responder's provisioning budget to get the
|
|
80
|
+
* initiator's await-response budget — the travel time for the result frame to come back
|
|
81
|
+
* after the responder finishes (see {@link DEFAULT_PROVISION_TIMEOUT_MS}).
|
|
82
|
+
* `StrandFormationManager` reuses this constant so a CONFIGURED budget preserves the same
|
|
83
|
+
* margin the defaults do, instead of applying the same number to both sides and racing the
|
|
84
|
+
* initiator's own timeout against the responder's clean rejection reply. The responder's
|
|
85
|
+
* clamp ({@link provisionCeilingMs}) holds the same margin back, so the ordering survives a
|
|
86
|
+
* budget large enough that BOTH roles get clamped.
|
|
87
|
+
*
|
|
88
|
+
* NOTE: 3 s is a fixed assumption about how long the result frame takes to travel back. If
|
|
89
|
+
* formation ever runs over paths where that frame can take longer (a slow circuit relay, a
|
|
90
|
+
* congested mobile link), the margin is too thin and the initiator's timeout races the
|
|
91
|
+
* responder's reply again — raise it, or derive it from an observed round-trip.
|
|
92
|
+
*/
|
|
93
|
+
export const PROVISION_RESPONSE_TRAVEL_MARGIN_MS = 3000;
|
|
94
|
+
/** Default initiator await-response budget (ms); see {@link DEFAULT_PROVISION_TIMEOUT_MS}. */
|
|
95
|
+
const DEFAULT_INITIATOR_PROVISION_TIMEOUT_MS = DEFAULT_PROVISION_TIMEOUT_MS + PROVISION_RESPONSE_TRAVEL_MARGIN_MS;
|
|
96
|
+
/**
|
|
97
|
+
* Default cap on concurrent inbound formation sessions.
|
|
98
|
+
* NOTE: a longer provisioning budget holds a session's slot longer, so a slow hook can
|
|
99
|
+
* exhaust this cap and make the listener reject fresh joiners with 'Too many concurrent
|
|
100
|
+
* formation sessions'. Fine at the current default; revisit if `provisionTimeoutMs` is
|
|
101
|
+
* raised well above its default or this cap is lowered.
|
|
102
|
+
*/
|
|
33
103
|
const DEFAULT_MAX_CONCURRENT_SESSIONS = 100;
|
|
34
104
|
// ── Stream framing helpers ───────────────────────────────────────────────────
|
|
35
105
|
/**
|
|
@@ -114,6 +184,49 @@ export function isValidResponderCreatesResult(response) {
|
|
|
114
184
|
return false;
|
|
115
185
|
return true;
|
|
116
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Ceiling for a resolved provisioning budget.
|
|
189
|
+
*
|
|
190
|
+
* The session budget also has to cover the wire step that PRECEDES provisioning (the
|
|
191
|
+
* responder's contact read, the initiator's dial-connect), so a whole step is held back
|
|
192
|
+
* rather than triggering only on a literal overrun.
|
|
193
|
+
*
|
|
194
|
+
* `reserveMs` is the EXTRA room only the responder holds back, so its own budget still
|
|
195
|
+
* lands strictly before the initiator's larger await-response budget even when both are
|
|
196
|
+
* clamped — without it, any configured budget at or above `sessionTimeoutMs -
|
|
197
|
+
* stepTimeoutMs` clamps both roles onto the same number and the responder's clean
|
|
198
|
+
* rejection races the initiator's timeout again. Capped at half the remaining room (like
|
|
199
|
+
* {@link splitProvisionBudget}) so a small session config still spends most of it working.
|
|
200
|
+
*/
|
|
201
|
+
function provisionCeilingMs(sessionTimeoutMs, stepTimeoutMs, reserveMs) {
|
|
202
|
+
const roomMs = sessionTimeoutMs - stepTimeoutMs;
|
|
203
|
+
return Math.max(1, roomMs - Math.min(reserveMs, Math.floor(roomMs / 2)));
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Resolve a caller-supplied provisioning budget: `0`/negative means "unset" (use
|
|
207
|
+
* `defaultMs`). If the result would let provisioning outlive the session — no result
|
|
208
|
+
* frame is ever sent, exactly the failure this budget exists to prevent — clamp it to
|
|
209
|
+
* {@link provisionCeilingMs} and log a warning.
|
|
210
|
+
*/
|
|
211
|
+
function resolveProvisionTimeoutMs(configured, defaultMs, sessionTimeoutMs, stepTimeoutMs, role, reserveMs = 0) {
|
|
212
|
+
const requested = configured && configured > 0 ? configured : defaultMs;
|
|
213
|
+
const ceilingMs = provisionCeilingMs(sessionTimeoutMs, stepTimeoutMs, reserveMs);
|
|
214
|
+
if (requested >= ceilingMs) {
|
|
215
|
+
log('%s provisionTimeoutMs %dms leaves no room under sessionTimeoutMs %dms (step %dms, reserve %dms); clamping to %dms', role, requested, sessionTimeoutMs, stepTimeoutMs, reserveMs, ceilingMs);
|
|
216
|
+
return ceilingMs;
|
|
217
|
+
}
|
|
218
|
+
return requested;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Split a resolved provisioning budget into the WORK budget and the trailing settle grace.
|
|
222
|
+
*
|
|
223
|
+
* The grace is carved OUT of the budget (see {@link PROVISION_SETTLE_GRACE_MS}), and capped at
|
|
224
|
+
* half of it so a small configured budget still spends at least half its time doing work.
|
|
225
|
+
*/
|
|
226
|
+
function splitProvisionBudget(provisionTimeoutMs) {
|
|
227
|
+
const graceMs = Math.min(PROVISION_SETTLE_GRACE_MS, Math.floor(provisionTimeoutMs / 2));
|
|
228
|
+
return { workMs: provisionTimeoutMs - graceMs, graceMs };
|
|
229
|
+
}
|
|
117
230
|
/**
|
|
118
231
|
* Responder side of the native formation protocol. Registers a libp2p handler and
|
|
119
232
|
* drives each inbound stream through token + disclosure validation, provisioning,
|
|
@@ -128,6 +241,9 @@ export class FormationListener {
|
|
|
128
241
|
this.options = options;
|
|
129
242
|
this.sessionTimeoutMs = options.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS;
|
|
130
243
|
this.stepTimeoutMs = options.stepTimeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;
|
|
244
|
+
const split = splitProvisionBudget(resolveProvisionTimeoutMs(options.provisionTimeoutMs, DEFAULT_PROVISION_TIMEOUT_MS, this.sessionTimeoutMs, this.stepTimeoutMs, 'FormationListener', PROVISION_RESPONSE_TRAVEL_MARGIN_MS));
|
|
245
|
+
this.provisionWorkMs = split.workMs;
|
|
246
|
+
this.provisionGraceMs = split.graceMs;
|
|
131
247
|
this.maxConcurrentSessions = options.maxConcurrentSessions ?? DEFAULT_MAX_CONCURRENT_SESSIONS;
|
|
132
248
|
}
|
|
133
249
|
/** Number of in-flight inbound sessions. */
|
|
@@ -181,6 +297,107 @@ export class FormationListener {
|
|
|
181
297
|
catch { /* ignore */ }
|
|
182
298
|
}
|
|
183
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Run the provisioning hook under its WORK budget — the configured provisioning budget minus
|
|
302
|
+
* the trailing settle grace ({@link splitProvisionBudget}, {@link PROVISION_SETTLE_GRACE_MS}).
|
|
303
|
+
*
|
|
304
|
+
* When the work budget expires the hook's signal is aborted, then
|
|
305
|
+
* {@link settleWithinGrace} waits out the grace for the aborted work to settle anyway.
|
|
306
|
+
* Returns `undefined` for "timed out" — which the caller turns into a retryable rejection
|
|
307
|
+
* frame — and rethrows every other failure so it reaches the internal-error path.
|
|
308
|
+
*
|
|
309
|
+
* Deliberately not `withDeadline`: that exposes neither the timed-out flag nor the signal
|
|
310
|
+
* outside its `op`, and both are needed here.
|
|
311
|
+
*/
|
|
312
|
+
async provision(id, contact) {
|
|
313
|
+
const controller = new AbortController();
|
|
314
|
+
let timedOut = false;
|
|
315
|
+
const pending = this.options.provisionStrand(contact, controller.signal);
|
|
316
|
+
try {
|
|
317
|
+
return await withTimeout(this.provisionWorkMs, `Formation provisioning#${id}`, () => pending, () => { timedOut = true; controller.abort(); });
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
if (!timedOut)
|
|
321
|
+
throw err;
|
|
322
|
+
log('formation session #%d provisioning work budget expired after %dms; aborted, settling up to %dms', id, this.provisionWorkMs, this.provisionGraceMs);
|
|
323
|
+
return await this.settleWithinGrace(id, pending);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Wait out the settle grace for an ABORTED provisioning, adopting a late success.
|
|
328
|
+
*
|
|
329
|
+
* A hook that observed the abort before issuing its `FormationUsage` insert rejects (with
|
|
330
|
+
* `FormationAbortedError`) and leaves the invite unspent → reported as a timeout. A hook
|
|
331
|
+
* that had already written cannot be un-written (the table is append-only), so if it lands
|
|
332
|
+
* inside the grace its outcome is ADOPTED — the joiner is told the truth (approved, or the
|
|
333
|
+
* hook's own rejection reason) rather than "timed out" over a spent invite.
|
|
334
|
+
*
|
|
335
|
+
* NOTE: one window stays open — a work budget that expires after the `FormationUsage`
|
|
336
|
+
* insert was issued AND a commit that outlasts the grace. The joiner is told 'timed out'
|
|
337
|
+
* while its one-time invite is in fact spent, and since every retry mints a fresh keypair
|
|
338
|
+
* no recovery path can match it. Nothing can un-spend an append-only row, so the late-settle
|
|
339
|
+
* logging below is the observability for it; widen the grace only if it is seen in the wild.
|
|
340
|
+
*/
|
|
341
|
+
async settleWithinGrace(id, pending) {
|
|
342
|
+
let stillPending = false;
|
|
343
|
+
try {
|
|
344
|
+
const outcome = await withTimeout(this.provisionGraceMs, `Formation settle#${id}`, () => pending, () => { stillPending = true; });
|
|
345
|
+
log('formation session #%d provisioning settled within its grace: approved=%s — adopting', id, outcome.approved);
|
|
346
|
+
return outcome;
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
if (!stillPending) {
|
|
350
|
+
log('formation session #%d provisioning failed after its abort: %o', id, err);
|
|
351
|
+
return undefined;
|
|
352
|
+
}
|
|
353
|
+
log('formation session #%d provisioning still pending after its %dms grace', id, this.provisionGraceMs);
|
|
354
|
+
// Log how it eventually settled so a late failure is not swallowed by the two
|
|
355
|
+
// abandoned `withTimeout` calls.
|
|
356
|
+
void pending.then((late) => log('formation session #%d provisioning settled after its grace: approved=%s', id, late.approved), (err2) => log('formation session #%d provisioning failed after its grace: %o', id, err2));
|
|
357
|
+
return undefined;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Joiner-consent pre-check — the legibility twin of the schema's
|
|
362
|
+
* `FormationUsage.PeerConsented` CHECK, exactly as `verifyFormationApproval` is for the
|
|
363
|
+
* approver's vouch. The database constraint stays the authority; this turns a bad consent
|
|
364
|
+
* into a clean 'Invalid joiner consent' rejection instead of an opaque CHECK failure at
|
|
365
|
+
* commit. Runs BEFORE token/disclosure validation: it is the cheapest check (pure local
|
|
366
|
+
* crypto, no DB read) and a rejection discloses nothing.
|
|
367
|
+
*
|
|
368
|
+
* Also pins `partyId` to `peerKey`: an ed25519 peer id is an identity multihash of the
|
|
369
|
+
* very key, and this is the ONLY layer that can check the match — SQL cannot unwrap a
|
|
370
|
+
* multihash, and `partyId` itself is never stored.
|
|
371
|
+
*/
|
|
372
|
+
isJoinerConsentValid(id, contact) {
|
|
373
|
+
try {
|
|
374
|
+
requireEd25519PublicKeyB64(contact.peerKey, 'joiner peer key');
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
// Deliberately not rethrown or echoed: the helper's error message embeds the whole
|
|
378
|
+
// rejected value, and this one arrived from a remote peer (the cap-the-echo case its
|
|
379
|
+
// own NOTE warns about). Log without the raw value instead.
|
|
380
|
+
log('formation session #%d: joiner peer key is not a base64url ed25519 public key', id);
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
const embedded = ed25519PublicKeyB64FromPeerId(contact.partyId);
|
|
384
|
+
if (!embedded || embedded !== contact.peerKey) {
|
|
385
|
+
log('formation session #%d: partyId does not embed the presented peer key', id);
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
const consentOk = verifyFormationConsent({
|
|
389
|
+
token: contact.token,
|
|
390
|
+
usageStampId: contact.usageStampId,
|
|
391
|
+
peerKey: contact.peerKey,
|
|
392
|
+
disclosure: canonicalJson(contact.disclosure),
|
|
393
|
+
peerSig: contact.peerSignature
|
|
394
|
+
});
|
|
395
|
+
if (!consentOk) {
|
|
396
|
+
log('formation session #%d: joiner consent signature failed verification', id);
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
184
401
|
async runSession(id, stream) {
|
|
185
402
|
// Track whether ANY frame has been written so the catch below can convert an
|
|
186
403
|
// unexpected internal error into a non-disclosing rejection ONLY when nothing has
|
|
@@ -194,9 +411,13 @@ export class FormationListener {
|
|
|
194
411
|
const reader = new FrameReader(stream);
|
|
195
412
|
const contact = await withTimeout(this.stepTimeoutMs, `Formation await-contact#${id}`, () => reader.read());
|
|
196
413
|
log('formation session #%d contact: token=%s party=%s', id, contact.token, contact.partyId);
|
|
414
|
+
if (!this.isJoinerConsentValid(id, contact)) {
|
|
415
|
+
send({ approved: false, reason: 'Invalid joiner consent' });
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
197
418
|
const tokenResult = await this.options.validateToken(contact.token);
|
|
198
419
|
if (!tokenResult.valid) {
|
|
199
|
-
send({ approved: false, reason:
|
|
420
|
+
send({ approved: false, reason: INVALID_TOKEN_REASON });
|
|
200
421
|
return;
|
|
201
422
|
}
|
|
202
423
|
const disclosureOk = await this.options.validateDisclosure(contact.token, contact.disclosure);
|
|
@@ -204,7 +425,13 @@ export class FormationListener {
|
|
|
204
425
|
send({ approved: false, reason: 'Invalid disclosure' });
|
|
205
426
|
return;
|
|
206
427
|
}
|
|
207
|
-
const outcome = await this.
|
|
428
|
+
const outcome = await this.provision(id, contact);
|
|
429
|
+
if (!outcome) {
|
|
430
|
+
// Reported as its own retryable reason rather than falling through to the generic
|
|
431
|
+
// catch below, which would report the misleading 'Internal formation error'.
|
|
432
|
+
send({ approved: false, reason: 'Formation provisioning timed out' });
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
208
435
|
if (!outcome.approved) {
|
|
209
436
|
// A post-validation rejection still discloses NEITHER identity NOR cadre,
|
|
210
437
|
// exactly like the token/disclosure rejections above.
|
|
@@ -250,6 +477,7 @@ export async function dialFormation(node, options) {
|
|
|
250
477
|
const protocolId = options.protocolId ?? FORMATION_PROTOCOL;
|
|
251
478
|
const sessionTimeoutMs = options.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS;
|
|
252
479
|
const stepTimeoutMs = options.stepTimeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;
|
|
480
|
+
const provisionTimeoutMs = resolveProvisionTimeoutMs(options.provisionTimeoutMs, DEFAULT_INITIATOR_PROVISION_TIMEOUT_MS, sessionTimeoutMs, stepTimeoutMs, 'dialFormation');
|
|
253
481
|
const addr = multiaddr(options.responderAddrs[0]);
|
|
254
482
|
return withTimeout(sessionTimeoutMs, 'Formation dial', async () => {
|
|
255
483
|
const rawStream = await withTimeout(stepTimeoutMs, 'Formation dial-connect', async () => node.dialProtocol(addr, protocolId));
|
|
@@ -257,7 +485,7 @@ export async function dialFormation(node, options) {
|
|
|
257
485
|
try {
|
|
258
486
|
const reader = new FrameReader(stream);
|
|
259
487
|
writeFrame(stream, options.contact);
|
|
260
|
-
const response = await withTimeout(
|
|
488
|
+
const response = await withTimeout(provisionTimeoutMs, 'Formation await-response', () => reader.read());
|
|
261
489
|
if (!response.approved) {
|
|
262
490
|
throw new Error(`Formation rejected: ${response.reason ?? 'no reason provided'}`);
|
|
263
491
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strand-formation-protocol.js","sourceRoot":"","sources":["../src/strand-formation-protocol.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"strand-formation-protocol.js","sourceRoot":"","sources":["../src/strand-formation-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAsB,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,oFAAoF;AACpF,sCAAsC;AACtC,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AAEpE,MAAM,GAAG,GAAG,KAAK,CAAC,8BAA8B,CAAC,CAAC;AAElD,yFAAyF;AACzF,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,4CAA4C;AAC5C,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,0BAA0B,GAAG,KAAM,CAAC;AAC1C,yDAAyD;AACzD,MAAM,uBAAuB,GAAG,IAAK,CAAC;AACtC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,4BAA4B,GAAG,KAAM,CAAC;AAC5C;;;;;;;;GAQG;AACH,MAAM,yBAAyB,GAAG,IAAK,CAAC;AACxC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,IAAK,CAAC;AACzD,8FAA8F;AAC9F,MAAM,sCAAsC,GAAG,4BAA4B,GAAG,mCAAmC,CAAC;AAClH;;;;;;GAMG;AACH,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAiF5C,gFAAgF;AAEhF;;;;;;;GAOG;AACH,MAAM,WAAW;IAKf,YAAY,MAAiC,EAAE,SAAS,GAAG,sBAAsB;QAFzE,WAAM,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;QAGjC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAEO,MAAM,CAAC,KAAiB;QAC9B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,0FAA0F;IAClF,KAAK,CAAC,IAAI,CAAC,IAAY;QAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YACjC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnD,IAAI,IAAI;gBAAE,OAAO,KAAK,CAAC;YACvB,MAAM,KAAK,GAAG,KAAK,YAAY,UAAU;gBACvC,CAAC,CAAC,KAAK;gBACP,CAAC,CAAE,KAAoC,CAAC,QAAQ,EAAE,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACpH,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,kBAAkB,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,yBAAyB,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;CACF;AAED,gFAAgF;AAEhF,0FAA0F;AAC1F,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,6BAA6B,CAAC,QAAgC;IAC5E,IAAI,CAAC,QAAQ,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC;IACtC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,MAAM,SAAS,GAAG,QAAQ,CAAC,eAAe,CAAC;IAC3C,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,SAAS,CAAC,MAAM,CAAC,SAAS,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,kBAAkB,CAAC,gBAAwB,EAAE,aAAqB,EAAE,SAAiB;IAC5F,MAAM,MAAM,GAAG,gBAAgB,GAAG,aAAa,CAAC;IAChD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,SAAS,yBAAyB,CAChC,UAA8B,EAC9B,SAAiB,EACjB,gBAAwB,EACxB,aAAqB,EACrB,IAAY,EACZ,SAAS,GAAG,CAAC;IAEb,MAAM,SAAS,GAAG,UAAU,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,gBAAgB,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;IACjF,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,GAAG,CACD,mHAAmH,EACnH,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,CACvE,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,kBAA0B;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,KAAK,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC;IACxF,OAAO,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC;AAuCD;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IAW5B,YAAY,OAAiC;QAJ5B,eAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,mBAAc,GAAG,CAAC,CAAC;QACnB,mBAAc,GAAG,CAAC,CAAC;QAGzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;QAC/E,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;QACtE,MAAM,KAAK,GAAG,oBAAoB,CAAC,yBAAyB,CAC1D,OAAO,CAAC,kBAAkB,EAAE,4BAA4B,EACxD,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,aAAa,EAAE,mBAAmB,EAC9D,mCAAmC,CACpC,CAAC,CAAC;QACH,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC;QACtC,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,IAAI,+BAA+B,CAAC;IAChG,CAAC;IAED,4CAA4C;IAC5C,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,aAAqB,kBAAkB;QAC5D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,yBAAyB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,KAAK,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,SAAkB,EAAE,WAAoB,EAAE,EAAE;YAC9E,MAAM,IAAI,CAAC,YAAY,CAAC,SAA0B,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,GAAG,CAAC,oCAAoC,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,UAAU,CAAC,IAAY,EAAE,aAAqB,kBAAkB;QAC9D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QACvC,KAAK,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,GAAG,CAAC,sCAAsC,EAAE,UAAU,CAAC,CAAC;IAC1D,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,MAAqB;QAC9C,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACtD,MAAM,SAAS,GAA2B,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;YAChH,IAAI,CAAC;gBAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;YAClE,IAAI,CAAC;gBAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC;QACjC,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,IAAI,CAAC,gBAAgB,EAAE,qBAAqB,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACzG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,kCAAkC,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC;gBAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACK,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,OAAgC;QAClE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QACzE,IAAI,CAAC;YACH,OAAO,MAAM,WAAW,CACtB,IAAI,CAAC,eAAe,EACpB,0BAA0B,EAAE,EAAE,EAC9B,GAAG,EAAE,CAAC,OAAO,EACb,GAAG,EAAE,GAAG,QAAQ,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAC/C,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ;gBAAE,MAAM,GAAG,CAAC;YACzB,GAAG,CACD,iGAAiG,EACjG,EAAE,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,gBAAgB,CAChD,CAAC;YACF,OAAO,MAAM,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACK,KAAK,CAAC,iBAAiB,CAC7B,EAAU,EACV,OAA2C;QAE3C,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAC/B,IAAI,CAAC,gBAAgB,EACrB,oBAAoB,EAAE,EAAE,EACxB,GAAG,EAAE,CAAC,OAAO,EACb,GAAG,EAAE,GAAG,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,CAC/B,CAAC;YACF,GAAG,CAAC,qFAAqF,EAAE,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjH,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,GAAG,CAAC,+DAA+D,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;gBAC9E,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,GAAG,CAAC,uEAAuE,EAAE,EAAE,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACxG,8EAA8E;YAC9E,iCAAiC;YACjC,KAAK,OAAO,CAAC,IAAI,CACf,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,yEAAyE,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,EAC3G,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,+DAA+D,EAAE,EAAE,EAAE,IAAI,CAAC,CACzF,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACK,oBAAoB,CAAC,EAAU,EAAE,OAAgC;QACvE,IAAI,CAAC;YACH,0BAA0B,CAAC,OAAO,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,mFAAmF;YACnF,qFAAqF;YACrF,4DAA4D;YAC5D,GAAG,CAAC,8EAA8E,EAAE,EAAE,CAAC,CAAC;YACxF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,QAAQ,GAAG,6BAA6B,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,GAAG,CAAC,sEAAsE,EAAE,EAAE,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,SAAS,GAAG,sBAAsB,CAAC;YACvC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC;YAC7C,OAAO,EAAE,OAAO,CAAC,aAAa;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,qEAAqE,EAAE,EAAE,CAAC,CAAC;YAC/E,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,MAAqB;QACxD,6EAA6E;QAC7E,kFAAkF;QAClF,mFAAmF;QACnF,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,GAA2B,EAAQ,EAAE;YACjD,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACxB,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,2BAA2B,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAA2B,CAAC,CAAC;YACrI,GAAG,CAAC,kDAAkD,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAE5F,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;gBACvB,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;gBACxD,OAAO;YACT,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YAC9F,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;gBACxD,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,kFAAkF;gBAClF,6EAA6E;gBAC7E,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC,CAAC;gBACtE,OAAO;YACT,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACtB,0EAA0E;gBAC1E,sDAAsD;gBACtD,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YACD,gFAAgF;YAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;YACrD,IAAI,CAAC;gBACH,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,cAAc,EAAE,QAAQ,CAAC,cAAc;gBACvC,eAAe,EAAE,OAAO,CAAC,MAAM;aAChC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iFAAiF;YACjF,qFAAqF;YACrF,kFAAkF;YAClF,oFAAoF;YACpF,gFAAgF;YAChF,6CAA6C;YAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,aAAa,GAA2B,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC;gBACtG,IAAI,CAAC;oBAAC,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;YAClF,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAsBD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,OAA6B;IAC7E,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,CAAC;IAC5D,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;IAChF,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACvE,MAAM,kBAAkB,GAAG,yBAAyB,CAClD,OAAO,CAAC,kBAAkB,EAAE,sCAAsC,EAClE,gBAAgB,EAAE,aAAa,EAAE,eAAe,CACjD,CAAC;IACF,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAElD,OAAO,WAAW,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,aAAa,EAAE,wBAAwB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC9H,MAAM,MAAM,GAAG,SAAqC,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;YACvC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAEpC,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,kBAAkB,EAAE,0BAA0B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAA0B,CAAC,CAAC;YAChI,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,IAAI,oBAAoB,EAAE,CAAC,CAAC;YACpF,CAAC;YACD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YACpD,IAAI,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YAE/D,IAAI,CAAC,QAAQ,CAAC,eAAe;gBAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACrG,OAAO,QAAQ,CAAC,eAAe,CAAC;QAClC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC;gBAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PrivateKey } from '@libp2p/interface';
|
|
2
|
-
import
|
|
2
|
+
import { type StrandBackfillConfig } from './strand-backfill.js';
|
|
3
|
+
import type { StrandInstance, StrandRow, StorageConfig, NetworkConfig, LatencyHint, NodeProfile, SAppConfig } from './types.js';
|
|
3
4
|
/**
|
|
4
5
|
* Configuration for starting a strand instance
|
|
5
6
|
*/
|
|
@@ -14,12 +15,6 @@ export interface StartStrandConfig {
|
|
|
14
15
|
privateKey?: PrivateKey;
|
|
15
16
|
/** Cohort-derived discovery seed (multiaddr strings). Defaults to [] when omitted. */
|
|
16
17
|
bootstrapNodes?: string[];
|
|
17
|
-
/**
|
|
18
|
-
* Lifecycle mode for this strand; selects the default transactor used by the
|
|
19
|
-
* StrandDatabase. When omitted, the StrandDatabase falls back to `'networked'`;
|
|
20
|
-
* callers (CadreNode) infer it from cohort membership before reaching here.
|
|
21
|
-
*/
|
|
22
|
-
mode?: StrandMode;
|
|
23
18
|
/**
|
|
24
19
|
* Require a valid author signature on the sApp schema before bring-up.
|
|
25
20
|
* Defaults to true (fail closed) when omitted; set false only for dev/test
|
|
@@ -33,17 +28,34 @@ export interface StartStrandConfig {
|
|
|
33
28
|
* {@link StrandConfig.founder}.
|
|
34
29
|
*/
|
|
35
30
|
founder?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Number of nodes Optimystic is told this strand's replication cluster should
|
|
33
|
+
* have. Same rule as {@link CadreNodeConfig.strandClusterSize}, which CadreNode
|
|
34
|
+
* forwards here: every node on the strand should use the same value, and it is
|
|
35
|
+
* frozen when the strand's libp2p node is created. Defaults to
|
|
36
|
+
* `DEFAULT_STRAND_CLUSTER_SIZE` (4); values below `MIN_CLUSTER_SIZE` (2) are
|
|
37
|
+
* rejected by `resolveStrandClusterSize`. Strand-only — the
|
|
38
|
+
* control network's breadth is the fixed `CONTROL_REPLICATION_BREADTH`.
|
|
39
|
+
*/
|
|
40
|
+
clusterSize?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Tuning for the strand peer-join block catch-up ({@link StrandBackfill}),
|
|
43
|
+
* forwarded from {@link CadreNodeConfig.strandBackfill}. When the strand's
|
|
44
|
+
* libp2p node connects to a peer this runtime has not yet caught up, every
|
|
45
|
+
* block in the strand's own raw store is pushed to it. Runs only on strands
|
|
46
|
+
* with per-strand storage; `{ enabled: false }` restores the pre-existing
|
|
47
|
+
* no-backfill behaviour.
|
|
48
|
+
*/
|
|
49
|
+
backfill?: StrandBackfillConfig;
|
|
36
50
|
}
|
|
37
51
|
/**
|
|
38
|
-
* Volatile inputs re-resolved when resuming a quiesced strand.
|
|
39
|
-
*
|
|
40
|
-
*
|
|
52
|
+
* Volatile inputs re-resolved when resuming a quiesced strand. The cohort
|
|
53
|
+
* discovery seed is the only one — it grows as peers are learned since the
|
|
54
|
+
* strand first launched.
|
|
41
55
|
*/
|
|
42
56
|
export interface ResumeStrandOverrides {
|
|
43
57
|
/** Freshly-resolved cohort discovery seed (multiaddr strings). */
|
|
44
58
|
bootstrapNodes?: string[];
|
|
45
|
-
/** Freshly-resolved lifecycle mode. */
|
|
46
|
-
mode?: StrandMode;
|
|
47
59
|
}
|
|
48
60
|
/**
|
|
49
61
|
* Get the isolated storage path for a specific strand.
|
|
@@ -72,6 +84,35 @@ export declare class StrandInstanceManager {
|
|
|
72
84
|
* without the caller re-threading storage/network/profile/key/sApp config.
|
|
73
85
|
*/
|
|
74
86
|
private launchConfigs;
|
|
87
|
+
/**
|
|
88
|
+
* The per-strand peer-join block catch-up, keyed by strand id. Private (not on
|
|
89
|
+
* the public {@link StrandInstance}) because it is runtime plumbing with the
|
|
90
|
+
* same lifetime as the strand's libp2p node: created in `buildStrandRuntime`,
|
|
91
|
+
* stopped and dropped in `releaseRuntime` — so quiesce → resume rebuilds it
|
|
92
|
+
* with a fresh caught-up-peer memo, which is intended (a resumed node may have
|
|
93
|
+
* missed writes).
|
|
94
|
+
*/
|
|
95
|
+
private backfills;
|
|
96
|
+
/**
|
|
97
|
+
* The resolved (cache-wrapped) raw storage per strand id — the instance's OWN
|
|
98
|
+
* store, resolved once in `startStrand` and held until `stopStrand` disposes it.
|
|
99
|
+
* Private for the same reason `backfills` is: runtime plumbing, not part of the
|
|
100
|
+
* public {@link StrandInstance}.
|
|
101
|
+
*
|
|
102
|
+
* Deliberately NOT touched by `releaseRuntime`: that is what lets a quiesce →
|
|
103
|
+
* resume cycle rebuild the libp2p node over the SAME store, keeping its
|
|
104
|
+
* write-through cache warm (and, on an in-memory backend, keeping the strand's
|
|
105
|
+
* blocks at all). An entry exists iff `instances` does AND the launch config
|
|
106
|
+
* supplied a storage provider.
|
|
107
|
+
*
|
|
108
|
+
* NOTE: a hibernating strand therefore keeps its store — and its share of the
|
|
109
|
+
* process-wide cache pool — resident for as long as the instance is tracked. That
|
|
110
|
+
* is the point (a warm wake), and the pool evicts under pressure, so the cost is
|
|
111
|
+
* one map entry per hibernating strand today. If a device ever hibernates strands
|
|
112
|
+
* by the hundred, revisit: dropping the store at quiesce and paying for a cold
|
|
113
|
+
* wake becomes the better trade.
|
|
114
|
+
*/
|
|
115
|
+
private strandStorages;
|
|
75
116
|
private stopping;
|
|
76
117
|
constructor();
|
|
77
118
|
/**
|
|
@@ -87,16 +128,30 @@ export declare class StrandInstanceManager {
|
|
|
87
128
|
*/
|
|
88
129
|
hasStrand(strandId: string): boolean;
|
|
89
130
|
/**
|
|
90
|
-
* Start a new strand instance
|
|
131
|
+
* Start a new strand instance.
|
|
132
|
+
*
|
|
133
|
+
* A failed launch leaves NOTHING tracked: the instance and its retained launch
|
|
134
|
+
* config are both dropped before the error is rethrown, so the strand id is
|
|
135
|
+
* free for a genuine retry. This matches the pre-registration failure path
|
|
136
|
+
* (a rejected schema signature, which throws before anything is recorded) —
|
|
137
|
+
* both failure modes of this call leave the same residue: none. Callers learn
|
|
138
|
+
* of the failure from the rejected promise (and, on the control-discovered
|
|
139
|
+
* path, from CadreNode's `strand:error` event), not from an error record left
|
|
140
|
+
* behind in `instances`.
|
|
141
|
+
*
|
|
142
|
+
* The strand's raw storage is resolved HERE, once, and held for the instance's
|
|
143
|
+
* lifetime (see `strandStorages`) — `buildStrandRuntime` only reads it, so a
|
|
144
|
+
* hibernation wake never re-enters the embedder's provider.
|
|
91
145
|
*/
|
|
92
146
|
startStrand(config: StartStrandConfig): Promise<StrandInstance>;
|
|
93
147
|
/**
|
|
94
148
|
* Build (or rebuild) the libp2p node + StrandDatabase for an instance and
|
|
95
149
|
* attach them, transitioning it to `active`. Shared by `startStrand` (fresh
|
|
96
150
|
* launch) and `resumeStrand` (rehydrating a quiesced instance). Reads all
|
|
97
|
-
* volatile inputs (bootstrapNodes,
|
|
98
|
-
*
|
|
99
|
-
*
|
|
151
|
+
* volatile inputs (bootstrapNodes, network, profile, privateKey, sApp config)
|
|
152
|
+
* from `config`, so the caller controls the cohort-derived values. Storage is the
|
|
153
|
+
* one input it does NOT re-read from `config`: that belongs to the instance and
|
|
154
|
+
* comes from `strandStorages`.
|
|
100
155
|
*/
|
|
101
156
|
private buildStrandRuntime;
|
|
102
157
|
/**
|
|
@@ -105,8 +160,22 @@ export declare class StrandInstanceManager {
|
|
|
105
160
|
* and zeroing connectedPeers. Tolerant of partially-built state — either handle
|
|
106
161
|
* may be absent — so it doubles as rollback for a failed `buildStrandRuntime`.
|
|
107
162
|
* Shared by `quiesceStrand`, `stopStrand`, and that rollback path.
|
|
163
|
+
*
|
|
164
|
+
* Leaves `strandStorages` untouched by design — the store outlives the runtime it
|
|
165
|
+
* was built into, which is what makes a resume warm. Only `stopStrand` disposes it.
|
|
108
166
|
*/
|
|
109
167
|
private releaseRuntime;
|
|
168
|
+
/**
|
|
169
|
+
* Drop the strand's owned store and release its cache registration with the shared
|
|
170
|
+
* pool. Called only where the strand's whole lifetime ends (`stopStrand`, and the
|
|
171
|
+
* failed-launch rollback) — never on a quiesce.
|
|
172
|
+
*
|
|
173
|
+
* A dispose failure is logged, not thrown: the store is already unreferenced here,
|
|
174
|
+
* and failing the stop over a cache-bookkeeping error would leave the caller unable
|
|
175
|
+
* to tear the strand down. `disposeStorageCache` no-ops for an unwrapped store
|
|
176
|
+
* (e.g. `MemoryRawStorage`), so no instanceof test is needed.
|
|
177
|
+
*/
|
|
178
|
+
private disposeStrandStorage;
|
|
110
179
|
/**
|
|
111
180
|
* Quiesce a strand: release its strand-network resources (stop the libp2p node,
|
|
112
181
|
* close the StrandDatabase) while RETAINING the instance record — identity,
|
|
@@ -120,9 +189,9 @@ export declare class StrandInstanceManager {
|
|
|
120
189
|
* Resume a previously-quiesced strand: rebuild its libp2p node + StrandDatabase
|
|
121
190
|
* from the retained launch config and re-attach them, transitioning it back to
|
|
122
191
|
* `active`. `overrides` re-applies volatile inputs that may have changed since
|
|
123
|
-
* launch (cohort `bootstrapNodes
|
|
124
|
-
*
|
|
125
|
-
*
|
|
192
|
+
* launch (the cohort `bootstrapNodes` seed) and updates the retained config so
|
|
193
|
+
* a later resume reuses the latest values. Returns the live instance unchanged
|
|
194
|
+
* if it is already running.
|
|
126
195
|
*/
|
|
127
196
|
resumeStrand(strandId: string, overrides?: ResumeStrandOverrides): Promise<StrandInstance>;
|
|
128
197
|
/**
|