@serfab/cadre-core 1.9.0 → 1.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/dist/cadre-node.d.ts +148 -44
- package/dist/cadre-node.js +363 -139
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +2 -2
- package/dist/control-authorization.js +1 -0
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.d.ts +1 -1
- package/dist/control-cohort.js +1 -1
- package/dist/control-database.d.ts +105 -14
- package/dist/control-database.js +242 -73
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +6 -6
- package/dist/control-formation-recorder.js +7 -8
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +1066 -979
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +21 -15
- package/dist/control-write-retry.js +21 -15
- package/dist/control-write-retry.js.map +1 -1
- package/dist/diagnostics/connection-path.d.ts +1 -18
- package/dist/diagnostics/connection-path.js +1 -20
- package/dist/diagnostics/connection-path.js.map +1 -1
- package/dist/identity-key.d.ts +0 -30
- package/dist/identity-key.js +7 -40
- package/dist/identity-key.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +12 -6
- package/dist/index.js.map +1 -1
- package/dist/invitation-bootstrap.d.ts +32 -0
- package/dist/invitation-bootstrap.js +30 -0
- package/dist/invitation-bootstrap.js.map +1 -0
- package/dist/link-budget.d.ts +204 -119
- package/dist/link-budget.js +208 -120
- package/dist/link-budget.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +3 -3
- package/dist/membership-connection-gater.js +3 -3
- package/dist/peer-dial.d.ts +18 -14
- package/dist/peer-dial.js +18 -14
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +3 -3
- package/dist/pending-join-runner.d.ts +186 -0
- package/dist/pending-join-runner.js +649 -0
- package/dist/pending-join-runner.js.map +1 -0
- package/dist/push-fanout.d.ts +1 -1
- package/dist/push-fanout.js +1 -1
- package/dist/relay-stun.d.ts +24 -0
- package/dist/relay-stun.js +51 -0
- package/dist/relay-stun.js.map +1 -0
- package/dist/seed-bootstrap.d.ts +2 -2
- package/dist/seed-bootstrap.js +5 -5
- package/dist/strand-addr-protocol.js +2 -2
- package/dist/strand-formation-deadlines.d.ts +5 -5
- package/dist/strand-formation-deadlines.js +5 -5
- package/dist/strand-formation-manager.d.ts +18 -4
- package/dist/strand-formation-manager.js +48 -33
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +71 -14
- package/dist/strand-formation-protocol.js +222 -47
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-formation-rejection.d.ts +94 -0
- package/dist/strand-formation-rejection.js +77 -0
- package/dist/strand-formation-rejection.js.map +1 -0
- package/dist/strand-instance-manager.js +4 -1
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-membership-writer.js +32 -32
- package/dist/strand-solicitation.d.ts +11 -3
- package/dist/strand-solicitation.js +9 -0
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/types.d.ts +103 -17
- package/dist/types.js +5 -9
- package/dist/types.js.map +1 -1
- package/package.json +22 -22
- package/src/cadre-node.ts +8654 -8400
- package/src/control-authorization.ts +2 -1
- package/src/control-cohort.ts +128 -128
- package/src/control-database.ts +303 -82
- package/src/control-formation-recorder.ts +353 -354
- package/src/control-read-retry.ts +216 -216
- package/src/control-schema.ts +1078 -991
- package/src/control-write-retry.ts +567 -561
- package/src/diagnostics/connection-path.ts +1 -29
- package/src/formation-approval.ts +610 -610
- package/src/hibernation-manager.ts +638 -638
- package/src/identity-key.ts +7 -62
- package/src/index.ts +644 -627
- package/src/invitation-bootstrap.ts +40 -0
- package/src/joined-strand-store.ts +498 -498
- package/src/link-budget.ts +684 -583
- package/src/membership-connection-gater.ts +570 -570
- package/src/node-local-snapshot.ts +298 -298
- package/src/peer-dial.ts +315 -311
- package/src/peer-join-backfill.ts +710 -710
- package/src/pending-join-runner.ts +735 -0
- package/src/push-fanout.ts +1 -1
- package/src/relay-reservation.ts +1121 -1121
- package/src/relay-server.ts +98 -98
- package/src/relay-stun.ts +58 -0
- package/src/seed-bootstrap.ts +1448 -1448
- package/src/strand-addr-protocol.ts +547 -547
- package/src/strand-database.ts +287 -287
- package/src/strand-first-sync-gate.ts +391 -391
- package/src/strand-formation-deadlines.ts +227 -227
- package/src/strand-formation-manager.ts +725 -700
- package/src/strand-formation-protocol.ts +1036 -802
- package/src/strand-formation-rejection.ts +129 -0
- package/src/strand-fret-addrs.ts +145 -145
- package/src/strand-instance-manager.ts +1789 -1786
- package/src/strand-membership-writer.ts +1974 -1974
- package/src/strand-network-state-file.ts +40 -40
- package/src/strand-network-state.ts +243 -243
- package/src/strand-revocation-enforcer.ts +654 -654
- package/src/strand-solicitation.ts +532 -519
- package/src/strand-wake-protocol.ts +401 -401
- package/src/types.ts +2222 -2140
- package/dist/diagnostics/webrtc-turn-tracker.d.ts +0 -50
- package/dist/diagnostics/webrtc-turn-tracker.js +0 -196
- package/dist/diagnostics/webrtc-turn-tracker.js.map +0 -1
- package/src/diagnostics/webrtc-turn-tracker.ts +0 -222
package/dist/cadre-node.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Libp2p, PeerId } from '@libp2p/interface';
|
|
2
2
|
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
3
|
-
import type { CadreNodeConfig, StrandInstance, StrandRow, StrandConfig, FoundStrandConfig, FoundStrandResult, SAppConfig, CadreNodeEvents, ControlNetworkSeed, ApplySeedResult, AddDroneOptions, AddPhoneOptions, DroneInitResult, InviteResult, CadreInvite, OpenInvitation, FormStrandResult, StrandFormationDisclosure, StrandMembershipInvite, ResolveOpts, SelfRegistrationOutcome, ServiceWakeResult, PushPlatform, DeviceTokenRecord, ResolveDeviceTokenOpts } from './types.js';
|
|
3
|
+
import type { CadreNodeConfig, StrandInstance, StrandRow, StrandConfig, FoundStrandConfig, FoundStrandResult, SAppConfig, CadreNodeEvents, ControlNetworkSeed, ApplySeedResult, AddDroneOptions, AddPhoneOptions, DroneInitResult, InviteResult, CadreInvite, OpenInvitation, FormStrandResult, StrandFormationDisclosure, StrandMembershipInvite, ResolveOpts, SelfRegistrationOutcome, ServiceWakeResult, PushPlatform, DeviceTokenRecord, ResolveDeviceTokenOpts, PendingJoinStatus } from './types.js';
|
|
4
4
|
import { type Ed25519KeyPair } from './ed25519-key.js';
|
|
5
5
|
import { type TrustedOwnerStore, type TrustSource } from './trusted-owner-store.js';
|
|
6
6
|
import { type BootstrapPeerStore } from './bootstrap-peer-store.js';
|
|
@@ -84,6 +84,15 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
84
84
|
private enrollmentService;
|
|
85
85
|
private seedBootstrapService;
|
|
86
86
|
private strandSolicitationService;
|
|
87
|
+
/**
|
|
88
|
+
* The service whose formation handler is registered on the control node. Trails
|
|
89
|
+
* {@link strandSolicitationService} while {@link initializeStrandSolicitation} swaps a new
|
|
90
|
+
* one in: the field is set at once so concurrent callers reuse it, the handler only when
|
|
91
|
+
* its queued swap runs.
|
|
92
|
+
*/
|
|
93
|
+
private registeredSolicitation;
|
|
94
|
+
/** Tail of the queued formation-handler swaps ({@link swapFormationResponder}). */
|
|
95
|
+
private solicitationSwaps;
|
|
87
96
|
private strandWakeService;
|
|
88
97
|
/**
|
|
89
98
|
* Control-network strand-address responder. Answers a co-cadre sibling's
|
|
@@ -382,6 +391,20 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
382
391
|
* `unpublishStrand` / `forgetJoinedStrand` as {@link formationStrandAddrs} is.
|
|
383
392
|
*/
|
|
384
393
|
private readonly pendingMembershipInvites;
|
|
394
|
+
/**
|
|
395
|
+
* Invite keys of the membership invitations this process has staged, by
|
|
396
|
+
* {@link adoptFormationMembershipInvite} or from a `joined` `PendingJoin` row
|
|
397
|
+
* ({@link stageMembershipInvitesFromPendingJoins}), so one the reconciler has settled is not
|
|
398
|
+
* staged again by the next pending-join pass. Same lifetime as
|
|
399
|
+
* {@link pendingMembershipInvites}: a restarted process stages each live one once more, and the
|
|
400
|
+
* reconciler settles it again (spent, or the party already seated).
|
|
401
|
+
*/
|
|
402
|
+
private readonly stagedMembershipInviteKeys;
|
|
403
|
+
/**
|
|
404
|
+
* The pending-join retry loop (`pending-join-runner.ts`): built by {@link start}, stopped by
|
|
405
|
+
* {@link cleanup}. It acts only while this machine is an enrolled owner.
|
|
406
|
+
*/
|
|
407
|
+
private pendingJoinRunner;
|
|
385
408
|
/**
|
|
386
409
|
* Founder launches refused because the strand was founded before the per-party
|
|
387
410
|
* identity split (`PreSplitStrandIdentityError`), keyed by strandId. Read by
|
|
@@ -589,23 +612,6 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
589
612
|
private controlConnectionOpenHandler;
|
|
590
613
|
/** `connection:close` listener re-arming the growth edge (teardown in {@link stopRecordRefresh}). */
|
|
591
614
|
private controlConnectionCloseHandler;
|
|
592
|
-
/**
|
|
593
|
-
* Hooks `globalThis.RTCPeerConnection` to observe whether ICE selected a TURN
|
|
594
|
-
* relay candidate for each WebRTC session. Installed in {@link start}, disposed
|
|
595
|
-
* in {@link cleanup}; inert on Node.js (no `RTCPeerConnection`).
|
|
596
|
-
*/
|
|
597
|
-
private readonly turnTracker;
|
|
598
|
-
/**
|
|
599
|
-
* Peer IDs whose current WebRTC connection was observed to be TURN-relayed.
|
|
600
|
-
* Populated by {@link handleTurnConnectionOpen} (drains the tracker queue on a
|
|
601
|
-
* `/webrtc` `connection:open`), cleared per-peer on `connection:close`. Read by
|
|
602
|
-
* {@link getConnectionPaths} to promote `webrtc` → `webrtc-turn` (relayed).
|
|
603
|
-
*/
|
|
604
|
-
private turnRelayedPeers;
|
|
605
|
-
/** `connection:open` listener feeding TURN detection (teardown in {@link stopRecordRefresh}). */
|
|
606
|
-
private turnConnectionOpenHandler;
|
|
607
|
-
/** `connection:close` listener clearing a peer's TURN flag (teardown in {@link stopRecordRefresh}). */
|
|
608
|
-
private turnConnectionCloseHandler;
|
|
609
615
|
constructor(config: CadreNodeConfig);
|
|
610
616
|
/**
|
|
611
617
|
* SAppIdLookup implementation - get sAppId for a strand: the claiming config's, else
|
|
@@ -966,11 +972,9 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
966
972
|
* `StrandSolicitationService.hasOutstandingInvitation`). A formation
|
|
967
973
|
* initiator is another party's peer by design and its token is only
|
|
968
974
|
* checkable inside the protocol, so the gate asks the coarser question
|
|
969
|
-
* "does this node expect a stranger at all?".
|
|
970
|
-
*
|
|
971
|
-
*
|
|
972
|
-
* bring-up) and `formStrand`'s lazy initialization both leave the gate
|
|
973
|
-
* armed, because neither mints an invitation.
|
|
975
|
+
* "does this node expect a stranger at all?". REGISTERING the responder
|
|
976
|
+
* does not suspend stranger denial: every node registers one at
|
|
977
|
+
* {@link start}, and registering mints no invitation.
|
|
974
978
|
*
|
|
975
979
|
* Ordering is semantically free (the checks are OR'd) but decides who pays:
|
|
976
980
|
* checks 1-3 are in-memory, 4/5 share one control-DB read, and only a peer
|
|
@@ -1002,6 +1006,11 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
1002
1006
|
* layer is fail-open behind `ADMISSION_DECISION_TIMEOUT_MS`, so the live
|
|
1003
1007
|
* read is safe here — unlike the per-stream gate, which must consult the
|
|
1004
1008
|
* materialized {@link authorizedControlPeers} snapshot instead.
|
|
1009
|
+
* NOTE: check 6 adds a second control read (`hasOutstandingFormationInvite`) for a
|
|
1010
|
+
* stranger with no locally minted invitation in play, on every node now that every
|
|
1011
|
+
* node runs the responder — a relay-enabled storage node included. If stranger
|
|
1012
|
+
* connections to such a node ever arrive fast enough for that read to show, cache
|
|
1013
|
+
* the answer for a few seconds.
|
|
1005
1014
|
* NOTE: on a relay-DISABLED node, a sibling whose membership row has not yet
|
|
1006
1015
|
* replicated here is denied until the row converges (typically via the
|
|
1007
1016
|
* owner); either side's next outbound reconcile dial (outbound is never
|
|
@@ -1344,6 +1353,12 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
1344
1353
|
* handling, is what keeps a mixed list from taking a whole peer offline.
|
|
1345
1354
|
*/
|
|
1346
1355
|
resolvePeerAddrs(peerId: string, opts?: ResolveOpts): Promise<Multiaddr[]>;
|
|
1356
|
+
/**
|
|
1357
|
+
* {@link resolvePeerAddrs} with the record's `UpdatedAt` kept beside the addresses, for a
|
|
1358
|
+
* caller that ranks peers by how recently they published. `null` wherever that returns `[]`
|
|
1359
|
+
* for a failed gate.
|
|
1360
|
+
*/
|
|
1361
|
+
private resolvePeerRecord;
|
|
1347
1362
|
/**
|
|
1348
1363
|
* Guarantee every address handed to a control-network dial terminates in
|
|
1349
1364
|
* `/p2p/<peerId>`, with no duplicates — the invariant every dial path
|
|
@@ -1537,15 +1552,18 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
1537
1552
|
*
|
|
1538
1553
|
* The list may name transports this node cannot dial (a lent node reports TCP
|
|
1539
1554
|
* and `/ws` addresses to a phone that dials WebSockets only). That needs no
|
|
1540
|
-
* filtering here: libp2p's dial queue (`calculateMultiaddrs`, libp2p 3.
|
|
1555
|
+
* filtering here: libp2p's dial queue (`calculateMultiaddrs`, libp2p 3.3.11)
|
|
1541
1556
|
* rejects an address no transport can dial before touching the network, so
|
|
1542
1557
|
* such an address costs a log line.
|
|
1543
1558
|
*
|
|
1544
1559
|
* The list is NOT handed to one `dial()`. libp2p tries a multi-address dial's
|
|
1545
|
-
* addresses one after another under a single deadline,
|
|
1546
|
-
*
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
1560
|
+
* addresses one after another under a single deadline, and sorts loopback
|
|
1561
|
+
* addresses last — so one or two addresses that never answer use up most of
|
|
1562
|
+
* the deadline before the address that works is tried. libp2p 3.3's
|
|
1563
|
+
* per-address `addressDialTimeout` does not prevent that: cadre sizes it for a
|
|
1564
|
+
* cold relayed open through two admission decisions (`optimysticDialLimits`,
|
|
1565
|
+
* 39 s at the default declared link).
|
|
1566
|
+
* {@link dialPeerAddrs} dials each address on its own time limit instead.
|
|
1549
1567
|
*/
|
|
1550
1568
|
private resolveControlDialAddrs;
|
|
1551
1569
|
/**
|
|
@@ -1817,16 +1835,6 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
1817
1835
|
* Idempotent.
|
|
1818
1836
|
*/
|
|
1819
1837
|
private wireControlConnectionListeners;
|
|
1820
|
-
/**
|
|
1821
|
-
* On a control connection opening: if it is a WebRTC connection, drain the TURN
|
|
1822
|
-
* tracker for the just-settled ICE verdict and, when it relayed, mark the peer
|
|
1823
|
-
* so {@link getConnectionPaths} classifies it `webrtc-turn` (relayed). The
|
|
1824
|
-
* settlement↔open correlation is timing-based and best-effort; an unknown
|
|
1825
|
-
* verdict degrades to not-relayed. Never throws to the event loop.
|
|
1826
|
-
*/
|
|
1827
|
-
private handleTurnConnectionOpen;
|
|
1828
|
-
/** On a control connection closing, drop any TURN-relayed flag for its peer. */
|
|
1829
|
-
private handleTurnConnectionClose;
|
|
1830
1838
|
/**
|
|
1831
1839
|
* Publish (or refresh) this node's own self-signed `DeviceToken` row so a server
|
|
1832
1840
|
* peer can resolve its FCM/APNs push token from its PeerId alone. Mirrors
|
|
@@ -2613,9 +2621,9 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
2613
2621
|
* caller runs the drive regardless).
|
|
2614
2622
|
*
|
|
2615
2623
|
* NOTE: against a relay that is DOWN this hook costs up to two strand-addr
|
|
2616
|
-
* timeouts (dial by peer id, then by addr;
|
|
2624
|
+
* timeouts (dial by peer id, then by addr; 28.5 s each at the default declared link round trip)
|
|
2617
2625
|
* before the reservation drive even starts, so one failed re-drive holds the supervisor
|
|
2618
|
-
* `driving` for those
|
|
2626
|
+
* `driving` for those 57 s plus the drive's own deadline — 75 s at the default, and longer on
|
|
2619
2627
|
* a host that declared a slower one (`link-budget.ts`).
|
|
2620
2628
|
* Bounded and harmless while the relay is unreachable anyway; if recovery
|
|
2621
2629
|
* latency after a relay comes back ever matters, skip the announce when the
|
|
@@ -3435,32 +3443,128 @@ export declare class CadreNode implements SAppIdLookup {
|
|
|
3435
3443
|
*/
|
|
3436
3444
|
dialInvite(invite: CadreInvite): Promise<void>;
|
|
3437
3445
|
/**
|
|
3438
|
-
*
|
|
3439
|
-
*
|
|
3446
|
+
* Replace this node's strand solicitation service — the formation responder every node
|
|
3447
|
+
* installs at {@link start}, and the initiator side of {@link formStrand}. Optional: call it
|
|
3448
|
+
* only to customize the responder (an approver, a provisioner, formation deadlines). The
|
|
3449
|
+
* new service's handler replaces the previous one's on the control node, and invitations
|
|
3450
|
+
* the previous service minted stay outstanding.
|
|
3451
|
+
*
|
|
3452
|
+
* Without `options.formationUsageRecorder`, tokens are checked against this party's
|
|
3453
|
+
* replicated `FormationInvite`/`FormationUsage` rows ({@link ControlFormationUsageRecorder}).
|
|
3454
|
+
* A responder that accepts every token is reachable only by constructing
|
|
3455
|
+
* {@link StrandSolicitationService} directly.
|
|
3440
3456
|
*
|
|
3441
3457
|
* @param options - Configuration for the solicitation service
|
|
3442
3458
|
*/
|
|
3443
3459
|
initializeStrandSolicitation(options?: StrandSolicitationServiceOptions): Promise<void>;
|
|
3444
3460
|
/**
|
|
3445
|
-
*
|
|
3461
|
+
* Answer formation from start. Log-and-continue: a node that cannot is still useful, and
|
|
3462
|
+
* {@link createOpenInvitation} / {@link formStrand} install the responder when it is missing.
|
|
3463
|
+
*/
|
|
3464
|
+
private installDefaultFormationResponder;
|
|
3465
|
+
/**
|
|
3466
|
+
* Move the control node's formation handler from the registered service to `service`.
|
|
3467
|
+
* Queued by {@link initializeStrandSolicitation} so swaps run one at a time: libp2p allows
|
|
3468
|
+
* one handler per protocol id, and two overlapping swaps would each find the other's
|
|
3469
|
+
* handler in the way. A failed swap registers the previous service again, points
|
|
3470
|
+
* {@link strandSolicitationService} back at it unless a later call has replaced it, and
|
|
3471
|
+
* rethrows.
|
|
3472
|
+
*
|
|
3473
|
+
* NOTE: same stray-handler caveat as {@link installSeedBootstrapService} — a failed
|
|
3474
|
+
* peer-store merge leaves the formation handler registered, so the restore below (and a
|
|
3475
|
+
* retry) rejects as a duplicate.
|
|
3476
|
+
*/
|
|
3477
|
+
private swapFormationResponder;
|
|
3478
|
+
/**
|
|
3479
|
+
* Get the strand solicitation service (for advanced use). Non-null on a started node unless
|
|
3480
|
+
* the install at {@link start} failed.
|
|
3446
3481
|
*/
|
|
3447
3482
|
getStrandSolicitationService(): StrandSolicitationService | null;
|
|
3448
3483
|
/**
|
|
3449
3484
|
* Create an open invitation for others to form strands with this party.
|
|
3450
3485
|
*
|
|
3486
|
+
* The invitation's bootstrap list names this machine first (it is the one most likely to
|
|
3487
|
+
* run the host strand), then a few of the party's other machines
|
|
3488
|
+
* ({@link siblingInvitationAddrs}), so a joiner can still form while this one is offline.
|
|
3489
|
+
*
|
|
3451
3490
|
* @param sAppId - The sApp to use for formed strands
|
|
3452
3491
|
* @param expirationMs - How long the invitation is valid (ms from now)
|
|
3453
3492
|
* @returns The open invitation to share out-of-band
|
|
3493
|
+
* @throws when neither this machine nor any other machine of the party has an address
|
|
3454
3494
|
*/
|
|
3455
3495
|
createOpenInvitation(sAppId: string, expirationMs?: number): Promise<OpenInvitation>;
|
|
3456
3496
|
/**
|
|
3457
|
-
*
|
|
3497
|
+
* Addresses of the party's other machines for an invitation's bootstrap list
|
|
3498
|
+
* ({@link selectInvitationSiblingAddrs} picks which). The source is each authorized
|
|
3499
|
+
* member's signed `CadrePeer` record ({@link resolvePeerRecord}), so a machine whose record
|
|
3500
|
+
* is missing, stale or untrusted is left out; live connections only order them.
|
|
3501
|
+
*
|
|
3502
|
+
* Best-effort: a failed read leaves the invitation naming this machine alone, which is what
|
|
3503
|
+
* it named before siblings were added.
|
|
3504
|
+
*/
|
|
3505
|
+
private siblingInvitationAddrs;
|
|
3506
|
+
/**
|
|
3507
|
+
* Form a strand with a responder via an open invitation: one attempt, from this machine, with
|
|
3508
|
+
* nothing recorded party-wide. {@link requestJoin} is the path that keeps trying.
|
|
3458
3509
|
*
|
|
3459
3510
|
* @param invitation - The open invitation received out-of-band
|
|
3460
3511
|
* @param disclosure - Identity/context information to share with the responder
|
|
3461
3512
|
* @returns The member key and strand info if successful
|
|
3513
|
+
* @throws `FormationRejectedError` or `FormationUnreachableError` when the formation fails, and
|
|
3514
|
+
* `FormationPostApprovalError` when it was approved and a step on this machine then failed
|
|
3462
3515
|
*/
|
|
3463
3516
|
formStrand(invitation: OpenInvitation, disclosure?: StrandFormationDisclosure): Promise<FormStrandResult>;
|
|
3517
|
+
/**
|
|
3518
|
+
* Ask to join through `invitation` and have the party keep trying until the join works, the
|
|
3519
|
+
* invitation is used up or expires, or the request is dismissed: across restarts, and from
|
|
3520
|
+
* any owner machine of the party (`docs/strands.md` → "Joining while the inviter is
|
|
3521
|
+
* offline"). Records a party-wide `PendingJoin` row, runs one attempt on this machine at
|
|
3522
|
+
* once, and returns the status after it: `'joined'` when the inviter answered yes, `'waiting'`
|
|
3523
|
+
* when it was unreachable or not ready, `'failed'` when it refused for good.
|
|
3524
|
+
*
|
|
3525
|
+
* Asking again for an invitation whose request is still pending adopts that request as it
|
|
3526
|
+
* is; asking again after it finished starts a fresh one. Later changes arrive as
|
|
3527
|
+
* `pendingJoin:changed`. A joined strand is offered through `strand:discovered` like any
|
|
3528
|
+
* {@link formStrand} join. Do not also call {@link formStrand} with the same invitation:
|
|
3529
|
+
* nothing coordinates the two, and one of them gets `token-spent`.
|
|
3530
|
+
*
|
|
3531
|
+
* @throws on a machine that is not an enrolled owner (the row is owner-signed), and on an
|
|
3532
|
+
* invitation already past its expiration
|
|
3533
|
+
*/
|
|
3534
|
+
requestJoin(invitation: OpenInvitation, disclosure?: StrandFormationDisclosure): Promise<PendingJoinStatus>;
|
|
3535
|
+
/**
|
|
3536
|
+
* Every join asked for with {@link requestJoin} and not dismissed, pending or finished, as this
|
|
3537
|
+
* machine sees it (see `PendingJoinStatus` for which states are machine-local).
|
|
3538
|
+
*/
|
|
3539
|
+
listPendingJoins(): Promise<PendingJoinStatus[]>;
|
|
3540
|
+
/**
|
|
3541
|
+
* Remove a join request party-wide. On a pending request this cancels it: every owner machine
|
|
3542
|
+
* stops at its next read, and an attempt already running does not record its outcome (a join
|
|
3543
|
+
* it made stays on that machine, as any {@link formStrand} join does). Owner machines only.
|
|
3544
|
+
* Resolves `false` when there was no such request.
|
|
3545
|
+
*/
|
|
3546
|
+
dismissPendingJoin(id: string): Promise<boolean>;
|
|
3547
|
+
private requirePendingJoins;
|
|
3548
|
+
/** This machine's owner key and signer for an owner-signed control write, or a throw carrying `refusal`. */
|
|
3549
|
+
private requireOwnerSigner;
|
|
3550
|
+
/**
|
|
3551
|
+
* Write a join request's row, or adopt the party's existing row for the same invitation: a
|
|
3552
|
+
* pending one as it is, a finished one replaced by `requested` (the user asked again).
|
|
3553
|
+
*/
|
|
3554
|
+
private recordJoinRequest;
|
|
3555
|
+
/** Build and start the pending-join retry loop over this node (see {@link pendingJoinRunner}). */
|
|
3556
|
+
private startPendingJoinRunner;
|
|
3557
|
+
/** The invitation a `PendingJoin` row stores. A failure names the row, never the invitation, which is a bearer credential. */
|
|
3558
|
+
private pendingJoinInvitation;
|
|
3559
|
+
private pendingJoinSAppId;
|
|
3560
|
+
/**
|
|
3561
|
+
* Stage the membership invitation of each `joined` row this process has not staged yet, so a
|
|
3562
|
+
* closed strand joined on another owner machine is seated by whichever machine launches it
|
|
3563
|
+
* first; the party key it admits is the replicated `StrandPartyKey` row the finishing machine
|
|
3564
|
+
* seated. A strand that already has an invitation staged keeps it, for the reconciler to
|
|
3565
|
+
* settle first.
|
|
3566
|
+
*/
|
|
3567
|
+
private stageMembershipInvitesFromPendingJoins;
|
|
3464
3568
|
/**
|
|
3465
3569
|
* Remember the strand a formation just joined (see {@link joinedStrandStore}), so it
|
|
3466
3570
|
* is re-offered after a restart even when the app is killed before its `addStrand`, and
|