@serfab/cadre-core 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +8 -6
  2. package/dist/cadre-node.d.ts +548 -137
  3. package/dist/cadre-node.js +1208 -383
  4. package/dist/cadre-node.js.map +1 -1
  5. package/dist/control-authorization.d.ts +2 -2
  6. package/dist/control-authorization.js +1 -0
  7. package/dist/control-authorization.js.map +1 -1
  8. package/dist/control-cohort.d.ts +6 -0
  9. package/dist/control-cohort.js +6 -0
  10. package/dist/control-cohort.js.map +1 -1
  11. package/dist/control-database.d.ts +46 -8
  12. package/dist/control-database.js +97 -18
  13. package/dist/control-database.js.map +1 -1
  14. package/dist/control-formation-recorder.d.ts +37 -14
  15. package/dist/control-formation-recorder.js +60 -10
  16. package/dist/control-formation-recorder.js.map +1 -1
  17. package/dist/control-read-retry.d.ts +13 -12
  18. package/dist/control-read-retry.js +14 -12
  19. package/dist/control-read-retry.js.map +1 -1
  20. package/dist/control-schema.d.ts +1 -1
  21. package/dist/control-schema.js +67 -5
  22. package/dist/control-schema.js.map +1 -1
  23. package/dist/control-stream.d.ts +9 -1
  24. package/dist/control-stream.js +24 -1
  25. package/dist/control-stream.js.map +1 -1
  26. package/dist/control-write-retry.d.ts +12 -2
  27. package/dist/control-write-retry.js +13 -2
  28. package/dist/control-write-retry.js.map +1 -1
  29. package/dist/delegate-admission.d.ts +11 -8
  30. package/dist/delegate-admission.js +19 -11
  31. package/dist/delegate-admission.js.map +1 -1
  32. package/dist/diagnostics/connection-path.d.ts +0 -7
  33. package/dist/diagnostics/connection-path.js +0 -7
  34. package/dist/diagnostics/connection-path.js.map +1 -1
  35. package/dist/formation-approval.d.ts +7 -0
  36. package/dist/formation-approval.js +9 -3
  37. package/dist/formation-approval.js.map +1 -1
  38. package/dist/fs-atomic.d.ts +11 -2
  39. package/dist/fs-atomic.js +13 -3
  40. package/dist/fs-atomic.js.map +1 -1
  41. package/dist/hibernation-manager.d.ts +111 -8
  42. package/dist/hibernation-manager.js +234 -49
  43. package/dist/hibernation-manager.js.map +1 -1
  44. package/dist/index.d.ts +13 -6
  45. package/dist/index.js +27 -5
  46. package/dist/index.js.map +1 -1
  47. package/dist/joined-strand-store.d.ts +177 -0
  48. package/dist/joined-strand-store.js +431 -0
  49. package/dist/joined-strand-store.js.map +1 -0
  50. package/dist/key-store-file.js +14 -5
  51. package/dist/key-store-file.js.map +1 -1
  52. package/dist/key-store.d.ts +6 -0
  53. package/dist/key-store.js.map +1 -1
  54. package/dist/link-budget.d.ts +367 -69
  55. package/dist/link-budget.js +375 -72
  56. package/dist/link-budget.js.map +1 -1
  57. package/dist/membership-connection-gater.d.ts +30 -43
  58. package/dist/membership-connection-gater.js +31 -42
  59. package/dist/membership-connection-gater.js.map +1 -1
  60. package/dist/node-local-snapshot.d.ts +5 -4
  61. package/dist/node-local-snapshot.js +6 -3
  62. package/dist/node-local-snapshot.js.map +1 -1
  63. package/dist/peer-dial.d.ts +24 -4
  64. package/dist/peer-dial.js +74 -5
  65. package/dist/peer-dial.js.map +1 -1
  66. package/dist/peer-join-backfill.d.ts +35 -15
  67. package/dist/peer-join-backfill.js +115 -55
  68. package/dist/peer-join-backfill.js.map +1 -1
  69. package/dist/push-fanout.d.ts +6 -0
  70. package/dist/push-fanout.js +6 -0
  71. package/dist/push-fanout.js.map +1 -1
  72. package/dist/relay-reservation.d.ts +3 -1
  73. package/dist/relay-reservation.js +3 -1
  74. package/dist/relay-reservation.js.map +1 -1
  75. package/dist/relay-server.d.ts +79 -0
  76. package/dist/relay-server.js +74 -0
  77. package/dist/relay-server.js.map +1 -0
  78. package/dist/seed-bootstrap.d.ts +57 -4
  79. package/dist/seed-bootstrap.js +107 -83
  80. package/dist/seed-bootstrap.js.map +1 -1
  81. package/dist/storage-scope.d.ts +33 -17
  82. package/dist/storage-scope.js +44 -23
  83. package/dist/storage-scope.js.map +1 -1
  84. package/dist/strand-addr-protocol.d.ts +58 -21
  85. package/dist/strand-addr-protocol.js +133 -85
  86. package/dist/strand-addr-protocol.js.map +1 -1
  87. package/dist/strand-database.d.ts +20 -2
  88. package/dist/strand-database.js +42 -5
  89. package/dist/strand-database.js.map +1 -1
  90. package/dist/strand-first-sync-gate.d.ts +59 -21
  91. package/dist/strand-first-sync-gate.js +58 -19
  92. package/dist/strand-first-sync-gate.js.map +1 -1
  93. package/dist/strand-formation-deadlines.d.ts +151 -0
  94. package/dist/strand-formation-deadlines.js +171 -0
  95. package/dist/strand-formation-deadlines.js.map +1 -0
  96. package/dist/strand-formation-manager.d.ts +63 -30
  97. package/dist/strand-formation-manager.js +67 -41
  98. package/dist/strand-formation-manager.js.map +1 -1
  99. package/dist/strand-formation-protocol.d.ts +45 -35
  100. package/dist/strand-formation-protocol.js +59 -122
  101. package/dist/strand-formation-protocol.js.map +1 -1
  102. package/dist/strand-instance-manager.d.ts +152 -6
  103. package/dist/strand-instance-manager.js +331 -42
  104. package/dist/strand-instance-manager.js.map +1 -1
  105. package/dist/strand-membership-writer.d.ts +6 -0
  106. package/dist/strand-membership-writer.js +11 -0
  107. package/dist/strand-membership-writer.js.map +1 -1
  108. package/dist/strand-peer-book-file.d.ts +12 -0
  109. package/dist/strand-peer-book-file.js +37 -0
  110. package/dist/strand-peer-book-file.js.map +1 -0
  111. package/dist/strand-peer-book-protocol.d.ts +168 -0
  112. package/dist/strand-peer-book-protocol.js +356 -0
  113. package/dist/strand-peer-book-protocol.js.map +1 -0
  114. package/dist/strand-peer-book-swap.d.ts +104 -0
  115. package/dist/strand-peer-book-swap.js +284 -0
  116. package/dist/strand-peer-book-swap.js.map +1 -0
  117. package/dist/strand-peer-book.d.ts +159 -0
  118. package/dist/strand-peer-book.js +361 -0
  119. package/dist/strand-peer-book.js.map +1 -0
  120. package/dist/strand-peer-observer.d.ts +88 -0
  121. package/dist/strand-peer-observer.js +180 -0
  122. package/dist/strand-peer-observer.js.map +1 -0
  123. package/dist/strand-revocation-enforcer.js +2 -1
  124. package/dist/strand-revocation-enforcer.js.map +1 -1
  125. package/dist/strand-solicitation.d.ts +36 -20
  126. package/dist/strand-solicitation.js +4 -4
  127. package/dist/strand-solicitation.js.map +1 -1
  128. package/dist/strand-wake-protocol.d.ts +80 -23
  129. package/dist/strand-wake-protocol.js +89 -64
  130. package/dist/strand-wake-protocol.js.map +1 -1
  131. package/dist/types.d.ts +181 -33
  132. package/dist/types.js +4 -3
  133. package/dist/types.js.map +1 -1
  134. package/package.json +11 -7
  135. package/src/cadre-node.ts +1316 -398
  136. package/src/control-authorization.ts +2 -1
  137. package/src/control-cohort.ts +6 -0
  138. package/src/control-database.ts +122 -18
  139. package/src/control-formation-recorder.ts +354 -305
  140. package/src/control-read-retry.ts +14 -12
  141. package/src/control-schema.ts +67 -5
  142. package/src/control-stream.ts +25 -1
  143. package/src/control-write-retry.ts +13 -2
  144. package/src/delegate-admission.ts +23 -13
  145. package/src/diagnostics/connection-path.ts +0 -7
  146. package/src/formation-approval.ts +610 -604
  147. package/src/fs-atomic.ts +14 -4
  148. package/src/hibernation-manager.ts +638 -437
  149. package/src/index.ts +91 -6
  150. package/src/joined-strand-store.ts +498 -0
  151. package/src/key-store-file.ts +14 -5
  152. package/src/key-store.ts +6 -0
  153. package/src/link-budget.ts +393 -74
  154. package/src/membership-connection-gater.ts +31 -45
  155. package/src/node-local-snapshot.ts +293 -289
  156. package/src/peer-dial.ts +81 -7
  157. package/src/peer-join-backfill.ts +120 -57
  158. package/src/push-fanout.ts +6 -0
  159. package/src/relay-reservation.ts +3 -1
  160. package/src/relay-server.ts +98 -0
  161. package/src/seed-bootstrap.ts +133 -91
  162. package/src/storage-scope.ts +44 -23
  163. package/src/strand-addr-protocol.ts +547 -458
  164. package/src/strand-database.ts +287 -242
  165. package/src/strand-first-sync-gate.ts +58 -19
  166. package/src/strand-formation-deadlines.ts +227 -0
  167. package/src/strand-formation-manager.ts +700 -647
  168. package/src/strand-formation-protocol.ts +103 -150
  169. package/src/strand-instance-manager.ts +387 -45
  170. package/src/strand-membership-writer.ts +12 -0
  171. package/src/strand-peer-book-file.ts +39 -0
  172. package/src/strand-peer-book-protocol.ts +466 -0
  173. package/src/strand-peer-book-swap.ts +338 -0
  174. package/src/strand-peer-book.ts +475 -0
  175. package/src/strand-peer-observer.ts +235 -0
  176. package/src/strand-revocation-enforcer.ts +2 -1
  177. package/src/strand-solicitation.ts +519 -500
  178. package/src/strand-wake-protocol.ts +401 -355
  179. package/src/types.ts +185 -33
