@serfab/cadre-core 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/cadre-node.d.ts +527 -206
- package/dist/cadre-node.js +1084 -528
- 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 +6 -0
- package/dist/control-cohort.js +6 -0
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +46 -8
- package/dist/control-database.js +97 -18
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +37 -14
- package/dist/control-formation-recorder.js +60 -10
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-read-retry.d.ts +13 -12
- package/dist/control-read-retry.js +14 -12
- package/dist/control-read-retry.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +67 -5
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +9 -1
- package/dist/control-stream.js +24 -1
- package/dist/control-stream.js.map +1 -1
- package/dist/control-write-retry.d.ts +12 -2
- package/dist/control-write-retry.js +13 -2
- package/dist/control-write-retry.js.map +1 -1
- package/dist/delegate-admission.d.ts +11 -8
- package/dist/delegate-admission.js +19 -11
- package/dist/delegate-admission.js.map +1 -1
- package/dist/diagnostics/connection-path.d.ts +0 -7
- package/dist/diagnostics/connection-path.js +0 -7
- package/dist/diagnostics/connection-path.js.map +1 -1
- package/dist/formation-approval.d.ts +7 -0
- package/dist/formation-approval.js +9 -3
- package/dist/formation-approval.js.map +1 -1
- package/dist/fs-atomic.d.ts +11 -2
- package/dist/fs-atomic.js +13 -3
- package/dist/fs-atomic.js.map +1 -1
- package/dist/hibernation-manager.d.ts +111 -8
- package/dist/hibernation-manager.js +234 -49
- package/dist/hibernation-manager.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +25 -20
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +90 -25
- package/dist/joined-strand-store.js +223 -55
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store-file.js +14 -5
- package/dist/key-store-file.js.map +1 -1
- package/dist/link-budget.d.ts +367 -69
- package/dist/link-budget.js +375 -72
- package/dist/link-budget.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +30 -43
- package/dist/membership-connection-gater.js +31 -42
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-local-snapshot.d.ts +6 -4
- package/dist/node-local-snapshot.js +7 -3
- package/dist/node-local-snapshot.js.map +1 -1
- package/dist/peer-dial.d.ts +24 -4
- package/dist/peer-dial.js +74 -5
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +2 -10
- package/dist/peer-join-backfill.js +8 -8
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/push-fanout.d.ts +6 -0
- package/dist/push-fanout.js +6 -0
- package/dist/push-fanout.js.map +1 -1
- package/dist/relay-reservation.d.ts +3 -1
- package/dist/relay-reservation.js +3 -1
- package/dist/relay-reservation.js.map +1 -1
- package/dist/relay-server.d.ts +79 -0
- package/dist/relay-server.js +74 -0
- package/dist/relay-server.js.map +1 -0
- package/dist/seed-bootstrap.d.ts +57 -4
- package/dist/seed-bootstrap.js +107 -83
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/storage-scope.d.ts +33 -17
- package/dist/storage-scope.js +44 -23
- package/dist/storage-scope.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +58 -21
- package/dist/strand-addr-protocol.js +133 -85
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-database.d.ts +20 -2
- package/dist/strand-database.js +42 -5
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +59 -21
- package/dist/strand-first-sync-gate.js +58 -19
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-formation-deadlines.d.ts +151 -0
- package/dist/strand-formation-deadlines.js +171 -0
- package/dist/strand-formation-deadlines.js.map +1 -0
- package/dist/strand-formation-manager.d.ts +63 -30
- package/dist/strand-formation-manager.js +67 -41
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +45 -46
- package/dist/strand-formation-protocol.js +62 -126
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-fret-addrs.d.ts +54 -0
- package/dist/strand-fret-addrs.js +108 -0
- package/dist/strand-fret-addrs.js.map +1 -0
- package/dist/strand-instance-manager.d.ts +122 -44
- package/dist/strand-instance-manager.js +270 -114
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +6 -0
- package/dist/strand-membership-writer.js +11 -0
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-network-state-file.d.ts +12 -0
- package/dist/strand-network-state-file.js +38 -0
- package/dist/strand-network-state-file.js.map +1 -0
- package/dist/strand-network-state.d.ts +111 -0
- package/dist/strand-network-state.js +191 -0
- package/dist/strand-network-state.js.map +1 -0
- package/dist/strand-revocation-enforcer.js +2 -1
- package/dist/strand-revocation-enforcer.js.map +1 -1
- package/dist/strand-solicitation.d.ts +36 -20
- package/dist/strand-solicitation.js +4 -4
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-wake-protocol.d.ts +80 -23
- package/dist/strand-wake-protocol.js +89 -64
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/types.d.ts +148 -61
- package/dist/types.js +4 -3
- package/dist/types.js.map +1 -1
- package/package.json +11 -10
- package/src/cadre-node.ts +8400 -7776
- package/src/control-authorization.ts +2 -1
- package/src/control-cohort.ts +6 -0
- package/src/control-database.ts +122 -18
- package/src/control-formation-recorder.ts +354 -305
- package/src/control-read-retry.ts +14 -12
- package/src/control-schema.ts +67 -5
- package/src/control-stream.ts +25 -1
- package/src/control-write-retry.ts +13 -2
- package/src/delegate-admission.ts +23 -13
- package/src/diagnostics/connection-path.ts +0 -7
- package/src/formation-approval.ts +610 -604
- package/src/fs-atomic.ts +14 -4
- package/src/hibernation-manager.ts +638 -437
- package/src/index.ts +43 -65
- package/src/joined-strand-store.ts +247 -57
- package/src/key-store-file.ts +14 -5
- package/src/link-budget.ts +393 -74
- package/src/membership-connection-gater.ts +31 -45
- package/src/node-local-snapshot.ts +12 -7
- package/src/peer-dial.ts +81 -7
- package/src/peer-join-backfill.ts +10 -9
- package/src/push-fanout.ts +6 -0
- package/src/relay-reservation.ts +3 -1
- package/src/relay-server.ts +98 -0
- package/src/seed-bootstrap.ts +133 -91
- package/src/storage-scope.ts +44 -23
- package/src/strand-addr-protocol.ts +547 -458
- package/src/strand-database.ts +287 -242
- package/src/strand-first-sync-gate.ts +58 -19
- package/src/strand-formation-deadlines.ts +227 -0
- package/src/strand-formation-manager.ts +700 -647
- package/src/strand-formation-protocol.ts +106 -154
- package/src/strand-fret-addrs.ts +145 -0
- package/src/strand-instance-manager.ts +307 -140
- package/src/strand-membership-writer.ts +12 -0
- package/src/strand-network-state-file.ts +40 -0
- package/src/strand-network-state.ts +243 -0
- package/src/strand-revocation-enforcer.ts +2 -1
- package/src/strand-solicitation.ts +519 -500
- package/src/strand-wake-protocol.ts +401 -355
- package/src/types.ts +150 -61
- package/dist/strand-peer-book-file.d.ts +0 -12
- package/dist/strand-peer-book-file.js +0 -37
- package/dist/strand-peer-book-file.js.map +0 -1
- package/dist/strand-peer-book-protocol.d.ts +0 -159
- package/dist/strand-peer-book-protocol.js +0 -360
- package/dist/strand-peer-book-protocol.js.map +0 -1
- package/dist/strand-peer-book-swap.d.ts +0 -104
- package/dist/strand-peer-book-swap.js +0 -284
- package/dist/strand-peer-book-swap.js.map +0 -1
- package/dist/strand-peer-book.d.ts +0 -159
- package/dist/strand-peer-book.js +0 -354
- package/dist/strand-peer-book.js.map +0 -1
- package/dist/strand-peer-observer.d.ts +0 -88
- package/dist/strand-peer-observer.js +0 -180
- package/dist/strand-peer-observer.js.map +0 -1
- package/src/strand-peer-book-file.ts +0 -39
- package/src/strand-peer-book-protocol.ts +0 -463
- package/src/strand-peer-book-swap.ts +0 -338
- package/src/strand-peer-book.ts +0 -468
- package/src/strand-peer-observer.ts +0 -235
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strand-formation deadlines, derived from the declared link round trip.
|
|
3
|
+
*
|
|
4
|
+
* The wire protocol lives in `strand-formation-protocol.ts`; this module is only the
|
|
5
|
+
* arithmetic it runs on: the ladder of deadlines one declaration yields
|
|
6
|
+
* ({@link formationDeadlines}) and the clamping of a caller's configured provisioning budget
|
|
7
|
+
* under its session ({@link resolveProvisionTimeoutMs}, {@link splitProvisionBudget}). It
|
|
8
|
+
* reaches `link-budget.ts` for the counts and `formation-approval.ts` for the hook's flat
|
|
9
|
+
* timeout, and nothing in the protocol, so both roles and the manager can import it freely.
|
|
10
|
+
*/
|
|
11
|
+
import debug from 'debug';
|
|
12
|
+
import { DEFAULT_APPROVAL_TIMEOUT_MS } from './formation-approval.js';
|
|
13
|
+
import { CIRCUIT_REQUEST_ROUND_TRIPS, cohortReadDeadlineMs, commitBudgetMs, relayedStreamOpenBudgetMs, resolveLinkRoundTripMs } from './link-budget.js';
|
|
14
|
+
const log = debug('sereus:cadre:formation-deadlines');
|
|
15
|
+
/**
|
|
16
|
+
* Derive every formation deadline from the declared link round trip
|
|
17
|
+
* (`NetworkConfig.linkRoundTripMs`; the default when none is declared is
|
|
18
|
+
* `DECLARED_LINK_ROUND_TRIP_MS` in `link-budget.ts`). With `L` the declaration, `R` one
|
|
19
|
+
* cohort read at that link (`cohortReadDeadlineMs`, 2L: one request and its answer over an
|
|
20
|
+
* open circuit) and `K` one commit (`commitBudgetMs`, 20L, measured):
|
|
21
|
+
*
|
|
22
|
+
* dialMs = a relayed dial plus one protocol negotiation (5L + 2 000)
|
|
23
|
+
* awaitContactMs = one request over the open stream (2L)
|
|
24
|
+
* validationMs = 2R (4L)
|
|
25
|
+
* provisionWorkMs = approval hook (10 000, flat) + 2R + K (10 000 + 24L)
|
|
26
|
+
* provisionGraceMs = R + K (22L)
|
|
27
|
+
* responseTravelMarginMs = L + validationMs (5L)
|
|
28
|
+
* initiatorAwaitResponseMs = work + grace + margin (10 000 + 51L)
|
|
29
|
+
* sessionMs = dialMs + initiatorAwaitResponseMs (12 000 + 56L)
|
|
30
|
+
*
|
|
31
|
+
* Why each term:
|
|
32
|
+
*
|
|
33
|
+
* - **awaitContact**: the listener's handler starts when it answers the protocol
|
|
34
|
+
* negotiation; the answer reaches the joiner and the contact frame comes back, one round
|
|
35
|
+
* trip, budgeted as a request over an open stream (2) for the same headroom as every other
|
|
36
|
+
* one-exchange read in `link-budget.ts`.
|
|
37
|
+
* - **validation** and the reads inside **provisionWork** are budgeted at two consulting
|
|
38
|
+
* reads each, not one per read the code issues. What actually runs: validation is three
|
|
39
|
+
* control reads (`isTokenValid` reads the invite; `isTokenUsed` reads it again and counts
|
|
40
|
+
* its usages) plus whatever the disclosure validator does; the bound provisioning path
|
|
41
|
+
* (`StrandFormationManager.provisionAsResponder`) reads the invite and the strand row to
|
|
42
|
+
* resolve the host strand, the invite again, the approver's `ValidationKey` and the seat
|
|
43
|
+
* count around the outside approval hook (an HTTP call, so its own
|
|
44
|
+
* `DEFAULT_APPROVAL_TIMEOUT_MS` is link-independent and added flat), the strand row and its
|
|
45
|
+
* `StrandPartyKey` to issue the joiner's membership invite, and the host strand's stamp
|
|
46
|
+
* before the `FormationUsage` write; then one strand-database commit issues the invite.
|
|
47
|
+
* Every one of those is a read of this party's own control database, which in steady state
|
|
48
|
+
* touches held blocks and consults nobody (`cadre-consistency.md` → "Deadlines Over
|
|
49
|
+
* Optimystic's Reads and Commits"), so `R` is charged as headroom for the ones that do
|
|
50
|
+
* consult, not per read. Waking a hibernating host strand inside the issue is NOT counted
|
|
51
|
+
* either: `wakeHostStrandForFormation` cuts it off by design with a retryable rejection
|
|
52
|
+
* and leaves the wake running, so the joiner's retry finds the strand live.
|
|
53
|
+
* NOTE: if formation is seen timing out while the responder's control reads are consulting
|
|
54
|
+
* the cohort (a cold responder, a control database not yet converged), charge one `R` per
|
|
55
|
+
* read here rather than raising the flat headroom; the joiner is told 'Formation
|
|
56
|
+
* provisioning timed out' with its invite unspent, so the cost is a retry, not a spent
|
|
57
|
+
* invite.
|
|
58
|
+
* - **provisionGrace**: the window it exists for opens when the `FormationUsage` insert
|
|
59
|
+
* attempt passes its abort check. `ControlDatabase.redeemInvitation` and
|
|
60
|
+
* `recordFormationUsage` check the signal once per attempt inside the write lock, then run
|
|
61
|
+
* the seat read (`assertSeatRemains`) and the transaction, so the grace contains one read
|
|
62
|
+
* plus one commit. A retry after a failed attempt re-checks the abort, so only one attempt
|
|
63
|
+
* needs containing.
|
|
64
|
+
* - **responseTravelMargin**: half a round trip out, half back, plus the validation reads,
|
|
65
|
+
* which run on the initiator's await-response clock but before the responder's
|
|
66
|
+
* provisioning clock starts.
|
|
67
|
+
* - **session**: the initiator's dial plus its await-response. The responder's whole path
|
|
68
|
+
* (awaitContact + validation + work + grace = 10 000 + 52L) is inside it at every L.
|
|
69
|
+
*
|
|
70
|
+
* Ordering, strict at every L > 0, and pinned by `strand-formation-deadlines.spec.ts`:
|
|
71
|
+
* approval hook < provisionWork < work + grace < initiatorAwaitResponse < session, and the
|
|
72
|
+
* responder's whole path < session. Each layer can therefore fail and report before the
|
|
73
|
+
* layer above it gives up, and the work budget always outlasts the hook's own timeout, so a
|
|
74
|
+
* dead hook reports 'Formation approval unavailable, retry' rather than racing a
|
|
75
|
+
* provisioning timeout.
|
|
76
|
+
*
|
|
77
|
+
* **What this costs.** At the default declaration (3 500 ms) a joiner whose responder
|
|
78
|
+
* accepts the contact and then hangs waits up to 188.5 s, about three minutes, before it is
|
|
79
|
+
* told, where the fixed ladder this replaced told it after 15 s; the whole session is
|
|
80
|
+
* bounded at 208 s. A responder that is unreachable still fails at the dial, 19.5 s. A host
|
|
81
|
+
* that knows its party is on a fast link lowers `linkRoundTripMs` and gets roughly the old
|
|
82
|
+
* numbers back (at L = 100: dial 2.5 s, provisioning 14.6 s, await-response 15.1 s, session
|
|
83
|
+
* 17.6 s). Before this derivation, the fixed 5 s dial could not open a relayed connection
|
|
84
|
+
* above a 1.25-second round trip, and the fixed 2 s grace could not contain one commit at the
|
|
85
|
+
* supported link, so a joiner could be told 'timed out' over an invite that was in fact
|
|
86
|
+
* spent.
|
|
87
|
+
*/
|
|
88
|
+
export function formationDeadlines(linkRoundTripMs) {
|
|
89
|
+
const link = resolveLinkRoundTripMs(linkRoundTripMs);
|
|
90
|
+
const readMs = cohortReadDeadlineMs(link);
|
|
91
|
+
const commitMs = commitBudgetMs(link);
|
|
92
|
+
const dialMs = relayedStreamOpenBudgetMs(link);
|
|
93
|
+
const validationMs = 2 * readMs;
|
|
94
|
+
const provisionWorkMs = DEFAULT_APPROVAL_TIMEOUT_MS + 2 * readMs + commitMs;
|
|
95
|
+
const provisionGraceMs = readMs + commitMs;
|
|
96
|
+
const responseTravelMarginMs = link + validationMs;
|
|
97
|
+
const initiatorAwaitResponseMs = provisionWorkMs + provisionGraceMs + responseTravelMarginMs;
|
|
98
|
+
return {
|
|
99
|
+
dialMs,
|
|
100
|
+
awaitContactMs: CIRCUIT_REQUEST_ROUND_TRIPS * link,
|
|
101
|
+
validationMs,
|
|
102
|
+
provisionWorkMs,
|
|
103
|
+
provisionGraceMs,
|
|
104
|
+
responseTravelMarginMs,
|
|
105
|
+
initiatorAwaitResponseMs,
|
|
106
|
+
sessionMs: dialMs + initiatorAwaitResponseMs
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Ceiling for a resolved provisioning budget.
|
|
111
|
+
*
|
|
112
|
+
* The session budget also has to cover what PRECEDES provisioning in the role
|
|
113
|
+
* (`precedingMs`: the initiator's dial; the responder's contact read plus its validation
|
|
114
|
+
* reads), so that whole span is held back rather than triggering only on a literal overrun.
|
|
115
|
+
*
|
|
116
|
+
* `reserveMs` is the EXTRA room only the responder holds back, so its own budget still
|
|
117
|
+
* lands strictly before the initiator's larger await-response budget even when both are
|
|
118
|
+
* clamped — without it, a configured budget large enough to clamp both roles puts the
|
|
119
|
+
* responder's reply on the wire at the moment the initiator's timeout fires. Capped at half
|
|
120
|
+
* the remaining room (like {@link splitProvisionBudget}) so a small session config still
|
|
121
|
+
* spends most of it working.
|
|
122
|
+
*/
|
|
123
|
+
function provisionCeilingMs(sessionTimeoutMs, precedingMs, reserveMs) {
|
|
124
|
+
const roomMs = sessionTimeoutMs - precedingMs;
|
|
125
|
+
return Math.max(1, roomMs - Math.min(reserveMs, Math.floor(roomMs / 2)));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The extra room the responder's clamp holds back ({@link provisionCeilingMs}'s `reserveMs`).
|
|
129
|
+
*
|
|
130
|
+
* The initiator's clamped await-response is `session - dial`, and the responder's reply
|
|
131
|
+
* reaches it `responseTravelMarginMs` after provisioning ends, so provisioning must end by
|
|
132
|
+
* `session - dial - margin`. The responder's own room is `session - awaitContact -
|
|
133
|
+
* validation`; the difference between the two is what it must hold back on top. Computed
|
|
134
|
+
* from the responder's own derivation, since it cannot see the initiator's dial budget: the
|
|
135
|
+
* module doc of `link-budget.ts` says why both parties must declare the same link.
|
|
136
|
+
*/
|
|
137
|
+
export function responderClampReserveMs(deadlines, awaitContactMs) {
|
|
138
|
+
return Math.max(0, deadlines.dialMs + deadlines.responseTravelMarginMs - awaitContactMs - deadlines.validationMs);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Resolve a caller-supplied provisioning budget: `0`/negative means "unset" (use
|
|
142
|
+
* `defaultMs`). If the result would let provisioning outlive the session — no result
|
|
143
|
+
* frame is ever sent, exactly the failure this budget exists to prevent — clamp it to
|
|
144
|
+
* {@link provisionCeilingMs} and log a warning. A budget that exactly meets the ceiling is
|
|
145
|
+
* not clamped: the derived defaults sit there by construction.
|
|
146
|
+
*/
|
|
147
|
+
export function resolveProvisionTimeoutMs(configured, defaultMs, sessionTimeoutMs, precedingMs, role, reserveMs = 0) {
|
|
148
|
+
const requested = configured && configured > 0 ? configured : defaultMs;
|
|
149
|
+
const ceilingMs = provisionCeilingMs(sessionTimeoutMs, precedingMs, reserveMs);
|
|
150
|
+
if (requested > ceilingMs) {
|
|
151
|
+
log('%s provisionTimeoutMs %dms leaves no room under sessionTimeoutMs %dms (preceding %dms, reserve %dms); clamping to %dms', role, requested, sessionTimeoutMs, precedingMs, reserveMs, ceilingMs);
|
|
152
|
+
return ceilingMs;
|
|
153
|
+
}
|
|
154
|
+
return requested;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Split a resolved provisioning budget into the WORK budget and the trailing settle grace.
|
|
158
|
+
*
|
|
159
|
+
* The grace is carved OUT of the budget, never added on top, so the ladder in
|
|
160
|
+
* {@link formationDeadlines} is untouched: the listener aborts the provisioning hook when the
|
|
161
|
+
* work budget expires, then waits up to the grace for the work to settle anyway
|
|
162
|
+
* (`FormationListener.settleWithinGrace` in `strand-formation-protocol.ts`). `graceCeilingMs`
|
|
163
|
+
* is the derived grace, which contains one seat read plus one commit at the declared link; it
|
|
164
|
+
* is capped at half the budget so a small configured budget still spends at least half its
|
|
165
|
+
* time doing work.
|
|
166
|
+
*/
|
|
167
|
+
export function splitProvisionBudget(provisionTimeoutMs, graceCeilingMs) {
|
|
168
|
+
const graceMs = Math.min(graceCeilingMs, Math.floor(provisionTimeoutMs / 2));
|
|
169
|
+
return { workMs: provisionTimeoutMs - graceMs, graceMs };
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=strand-formation-deadlines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strand-formation-deadlines.js","sourceRoot":"","sources":["../src/strand-formation-deadlines.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,12 +14,14 @@ export declare const MEMBERSHIP_INVITE_TTL_MS: number;
|
|
|
14
14
|
/**
|
|
15
15
|
* Rejection reason for a bound CLOSED-strand redemption whose responder could not issue
|
|
16
16
|
* the joiner's membership invitation — the host strand runtime not live on this
|
|
17
|
-
* responder,
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* a
|
|
17
|
+
* responder (never launched, mid-start, or a hibernating one that did not wake within the
|
|
18
|
+
* provisioning budget; a hibernating runtime is woken, not refused), no party identity key
|
|
19
|
+
* yet, or the strand DB refusing the `Strand.Invite` write. Retryable on purpose, and
|
|
20
|
+
* rejected BEFORE the consent row is recorded, so the formation token stays unspent:
|
|
21
|
+
* approving without an invitation would admit a joiner that looks joined but can never
|
|
22
|
+
* become a member, and a responder not running the strand cannot serve the joiner's sync
|
|
23
|
+
* anyway. The one permanent failure, a pre-split host strand, gets
|
|
24
|
+
* {@link HOST_STRAND_MUST_BE_RECREATED_REASON} instead.
|
|
23
25
|
*/
|
|
24
26
|
export declare const MEMBERSHIP_INVITE_UNAVAILABLE_REASON = "Strand membership invitation unavailable, retry";
|
|
25
27
|
/**
|
|
@@ -31,20 +33,36 @@ export declare const MEMBERSHIP_INVITE_UNAVAILABLE_REASON = "Strand membership i
|
|
|
31
33
|
* the formation token stays unspent.
|
|
32
34
|
*/
|
|
33
35
|
export declare const HOST_STRAND_MUST_BE_RECREATED_REASON = "Host strand must be recreated";
|
|
36
|
+
/**
|
|
37
|
+
* Responder-side seam that issues a bound joiner's membership invitation — see
|
|
38
|
+
* {@link StrandFormationManagerOptions.issueMembershipInvite} for the contract. `signal`
|
|
39
|
+
* is the responder's provisioning budget: the issuer stops waiting (and throws) once it
|
|
40
|
+
* aborts.
|
|
41
|
+
*/
|
|
42
|
+
export type MembershipInviteIssuer = (strandId: string, signal?: AbortSignal) => Promise<StrandMembershipInvite | null>;
|
|
34
43
|
/**
|
|
35
44
|
* Configuration for StrandFormationManager
|
|
36
45
|
*/
|
|
37
46
|
export interface StrandFormationManagerConfig {
|
|
38
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* This machine's declared link round trip (`NetworkConfig.linkRoundTripMs`), from which
|
|
49
|
+
* every formation deadline is derived (`formationDeadlines` in
|
|
50
|
+
* `strand-formation-deadlines.ts`). `CadreNode` fills it from its network config; the
|
|
51
|
+
* fields below override single rungs of that ladder.
|
|
52
|
+
*/
|
|
53
|
+
linkRoundTripMs?: number;
|
|
54
|
+
/** Whole-session budget, both roles, in milliseconds. */
|
|
39
55
|
sessionTimeoutMs?: number;
|
|
40
|
-
/**
|
|
56
|
+
/** The responder's contact-frame read, in milliseconds. */
|
|
41
57
|
stepTimeoutMs?: number;
|
|
58
|
+
/** The initiator's dial-connect (open the connection, negotiate the protocol), in milliseconds. */
|
|
59
|
+
dialTimeoutMs?: number;
|
|
42
60
|
/**
|
|
43
61
|
* Provisioning budget in milliseconds for the RESPONDER's `provisionStrand` hook call.
|
|
44
|
-
* The initiator's `await-response` wait is derived automatically from this value plus
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
62
|
+
* The initiator's `await-response` wait is derived automatically from this value plus the
|
|
63
|
+
* travel margin of the derived ladder (`responseTravelMarginMs`) — never set directly — so
|
|
64
|
+
* the ordering documented there (approval hook < responder provisioning < initiator
|
|
65
|
+
* await-response < session) cannot collapse when this is configured.
|
|
48
66
|
*/
|
|
49
67
|
provisionTimeoutMs?: number;
|
|
50
68
|
/** Maximum concurrent sessions */
|
|
@@ -97,11 +115,15 @@ export interface StrandFormationManagerOptions {
|
|
|
97
115
|
* `PreSplitStrandIdentityError` for a host strand that can never issue one; that maps
|
|
98
116
|
* to the non-retryable {@link HOST_STRAND_MUST_BE_RECREATED_REASON}.
|
|
99
117
|
*
|
|
118
|
+
* A hibernating host runtime is not a reason to throw: the issuer wakes it first,
|
|
119
|
+
* bounded by `signal` (the responder's provisioning budget), and throws only when the
|
|
120
|
+
* wake does not finish in time or fails.
|
|
121
|
+
*
|
|
100
122
|
* Left unwired — mock/transport tests — the bound path approves with no invitation,
|
|
101
123
|
* mirroring the unwired {@link resolveStrandAddrs} posture. Production
|
|
102
124
|
* (`CadreNode.initializeStrandSolicitation`) always wires it.
|
|
103
125
|
*/
|
|
104
|
-
issueMembershipInvite?:
|
|
126
|
+
issueMembershipInvite?: MembershipInviteIssuer;
|
|
105
127
|
/** Configuration options */
|
|
106
128
|
config?: StrandFormationManagerConfig;
|
|
107
129
|
}
|
|
@@ -136,11 +158,11 @@ export declare class StrandFormationManager {
|
|
|
136
158
|
* Register this manager as a protocol handler on a libp2p node.
|
|
137
159
|
* Call this on the control network node to handle incoming formation requests.
|
|
138
160
|
*/
|
|
139
|
-
registerResponder(node: Libp2p, protocolId?: string): void
|
|
161
|
+
registerResponder(node: Libp2p, protocolId?: string): Promise<void>;
|
|
140
162
|
/**
|
|
141
163
|
* Unregister the protocol handler from a libp2p node.
|
|
142
164
|
*/
|
|
143
|
-
unregisterResponder(node: Libp2p, protocolId?: string): void
|
|
165
|
+
unregisterResponder(node: Libp2p, protocolId?: string): Promise<void>;
|
|
144
166
|
/**
|
|
145
167
|
* Form a strand with a responder via an open invitation (initiator side).
|
|
146
168
|
*
|
|
@@ -171,12 +193,13 @@ export declare class StrandFormationManager {
|
|
|
171
193
|
private membershipInviteFrom;
|
|
172
194
|
/**
|
|
173
195
|
* Derive the initiator's await-response budget from the configured RESPONDER budget —
|
|
174
|
-
* never the same number (see `StrandFormationManagerConfig.provisionTimeoutMs`)
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
196
|
+
* never the same number (see `StrandFormationManagerConfig.provisionTimeoutMs`): the
|
|
197
|
+
* configured value plus the travel margin the ladder derives at this machine's link.
|
|
198
|
+
* Mirrors `resolveProvisionTimeoutMs`'s own "`0`/negative means unset" rule so an unset
|
|
199
|
+
* config still lets both sides fall back to their own derived defaults; must NOT
|
|
200
|
+
* reproduce the derived default here, or the per-role clamping downstream is defeated.
|
|
178
201
|
* A value too large for the session is clamped per role, and the responder's ceiling holds
|
|
179
|
-
* the
|
|
202
|
+
* the margin back, so the ordering survives there too.
|
|
180
203
|
*/
|
|
181
204
|
private initiatorProvisionTimeoutMs;
|
|
182
205
|
private validateToken;
|
|
@@ -187,14 +210,16 @@ export declare class StrandFormationManager {
|
|
|
187
210
|
* {@link ResponderProvisionOutcome} with `approved: false` — `runSession` turns that
|
|
188
211
|
* into a clean, non-disclosing reply instead of a dropped result frame.
|
|
189
212
|
*
|
|
190
|
-
* - **bound** (host strand present): provision-then-record
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
213
|
+
* - **bound** (host strand present): provision-then-record, in three steps —
|
|
214
|
+
* (1) authorize ({@link authorizeBoundUsage}: the outside approval when the invite
|
|
215
|
+
* demands one, and a seat pre-check), so a refused join writes nothing into the host
|
|
216
|
+
* strand; (2) issue the joiner's single-use strand membership invitation via the wired
|
|
217
|
+
* `issueMembershipInvite` seam ({@link issueBoundMembershipInvite}; a closed strand whose
|
|
218
|
+
* invitation cannot be issued rejects retryably HERE, before any consent row spends the
|
|
219
|
+
* token); (3) write the single `FormationUsage` consent row against the pre-existing
|
|
220
|
+
* strand (record-only) and return it + its membership key + the invitation (all
|
|
221
|
+
* read-gating secrets disclosed only here, behind the token + disclosure validation
|
|
222
|
+
* `runSession` already enforced).
|
|
198
223
|
* - **missing** (invite names a host strand absent on this responder, e.g. unconverged):
|
|
199
224
|
* reject cleanly + retryably, writing NO usage row — recording usage here would fail the
|
|
200
225
|
* deferred `StrandExists` CHECK at commit and drop the frame.
|
|
@@ -213,15 +238,23 @@ export declare class StrandFormationManager {
|
|
|
213
238
|
* not control-flow-by-exception.
|
|
214
239
|
*/
|
|
215
240
|
private provisionAsResponder;
|
|
241
|
+
/**
|
|
242
|
+
* Authorize a BOUND redemption without writing it, through the recorder's optional
|
|
243
|
+
* {@link FormationUsageRecorder.authorizeUsage}. A recorder without it has nothing to ask up
|
|
244
|
+
* front, so its handle defers everything to `recordUsage`.
|
|
245
|
+
*/
|
|
246
|
+
private authorizeBoundUsage;
|
|
216
247
|
/**
|
|
217
248
|
* Issue the joiner's membership invitation for a BOUND redemption via the wired
|
|
218
|
-
* {@link StrandFormationManagerOptions.issueMembershipInvite} seam.
|
|
249
|
+
* {@link StrandFormationManagerOptions.issueMembershipInvite} seam. Runs after the
|
|
250
|
+
* redemption is authorized ({@link authorizeBoundUsage}) and before consent is recorded.
|
|
219
251
|
*
|
|
220
252
|
* - Hook unwired (mock/transport tests): approve with no invitation, the same posture
|
|
221
253
|
* as an unwired `resolveStrandAddrs`.
|
|
222
254
|
* - Hook returns an invitation (closed host strand): carry it on the approval.
|
|
223
255
|
* - Hook returns `null` (open host strand): approve with no invitation.
|
|
224
|
-
* - Hook throws (runtime not live
|
|
256
|
+
* - Hook throws (runtime not live — including a hibernating one whose wake outran
|
|
257
|
+
* `signal` — no party key, strand-DB write rejected): report
|
|
225
258
|
* `ok: false` with {@link MEMBERSHIP_INVITE_UNAVAILABLE_REASON} — the caller rejects
|
|
226
259
|
* BEFORE any consent row is written, so the formation token stays unspent.
|
|
227
260
|
* - Hook throws `PreSplitStrandIdentityError` (the host strand was founded before the
|
|
@@ -6,7 +6,8 @@ import { FormationAbortedError, InvitationExhaustedError } from './control-datab
|
|
|
6
6
|
import { PreSplitStrandIdentityError } from './strand-membership-writer.js';
|
|
7
7
|
import { mintPlaceholderStrandId } from './strand-id.js';
|
|
8
8
|
import { canonicalJson } from './canonical-json.js';
|
|
9
|
-
import { FormationListener, INVALID_TOKEN_REASON,
|
|
9
|
+
import { FormationListener, INVALID_TOKEN_REASON, dialFormation, isValidResponderCreatesResult, isWellFormedMembershipInvite } from './strand-formation-protocol.js';
|
|
10
|
+
import { formationDeadlines } from './strand-formation-deadlines.js';
|
|
10
11
|
const log = debug('sereus:cadre:formation-manager');
|
|
11
12
|
/**
|
|
12
13
|
* Largest serialized disclosure a responder will accept (8 KiB). The disclosure is
|
|
@@ -28,12 +29,14 @@ export const MEMBERSHIP_INVITE_TTL_MS = 7 * 24 * 3600000;
|
|
|
28
29
|
/**
|
|
29
30
|
* Rejection reason for a bound CLOSED-strand redemption whose responder could not issue
|
|
30
31
|
* the joiner's membership invitation — the host strand runtime not live on this
|
|
31
|
-
* responder,
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* a
|
|
32
|
+
* responder (never launched, mid-start, or a hibernating one that did not wake within the
|
|
33
|
+
* provisioning budget; a hibernating runtime is woken, not refused), no party identity key
|
|
34
|
+
* yet, or the strand DB refusing the `Strand.Invite` write. Retryable on purpose, and
|
|
35
|
+
* rejected BEFORE the consent row is recorded, so the formation token stays unspent:
|
|
36
|
+
* approving without an invitation would admit a joiner that looks joined but can never
|
|
37
|
+
* become a member, and a responder not running the strand cannot serve the joiner's sync
|
|
38
|
+
* anyway. The one permanent failure, a pre-split host strand, gets
|
|
39
|
+
* {@link HOST_STRAND_MUST_BE_RECREATED_REASON} instead.
|
|
37
40
|
*/
|
|
38
41
|
export const MEMBERSHIP_INVITE_UNAVAILABLE_REASON = 'Strand membership invitation unavailable, retry';
|
|
39
42
|
/**
|
|
@@ -92,6 +95,7 @@ export class StrandFormationManager {
|
|
|
92
95
|
// Forwarded only when wired, so `FormationListenerOptions.resolveStrandAddrs`
|
|
93
96
|
// stays genuinely absent (and the listener short-circuits) for an unwired manager.
|
|
94
97
|
...(this.resolveStrandAddrs && { resolveStrandAddrs: this.resolveStrandAddrs }),
|
|
98
|
+
linkRoundTripMs: this.config.linkRoundTripMs,
|
|
95
99
|
sessionTimeoutMs: this.config.sessionTimeoutMs,
|
|
96
100
|
stepTimeoutMs: this.config.stepTimeoutMs,
|
|
97
101
|
provisionTimeoutMs: this.config.provisionTimeoutMs,
|
|
@@ -103,23 +107,23 @@ export class StrandFormationManager {
|
|
|
103
107
|
* Register this manager as a protocol handler on a libp2p node.
|
|
104
108
|
* Call this on the control network node to handle incoming formation requests.
|
|
105
109
|
*/
|
|
106
|
-
registerResponder(node, protocolId) {
|
|
110
|
+
async registerResponder(node, protocolId) {
|
|
107
111
|
if (this.registeredNodes.has(node)) {
|
|
108
112
|
log('Node already registered');
|
|
109
113
|
return;
|
|
110
114
|
}
|
|
111
|
-
this.listener.register(node, protocolId ?? this.config.protocolId);
|
|
115
|
+
await this.listener.register(node, protocolId ?? this.config.protocolId);
|
|
112
116
|
this.registeredNodes.add(node);
|
|
113
117
|
log('Registered as responder on node');
|
|
114
118
|
}
|
|
115
119
|
/**
|
|
116
120
|
* Unregister the protocol handler from a libp2p node.
|
|
117
121
|
*/
|
|
118
|
-
unregisterResponder(node, protocolId) {
|
|
122
|
+
async unregisterResponder(node, protocolId) {
|
|
119
123
|
if (!this.registeredNodes.has(node)) {
|
|
120
124
|
return;
|
|
121
125
|
}
|
|
122
|
-
this.listener.unregister(node, protocolId ?? this.config.protocolId);
|
|
126
|
+
await this.listener.unregister(node, protocolId ?? this.config.protocolId);
|
|
123
127
|
this.registeredNodes.delete(node);
|
|
124
128
|
log('Unregistered from node');
|
|
125
129
|
}
|
|
@@ -149,8 +153,9 @@ export class StrandFormationManager {
|
|
|
149
153
|
contact,
|
|
150
154
|
responderAddrs: invitation.bootstrap,
|
|
151
155
|
validateResponse: (response) => this.validateResponse(invitation, disclosure, response),
|
|
156
|
+
linkRoundTripMs: this.config.linkRoundTripMs,
|
|
152
157
|
sessionTimeoutMs: this.config.sessionTimeoutMs,
|
|
153
|
-
|
|
158
|
+
dialTimeoutMs: this.config.dialTimeoutMs,
|
|
154
159
|
provisionTimeoutMs: this.initiatorProvisionTimeoutMs(),
|
|
155
160
|
protocolId: this.config.protocolId
|
|
156
161
|
});
|
|
@@ -200,16 +205,19 @@ export class StrandFormationManager {
|
|
|
200
205
|
}
|
|
201
206
|
/**
|
|
202
207
|
* Derive the initiator's await-response budget from the configured RESPONDER budget —
|
|
203
|
-
* never the same number (see `StrandFormationManagerConfig.provisionTimeoutMs`)
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
208
|
+
* never the same number (see `StrandFormationManagerConfig.provisionTimeoutMs`): the
|
|
209
|
+
* configured value plus the travel margin the ladder derives at this machine's link.
|
|
210
|
+
* Mirrors `resolveProvisionTimeoutMs`'s own "`0`/negative means unset" rule so an unset
|
|
211
|
+
* config still lets both sides fall back to their own derived defaults; must NOT
|
|
212
|
+
* reproduce the derived default here, or the per-role clamping downstream is defeated.
|
|
207
213
|
* A value too large for the session is clamped per role, and the responder's ceiling holds
|
|
208
|
-
* the
|
|
214
|
+
* the margin back, so the ordering survives there too.
|
|
209
215
|
*/
|
|
210
216
|
initiatorProvisionTimeoutMs() {
|
|
211
217
|
const host = this.config.provisionTimeoutMs;
|
|
212
|
-
return host && host > 0
|
|
218
|
+
return host && host > 0
|
|
219
|
+
? host + formationDeadlines(this.config.linkRoundTripMs).responseTravelMarginMs
|
|
220
|
+
: undefined;
|
|
213
221
|
}
|
|
214
222
|
// ── Responder-side hooks ─────────────────────────────────────────────────────
|
|
215
223
|
async validateToken(token) {
|
|
@@ -241,14 +249,16 @@ export class StrandFormationManager {
|
|
|
241
249
|
* {@link ResponderProvisionOutcome} with `approved: false` — `runSession` turns that
|
|
242
250
|
* into a clean, non-disclosing reply instead of a dropped result frame.
|
|
243
251
|
*
|
|
244
|
-
* - **bound** (host strand present): provision-then-record
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
+
* - **bound** (host strand present): provision-then-record, in three steps —
|
|
253
|
+
* (1) authorize ({@link authorizeBoundUsage}: the outside approval when the invite
|
|
254
|
+
* demands one, and a seat pre-check), so a refused join writes nothing into the host
|
|
255
|
+
* strand; (2) issue the joiner's single-use strand membership invitation via the wired
|
|
256
|
+
* `issueMembershipInvite` seam ({@link issueBoundMembershipInvite}; a closed strand whose
|
|
257
|
+
* invitation cannot be issued rejects retryably HERE, before any consent row spends the
|
|
258
|
+
* token); (3) write the single `FormationUsage` consent row against the pre-existing
|
|
259
|
+
* strand (record-only) and return it + its membership key + the invitation (all
|
|
260
|
+
* read-gating secrets disclosed only here, behind the token + disclosure validation
|
|
261
|
+
* `runSession` already enforced).
|
|
252
262
|
* - **missing** (invite names a host strand absent on this responder, e.g. unconverged):
|
|
253
263
|
* reject cleanly + retryably, writing NO usage row — recording usage here would fail the
|
|
254
264
|
* deferred `StrandExists` CHECK at commit and drop the frame.
|
|
@@ -284,18 +294,8 @@ export class StrandFormationManager {
|
|
|
284
294
|
try {
|
|
285
295
|
switch (resolved.kind) {
|
|
286
296
|
case 'bound': {
|
|
287
|
-
// Issued BEFORE the consent row is recorded, so an issue failure rejects with
|
|
288
|
-
// the formation token still unspent (retryable). The inverse window — invite
|
|
289
|
-
// issued, then recordUsage fails/aborts — orphans a live `Strand.Invite` no
|
|
290
|
-
// joiner ever received; bounded deliberately by its expiry
|
|
291
|
-
// ({@link MEMBERSHIP_INVITE_TTL_MS}) rather than compensated, since nothing
|
|
292
|
-
// here can atomically un-issue a strand-DB row.
|
|
293
|
-
const issued = await this.issueBoundMembershipInvite(token, resolved.strandId);
|
|
294
|
-
if (!issued.ok) {
|
|
295
|
-
return { approved: false, reason: issued.reason };
|
|
296
|
-
}
|
|
297
297
|
// recorder is guaranteed non-null here: only resolveStrand can yield 'bound'.
|
|
298
|
-
await
|
|
298
|
+
const authorized = await this.authorizeBoundUsage(recorder, {
|
|
299
299
|
token,
|
|
300
300
|
peerKey: contact.peerKey,
|
|
301
301
|
peerSignature: contact.peerSignature,
|
|
@@ -304,6 +304,19 @@ export class StrandFormationManager {
|
|
|
304
304
|
disclosure: disclosureText,
|
|
305
305
|
signal
|
|
306
306
|
});
|
|
307
|
+
// Issued only once authorized (a refused join writes nothing into the strand) and
|
|
308
|
+
// BEFORE consent is recorded (an issue failure leaves the token unspent, retryable).
|
|
309
|
+
// The remaining window — invite issued, then record() fails or aborts (a write that
|
|
310
|
+
// exhausted its retries, an abort, or the same-node seat race noted at
|
|
311
|
+
// `ControlFormationUsageRecorder.assertSeatFree`) — orphans a
|
|
312
|
+
// live `Strand.Invite` no joiner ever received; bounded deliberately by its expiry
|
|
313
|
+
// ({@link MEMBERSHIP_INVITE_TTL_MS}) rather than compensated, since nothing
|
|
314
|
+
// here can atomically un-issue a strand-DB row.
|
|
315
|
+
const issued = await this.issueBoundMembershipInvite(token, resolved.strandId, signal);
|
|
316
|
+
if (!issued.ok) {
|
|
317
|
+
return { approved: false, reason: issued.reason };
|
|
318
|
+
}
|
|
319
|
+
await authorized.record();
|
|
307
320
|
return this.approve({
|
|
308
321
|
strand: { strandId: resolved.strandId, createdBy: 'responder' },
|
|
309
322
|
memberPrivateKey: resolved.memberPrivateKey ?? undefined,
|
|
@@ -349,15 +362,28 @@ export class StrandFormationManager {
|
|
|
349
362
|
return { approved: false, reason: 'Formation conflict, retry' };
|
|
350
363
|
}
|
|
351
364
|
}
|
|
365
|
+
/**
|
|
366
|
+
* Authorize a BOUND redemption without writing it, through the recorder's optional
|
|
367
|
+
* {@link FormationUsageRecorder.authorizeUsage}. A recorder without it has nothing to ask up
|
|
368
|
+
* front, so its handle defers everything to `recordUsage`.
|
|
369
|
+
*/
|
|
370
|
+
async authorizeBoundUsage(recorder, params) {
|
|
371
|
+
if (recorder.authorizeUsage) {
|
|
372
|
+
return await recorder.authorizeUsage(params);
|
|
373
|
+
}
|
|
374
|
+
return { record: () => recorder.recordUsage(params) };
|
|
375
|
+
}
|
|
352
376
|
/**
|
|
353
377
|
* Issue the joiner's membership invitation for a BOUND redemption via the wired
|
|
354
|
-
* {@link StrandFormationManagerOptions.issueMembershipInvite} seam.
|
|
378
|
+
* {@link StrandFormationManagerOptions.issueMembershipInvite} seam. Runs after the
|
|
379
|
+
* redemption is authorized ({@link authorizeBoundUsage}) and before consent is recorded.
|
|
355
380
|
*
|
|
356
381
|
* - Hook unwired (mock/transport tests): approve with no invitation, the same posture
|
|
357
382
|
* as an unwired `resolveStrandAddrs`.
|
|
358
383
|
* - Hook returns an invitation (closed host strand): carry it on the approval.
|
|
359
384
|
* - Hook returns `null` (open host strand): approve with no invitation.
|
|
360
|
-
* - Hook throws (runtime not live
|
|
385
|
+
* - Hook throws (runtime not live — including a hibernating one whose wake outran
|
|
386
|
+
* `signal` — no party key, strand-DB write rejected): report
|
|
361
387
|
* `ok: false` with {@link MEMBERSHIP_INVITE_UNAVAILABLE_REASON} — the caller rejects
|
|
362
388
|
* BEFORE any consent row is written, so the formation token stays unspent.
|
|
363
389
|
* - Hook throws `PreSplitStrandIdentityError` (the host strand was founded before the
|
|
@@ -367,12 +393,12 @@ export class StrandFormationManager {
|
|
|
367
393
|
* The LOG-before-reject keeps both a deliberate internal-error→protocol-rejection
|
|
368
394
|
* conversion, same as the catch-all in {@link provisionAsResponder}.
|
|
369
395
|
*/
|
|
370
|
-
async issueBoundMembershipInvite(token, strandId) {
|
|
396
|
+
async issueBoundMembershipInvite(token, strandId, signal) {
|
|
371
397
|
if (!this.issueMembershipInvite) {
|
|
372
398
|
return { ok: true };
|
|
373
399
|
}
|
|
374
400
|
try {
|
|
375
|
-
const invite = await this.issueMembershipInvite(strandId);
|
|
401
|
+
const invite = await this.issueMembershipInvite(strandId, signal);
|
|
376
402
|
return { ok: true, invite: invite ?? undefined };
|
|
377
403
|
}
|
|
378
404
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strand-formation-manager.js","sourceRoot":"","sources":["../src/strand-formation-manager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"strand-formation-manager.js","sourceRoot":"","sources":["../src/strand-formation-manager.ts"],"names":[],"mappings":"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"}
|