@@ -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, no party identity key yet, or the strand DB refusing the `Strand.Invite`
18
- * write. Retryable on purpose, and rejected BEFORE the consent row is recorded, so the
19
- * formation token stays unspent: approving without an invitation would admit a joiner
20
- * that looks joined but can never become a member, and a responder not running the
21
- * strand cannot serve the joiner's sync anyway. The one permanent failure,
22
- * a pre-split host strand, gets {@link HOST_STRAND_MUST_BE_RECREATED_REASON} instead.
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
- /** Session timeout in milliseconds */
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
- /** Step timeout in milliseconds */
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
- * `PROVISION_RESPONSE_TRAVEL_MARGIN_MS` (`strand-formation-protocol.ts`) — never set
46
- * directly — so the ordering documented there (approval hook < responder provisioning <
47
- * initiator await-response < session) cannot collapse when this is configured.
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?: (strandId: string) => Promise<StrandMembershipInvite | null>;
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`). Mirrors
175
- * `resolveProvisionTimeoutMs`'s own "`0`/negative means unset" rule so an unset config
176
- * still lets both sides fall back to their own independent defaults; must NOT hardcode
177
- * `DEFAULT_PROVISION_TIMEOUT_MS` here, or the per-role clamping downstream is defeated.
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 same margin back, so the ordering survives there too.
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 — first issue the joiner's
191
- * single-use strand membership invitation via the wired `issueMembershipInvite` seam
192
- * ({@link issueBoundMembershipInvite}; a closed strand whose invitation cannot be
193
- * issued rejects retryably HERE, before any consent row spends the token), then write
194
- * the single `FormationUsage` consent row against the pre-existing strand
195
- * (record-only) and return it + its membership key + the invitation (all read-gating
196
- * secrets disclosed only here, behind the token + disclosure validation `runSession`
197
- * already enforced).
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, no party key, strand-DB write rejected): report
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, PROVISION_RESPONSE_TRAVEL_MARGIN_MS, dialFormation, isValidResponderCreatesResult, isWellFormedMembershipInvite } from './strand-formation-protocol.js';
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, no party identity key yet, or the strand DB refusing the `Strand.Invite`
32
- * write. Retryable on purpose, and rejected BEFORE the consent row is recorded, so the
33
- * formation token stays unspent: approving without an invitation would admit a joiner
34
- * that looks joined but can never become a member, and a responder not running the
35
- * strand cannot serve the joiner's sync anyway. The one permanent failure,
36
- * a pre-split host strand, gets {@link HOST_STRAND_MUST_BE_RECREATED_REASON} instead.
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
- stepTimeoutMs: this.config.stepTimeoutMs,
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`). Mirrors
204
- * `resolveProvisionTimeoutMs`'s own "`0`/negative means unset" rule so an unset config
205
- * still lets both sides fall back to their own independent defaults; must NOT hardcode
206
- * `DEFAULT_PROVISION_TIMEOUT_MS` here, or the per-role clamping downstream is defeated.
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 same margin back, so the ordering survives there too.
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 ? host + PROVISION_RESPONSE_TRAVEL_MARGIN_MS : undefined;
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 — first issue the joiner's
245
- * single-use strand membership invitation via the wired `issueMembershipInvite` seam
246
- * ({@link issueBoundMembershipInvite}; a closed strand whose invitation cannot be
247
- * issued rejects retryably HERE, before any consent row spends the token), then write
248
- * the single `FormationUsage` consent row against the pre-existing strand
249
- * (record-only) and return it + its membership key + the invitation (all read-gating
250
- * secrets disclosed only here, behind the token + disclosure validation `runSession`
251
- * already enforced).
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 recorder.recordUsage({
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, no party key, strand-DB write rejected): report
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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"}
@@ -29,22 +29,6 @@ export declare const FORMATION_PROTOCOL = "/sereus/formation/1.0.0";
29
29
  * from a non-racing latecomer, so the two sites must never drift apart.
30
30
  */
31
31
  export declare const INVALID_TOKEN_REASON = "Invalid token";
32
- /**
33
- * Wire-latency margin (ms) added to the responder's provisioning budget to get the
34
- * initiator's await-response budget — the travel time for the result frame to come back
35
- * after the responder finishes (see {@link DEFAULT_PROVISION_TIMEOUT_MS}).
36
- * `StrandFormationManager` reuses this constant so a CONFIGURED budget preserves the same
37
- * margin the defaults do, instead of applying the same number to both sides and racing the
38
- * initiator's own timeout against the responder's clean rejection reply. The responder's
39
- * clamp ({@link provisionCeilingMs}) holds the same margin back, so the ordering survives a
40
- * budget large enough that BOTH roles get clamped.
41
- *
42
- * NOTE: 3 s is a fixed assumption about how long the result frame takes to travel back. If
43
- * formation ever runs over paths where that frame can take longer (a slow circuit relay, a
44
- * congested mobile link), the margin is too thin and the initiator's timeout races the
45
- * responder's reply again — raise it, or derive it from an observed round-trip.
46
- */
47
- export declare const PROVISION_RESPONSE_TRAVEL_MARGIN_MS = 3000;
48
32
  /**
49
33
  * Cap on the strand-network addresses a formation result carries
50
34
  * ({@link FormationResultMessage.strandAddrs}). A node's own strand multiaddrs are a
@@ -226,14 +210,22 @@ export interface FormationListenerOptions {
226
210
  * per-strand address lookup.
227
211
  */
228
212
  resolveStrandAddrs?(strandId: string): string[];
213
+ /**
214
+ * This machine's declared link round trip (`NetworkConfig.linkRoundTripMs`), from which
215
+ * every deadline below takes its default ({@link formationDeadlines}). The default
216
+ * declaration when omitted.
217
+ */
218
+ linkRoundTripMs?: number;
219
+ /** Whole-session budget; default `sessionMs` of the derived ladder. */
229
220
  sessionTimeoutMs?: number;
221
+ /** Budget for the contact-frame read; default `awaitContactMs` of the derived ladder. */
230
222
  stepTimeoutMs?: number;
231
223
  /**
232
- * Budget for the `provisionStrand` hook call — distinct from `stepTimeoutMs` because
233
- * provisioning is real work, not a bare wire read/write. Default 12 s; `0`/unset uses
234
- * the default; a value that would outlive the session is clamped ({@link
235
- * provisionCeilingMs}). See {@link DEFAULT_PROVISION_TIMEOUT_MS} for the full ordering
236
- * rationale.
224
+ * Budget for the `provisionStrand` hook call, work plus settle grace — distinct from
225
+ * `stepTimeoutMs` because provisioning is real work, not a bare wire read. Default
226
+ * `provisionWorkMs + provisionGraceMs` of the derived ladder (171 s at the default
227
+ * declaration); `0`/unset uses the default; a value that would outlive the session is
228
+ * clamped ({@link resolveProvisionTimeoutMs}). See {@link formationDeadlines} for the ordering.
237
229
  */
238
230
  provisionTimeoutMs?: number;
239
231
  maxConcurrentSessions?: number;
@@ -247,7 +239,7 @@ export interface FormationListenerOptions {
247
239
  export declare class FormationListener {
248
240
  private readonly options;
249
241
  private readonly sessionTimeoutMs;
250
- private readonly stepTimeoutMs;
242
+ private readonly awaitContactMs;
251
243
  private readonly provisionWorkMs;
252
244
  private readonly provisionGraceMs;
253
245
  private readonly maxConcurrentSessions;
@@ -257,12 +249,13 @@ export declare class FormationListener {
257
249
  constructor(options: FormationListenerOptions);
258
250
  /** Number of in-flight inbound sessions. */
259
251
  get activeCount(): number;
260
- register(node: Libp2p, protocolId?: string): void;
261
- unregister(node: Libp2p, protocolId?: string): void;
252
+ /** Register the formation handler on `node`. Rejects when libp2p refuses the registration. */
253
+ register(node: Libp2p, protocolId?: string): Promise<void>;
254
+ unregister(node: Libp2p, protocolId?: string): Promise<void>;
262
255
  private handleStream;
263
256
  /**
264
- * Run the provisioning hook under its WORK budget — the configured provisioning budget minus
265
- * the trailing settle grace ({@link splitProvisionBudget}, {@link PROVISION_SETTLE_GRACE_MS}).
257
+ * Run the provisioning hook under its WORK budget — the provisioning budget minus the
258
+ * trailing settle grace ({@link splitProvisionBudget}).
266
259
  *
267
260
  * When the work budget expires the hook's signal is aborted, then
268
261
  * {@link settleWithinGrace} waits out the grace for the aborted work to settle anyway.
@@ -282,11 +275,16 @@ export declare class FormationListener {
282
275
  * inside the grace its outcome is ADOPTED — the joiner is told the truth (approved, or the
283
276
  * hook's own rejection reason) rather than "timed out" over a spent invite.
284
277
  *
285
- * NOTE: one window stays open — a work budget that expires after the `FormationUsage`
286
- * insert was issued AND a commit that outlasts the grace. The joiner is told 'timed out'
287
- * while its one-time invite is in fact spent, and since every retry mints a fresh keypair
288
- * no recovery path can match it. Nothing can un-spend an append-only row, so the late-settle
289
- * logging below is the observability for it; widen the grace only if it is seen in the wild.
278
+ * The grace is derived to contain one seat read plus one commit at the declared link
279
+ * ({@link formationDeadlines}), which is exactly what runs after the insert attempt passes
280
+ * its abort check, so at that link the late outcome lands inside it.
281
+ *
282
+ * NOTE: a commit that outlasts even the derived grace (a link slower than declared, or a
283
+ * configured `provisionTimeoutMs` whose half-cap shrank the grace) still tells the joiner
284
+ * 'timed out' while its one-time invite is in fact spent, and since every retry mints a
285
+ * fresh keypair no recovery path can match it. Nothing can un-spend an append-only row, so
286
+ * the late-settle logging below is the observability for it; if it is seen in the wild,
287
+ * raise the declared link rather than this grace.
290
288
  */
291
289
  private settleWithinGrace;
292
290
  /**
@@ -319,12 +317,24 @@ export interface FormationDialOptions {
319
317
  responderAddrs: string[];
320
318
  /** Validate the responder's result; a false return aborts the formation. */
321
319
  validateResponse(response: FormationResultMessage): Promise<boolean>;
320
+ /**
321
+ * This machine's declared link round trip (`NetworkConfig.linkRoundTripMs`), from which
322
+ * every deadline below takes its default ({@link formationDeadlines}). The default
323
+ * declaration when omitted.
324
+ */
325
+ linkRoundTripMs?: number;
326
+ /** Whole-session budget; default `sessionMs` of the derived ladder. */
322
327
  sessionTimeoutMs?: number;
323
- stepTimeoutMs?: number;
324
328
  /**
325
- * Budget for the `await-response` read only (the responder's provisioning + reply travel
326
- * time) — `dial-connect` keeps using `stepTimeoutMs`. Default 15 s; `0`/unset uses the
327
- * default. See {@link DEFAULT_PROVISION_TIMEOUT_MS} for the full ordering rationale.
329
+ * Budget for `dial-connect`: opening the connection, through a relay if need be, and
330
+ * negotiating the formation protocol. Default `dialMs` of the derived ladder.
331
+ */
332
+ dialTimeoutMs?: number;
333
+ /**
334
+ * Budget for the `await-response` read only (the responder's provisioning plus the reply's
335
+ * travel time). Default `initiatorAwaitResponseMs` of the derived ladder; `0`/unset uses
336
+ * the default; a value that would outlive the session is clamped. See
337
+ * {@link formationDeadlines} for the ordering.
328
338
  */
329
339
  provisionTimeoutMs?: number;
330
340
  protocolId?: string;