@serfab/cadre-core 1.13.0 → 1.15.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 (230) hide show
  1. package/README.md +293 -274
  2. package/dist/cadre-invite-protocol.d.ts +383 -0
  3. package/dist/cadre-invite-protocol.js +774 -0
  4. package/dist/cadre-invite-protocol.js.map +1 -0
  5. package/dist/cadre-join-request.d.ts +42 -0
  6. package/dist/cadre-join-request.js +144 -0
  7. package/dist/cadre-join-request.js.map +1 -0
  8. package/dist/cadre-node.d.ts +849 -210
  9. package/dist/cadre-node.js +1574 -374
  10. package/dist/cadre-node.js.map +1 -1
  11. package/dist/claim-proof.d.ts +45 -0
  12. package/dist/claim-proof.js +132 -0
  13. package/dist/claim-proof.js.map +1 -0
  14. package/dist/control-authorization.d.ts +80 -19
  15. package/dist/control-authorization.js +55 -13
  16. package/dist/control-authorization.js.map +1 -1
  17. package/dist/control-cohort.js +1 -1
  18. package/dist/control-cohort.js.map +1 -1
  19. package/dist/control-database.d.ts +605 -108
  20. package/dist/control-database.js +1299 -280
  21. package/dist/control-database.js.map +1 -1
  22. package/dist/control-protocol-guard.d.ts +142 -0
  23. package/dist/control-protocol-guard.js +293 -0
  24. package/dist/control-protocol-guard.js.map +1 -0
  25. package/dist/control-schema.d.ts +1 -1
  26. package/dist/control-schema.js +817 -1067
  27. package/dist/control-schema.js.map +1 -1
  28. package/dist/control-stream.d.ts +4 -0
  29. package/dist/control-stream.js +22 -7
  30. package/dist/control-stream.js.map +1 -1
  31. package/dist/delegate-admission.d.ts +1 -1
  32. package/dist/delegate-admission.js +1 -1
  33. package/dist/device-token.d.ts +11 -9
  34. package/dist/device-token.js +14 -12
  35. package/dist/device-token.js.map +1 -1
  36. package/dist/ed25519-key.d.ts +22 -9
  37. package/dist/ed25519-key.js +47 -10
  38. package/dist/ed25519-key.js.map +1 -1
  39. package/dist/fetch-impl.d.ts +12 -0
  40. package/dist/fetch-impl.js +23 -0
  41. package/dist/fetch-impl.js.map +1 -0
  42. package/dist/file-durable-slot.js +2 -1
  43. package/dist/file-durable-slot.js.map +1 -1
  44. package/dist/file-safe-name.d.ts +25 -0
  45. package/dist/file-safe-name.js +29 -0
  46. package/dist/file-safe-name.js.map +1 -0
  47. package/dist/formation-approval.js +5 -11
  48. package/dist/formation-approval.js.map +1 -1
  49. package/dist/fs-atomic.d.ts +0 -19
  50. package/dist/fs-atomic.js +3 -24
  51. package/dist/fs-atomic.js.map +1 -1
  52. package/dist/index.d.ts +22 -10
  53. package/dist/index.js +54 -11
  54. package/dist/index.js.map +1 -1
  55. package/dist/invitation-bootstrap.d.ts +50 -12
  56. package/dist/invitation-bootstrap.js +76 -13
  57. package/dist/invitation-bootstrap.js.map +1 -1
  58. package/dist/joined-strand-store.d.ts +7 -0
  59. package/dist/joined-strand-store.js +9 -0
  60. package/dist/joined-strand-store.js.map +1 -1
  61. package/dist/key-store-file.js +2 -1
  62. package/dist/key-store-file.js.map +1 -1
  63. package/dist/link-budget.d.ts +25 -33
  64. package/dist/link-budget.js +25 -35
  65. package/dist/link-budget.js.map +1 -1
  66. package/dist/machine-removal.d.ts +78 -0
  67. package/dist/machine-removal.js +166 -0
  68. package/dist/machine-removal.js.map +1 -0
  69. package/dist/membership-connection-gater.d.ts +191 -151
  70. package/dist/membership-connection-gater.js +236 -173
  71. package/dist/membership-connection-gater.js.map +1 -1
  72. package/dist/node-claim-payload.d.ts +74 -0
  73. package/dist/node-claim-payload.js +224 -0
  74. package/dist/node-claim-payload.js.map +1 -0
  75. package/dist/node-default-transports.d.ts +27 -0
  76. package/dist/node-default-transports.js +35 -0
  77. package/dist/node-default-transports.js.map +1 -0
  78. package/dist/node-transports.d.ts +30 -0
  79. package/dist/node-transports.js +40 -0
  80. package/dist/node-transports.js.map +1 -0
  81. package/dist/owner-anchor-sync.d.ts +22 -0
  82. package/dist/owner-anchor-sync.js +143 -0
  83. package/dist/owner-anchor-sync.js.map +1 -0
  84. package/dist/peer-authorization.d.ts +113 -18
  85. package/dist/peer-authorization.js +225 -29
  86. package/dist/peer-authorization.js.map +1 -1
  87. package/dist/peer-dial.d.ts +143 -27
  88. package/dist/peer-dial.js +276 -31
  89. package/dist/peer-dial.js.map +1 -1
  90. package/dist/peer-join-backfill.d.ts +26 -2
  91. package/dist/peer-join-backfill.js +60 -12
  92. package/dist/peer-join-backfill.js.map +1 -1
  93. package/dist/peer-record.d.ts +17 -52
  94. package/dist/peer-record.js +20 -58
  95. package/dist/peer-record.js.map +1 -1
  96. package/dist/pending-join-runner.d.ts +66 -58
  97. package/dist/pending-join-runner.js +136 -145
  98. package/dist/pending-join-runner.js.map +1 -1
  99. package/dist/primary-lan-address.d.ts +8 -0
  100. package/dist/primary-lan-address.js +46 -0
  101. package/dist/primary-lan-address.js.map +1 -0
  102. package/dist/provider/client.d.ts +131 -0
  103. package/dist/provider/client.js +226 -0
  104. package/dist/provider/client.js.map +1 -0
  105. package/dist/provider/descriptor.d.ts +41 -0
  106. package/dist/provider/descriptor.js +103 -0
  107. package/dist/provider/descriptor.js.map +1 -0
  108. package/dist/provider/index.d.ts +9 -0
  109. package/dist/provider/index.js +10 -0
  110. package/dist/provider/index.js.map +1 -0
  111. package/dist/provider/oauth.d.ts +125 -0
  112. package/dist/provider/oauth.js +199 -0
  113. package/dist/provider/oauth.js.map +1 -0
  114. package/dist/provider/rent-node.d.ts +101 -0
  115. package/dist/provider/rent-node.js +220 -0
  116. package/dist/provider/rent-node.js.map +1 -0
  117. package/dist/push-fanout.d.ts +8 -2
  118. package/dist/push-fanout.js +8 -2
  119. package/dist/push-fanout.js.map +1 -1
  120. package/dist/relay-addrs.d.ts +9 -4
  121. package/dist/relay-addrs.js +9 -4
  122. package/dist/relay-addrs.js.map +1 -1
  123. package/dist/relay-reservation.d.ts +51 -16
  124. package/dist/relay-reservation.js +107 -24
  125. package/dist/relay-reservation.js.map +1 -1
  126. package/dist/seed-bootstrap.d.ts +165 -123
  127. package/dist/seed-bootstrap.js +313 -275
  128. package/dist/seed-bootstrap.js.map +1 -1
  129. package/dist/seed-trust-policy.d.ts +98 -37
  130. package/dist/seed-trust-policy.js +188 -2
  131. package/dist/seed-trust-policy.js.map +1 -1
  132. package/dist/strand-addr-protocol.d.ts +24 -26
  133. package/dist/strand-addr-protocol.js +19 -26
  134. package/dist/strand-addr-protocol.js.map +1 -1
  135. package/dist/strand-commit-durability.d.ts +54 -0
  136. package/dist/strand-commit-durability.js +74 -0
  137. package/dist/strand-commit-durability.js.map +1 -0
  138. package/dist/strand-database.d.ts +23 -8
  139. package/dist/strand-database.js +41 -13
  140. package/dist/strand-database.js.map +1 -1
  141. package/dist/strand-first-sync-gate.d.ts +7 -1
  142. package/dist/strand-first-sync-gate.js +7 -1
  143. package/dist/strand-first-sync-gate.js.map +1 -1
  144. package/dist/strand-formation-protocol.js +5 -2
  145. package/dist/strand-formation-protocol.js.map +1 -1
  146. package/dist/strand-fret-addrs.d.ts +19 -1
  147. package/dist/strand-fret-addrs.js +27 -9
  148. package/dist/strand-fret-addrs.js.map +1 -1
  149. package/dist/strand-instance-manager.d.ts +81 -19
  150. package/dist/strand-instance-manager.js +216 -105
  151. package/dist/strand-instance-manager.js.map +1 -1
  152. package/dist/strand-move.d.ts +124 -0
  153. package/dist/strand-move.js +438 -0
  154. package/dist/strand-move.js.map +1 -0
  155. package/dist/strand-network-config.js +7 -6
  156. package/dist/strand-network-config.js.map +1 -1
  157. package/dist/strand-peer-redial.d.ts +113 -0
  158. package/dist/strand-peer-redial.js +236 -0
  159. package/dist/strand-peer-redial.js.map +1 -0
  160. package/dist/strand-revocation-enforcer.d.ts +11 -11
  161. package/dist/strand-revocation-enforcer.js +11 -11
  162. package/dist/strand-wake-protocol.d.ts +13 -16
  163. package/dist/strand-wake-protocol.js +23 -27
  164. package/dist/strand-wake-protocol.js.map +1 -1
  165. package/dist/trusted-owner-store.d.ts +35 -5
  166. package/dist/trusted-owner-store.js +50 -8
  167. package/dist/trusted-owner-store.js.map +1 -1
  168. package/dist/types.d.ts +512 -89
  169. package/dist/types.js +10 -0
  170. package/dist/types.js.map +1 -1
  171. package/package.json +19 -10
  172. package/src/cadre-invite-protocol.ts +1052 -0
  173. package/src/cadre-join-request.ts +167 -0
  174. package/src/cadre-node.ts +1703 -386
  175. package/src/claim-proof.ts +147 -0
  176. package/src/control-authorization.ts +203 -117
  177. package/src/control-cohort.ts +1 -1
  178. package/src/control-database.ts +4663 -3453
  179. package/src/control-protocol-guard.ts +348 -0
  180. package/src/control-schema.ts +828 -1078
  181. package/src/control-stream.ts +26 -7
  182. package/src/delegate-admission.ts +1 -1
  183. package/src/device-token.ts +14 -10
  184. package/src/ed25519-key.ts +47 -10
  185. package/src/fetch-impl.ts +23 -0
  186. package/src/file-durable-slot.ts +64 -63
  187. package/src/file-safe-name.ts +32 -0
  188. package/src/formation-approval.ts +604 -610
  189. package/src/fs-atomic.ts +92 -117
  190. package/src/index.ts +789 -648
  191. package/src/invitation-bootstrap.ts +91 -13
  192. package/src/joined-strand-store.ts +508 -498
  193. package/src/key-store-file.ts +142 -141
  194. package/src/link-budget.ts +25 -36
  195. package/src/machine-removal.ts +216 -0
  196. package/src/membership-connection-gater.ts +259 -191
  197. package/src/node-claim-payload.ts +259 -0
  198. package/src/node-default-transports.ts +38 -0
  199. package/src/node-transports.ts +49 -0
  200. package/src/owner-anchor-sync.ts +171 -0
  201. package/src/peer-authorization.ts +258 -29
  202. package/src/peer-dial.ts +604 -315
  203. package/src/peer-join-backfill.ts +62 -11
  204. package/src/peer-record.ts +159 -197
  205. package/src/pending-join-runner.ts +729 -735
  206. package/src/primary-lan-address.ts +47 -0
  207. package/src/provider/client.ts +326 -0
  208. package/src/provider/descriptor.ts +129 -0
  209. package/src/provider/index.ts +59 -0
  210. package/src/provider/oauth.ts +285 -0
  211. package/src/provider/rent-node.ts +275 -0
  212. package/src/push-fanout.ts +8 -2
  213. package/src/relay-addrs.ts +9 -4
  214. package/src/relay-reservation.ts +1211 -1121
  215. package/src/seed-bootstrap.ts +1502 -1448
  216. package/src/seed-trust-policy.ts +353 -140
  217. package/src/strand-addr-protocol.ts +26 -35
  218. package/src/strand-commit-durability.ts +116 -0
  219. package/src/strand-database.ts +46 -14
  220. package/src/strand-first-sync-gate.ts +7 -1
  221. package/src/strand-formation-protocol.ts +1039 -1036
  222. package/src/strand-fret-addrs.ts +179 -145
  223. package/src/strand-instance-manager.ts +2026 -1883
  224. package/src/strand-move.ts +585 -0
  225. package/src/strand-network-config.ts +7 -6
  226. package/src/strand-peer-redial.ts +307 -0
  227. package/src/strand-revocation-enforcer.ts +11 -11
  228. package/src/strand-wake-protocol.ts +23 -30
  229. package/src/trusted-owner-store.ts +242 -171
  230. package/src/types.ts +2687 -2242
@@ -1,121 +1,160 @@
1
1
  /**
2
- * Control-network inbound admission gates (defense-in-depth): the
3
- * encrypted-connection checkpoint and the circuit-relay reservation checkpoint.
4
- *
5
- * Layer 2 of the membership enforcement chain: the PRIMARY gates are per-stream
6
- * — every sensitive sereus control protocol rejects a peer that fails the
7
- * voucher-anchored membership check (wake and strand-addr via
8
- * `CadreNode.isAuthorizedMember`; the Optimystic control-DB protocols via the
9
- * materialized-snapshot gate `CadreNode.authorizeInboundControlStream`), and
10
- * the replicated rows an outsider *can* still write are disbelieved at read
11
- * time. This module adds the opportunistic connection-level layer on top: a
12
- * peer this node can positively determine is NOT authorized is refused at the
13
- * encrypted-connection checkpoint, before any protocol negotiation, so a
14
- * known-nothing outsider is never even in the conversation — EXCEPT on a node
15
- * that runs the circuit-relay server, where the refusal moves to the
16
- * relay-reservation checkpoint instead (see "The relay-reservation seam").
17
- *
18
- * ## The stranger allowlist (the ONE place it is defined)
19
- *
20
- * A libp2p connection gater decides per CONNECTION, before protocols are
21
- * negotiated, so "allow seed, deny repo" cannot be expressed here — instead the
22
- * policy admits a connection whenever a legitimate stranger interaction could be
23
- * riding it, and the per-stream gates take over. The complete set of protocols a
24
- * NOT-yet-authorized peer may legitimately speak on a control node is:
25
- *
26
- * - `/sereus/seed/1.0.0` ({@link SEED_PROTOCOL}) — enrollment seed delivery.
2
+ * Control-network inbound admission gates: the encrypted-connection checkpoint
3
+ * and the circuit-relay reservation checkpoint.
4
+ *
5
+ * The fail-closed layer of the membership enforcement chain is per-stream: the
6
+ * control node's protocol guard (`control-protocol-guard.ts`) refuses a peer that
7
+ * is not an authorized member on every protocol not declared open to strangers,
8
+ * before its handler runs, and the replicated rows an outsider *can* still write
9
+ * are disbelieved at read time. This module is NOT a stranger boundary on an
10
+ * enrolled node — outside the bring-up quiet period it admits every inbound
11
+ * connection. Its jobs are:
12
+ *
13
+ * - the bring-up quiet period (below), the one state in which it denies;
14
+ * - deciding which admitted peers carry a deadline: a peer the policy cannot
15
+ * place is admitted PROVISIONALLY, and its connection is closed at the
16
+ * deadline unless the policy admits it by then (see "Provisional admission");
17
+ * - handing circuit-relay reservations to the reservation policy (see "The
18
+ * relay-reservation seam").
19
+ *
20
+ * Why a stranger's connection is admitted at all: the gate sees only a peer id,
21
+ * after the encrypted handshake and before any protocol, so it cannot tell an
22
+ * outsider from a device carrying a cadre invitation this node has not received
23
+ * yet, or from a sibling whose membership row is still replicating. Refusing
24
+ * would fail those at the connection; admitting costs a mute connection for a
25
+ * bounded time, because the protocol guard refuses it every members-only protocol.
26
+ *
27
+ * ## Admitted outright
28
+ *
29
+ * A peer the policy CAN place gets no deadline. Besides members, configured
30
+ * infrastructure and an un-enrolled node's whole world (empty anchor or empty
31
+ * authorized set), that covers the stranger windows: states in which this node
32
+ * expects a stranger on one of the `stranger-open` protocols declared in
33
+ * `controlProtocolClasses` (`control-protocol-guard.ts`):
34
+ *
35
+ * - `/sereus/seed/1.0.0` — enrollment seed delivery.
27
36
  * An owner dials a brand-new node to seed it (the new node has no members
28
- * yet, so its gate is inert), and an invited phone dials the owner before it
29
- * is authorized (admitted via the enrollment window `CadreNode.createInvite`
30
- * opens). The handler's own trust decision is the anchored seed-trust policy.
31
- * - `/sereus/formation/1.0.0` ({@link FORMATION_PROTOCOL}) — cross-party
37
+ * yet, so it admits everyone outright). The handler's own trust decision is the
38
+ * anchored seed-trust policy — or, on a node started with a claim secret
39
+ * (`CadreNodeConfig.claim`), the claim-secret policy. Such a node is the one
40
+ * stranger-facing state that is NOT "admit the connection and let the
41
+ * per-stream gates sort it out": while it waits to be claimed
42
+ * (`CadreNode.isAwaitingClaim`) its connection is admitted, because the claim
43
+ * seed has to ride one, but its control-DB streams and relay reservations are
44
+ * refused ahead of every admission below, the empty-anchor one included. An
45
+ * unclaimed node has no siblings to replicate from, and one on a public
46
+ * address must not relay for anyone. The claim anchors the owner, after which
47
+ * the ordinary rules apply.
48
+ * - `/sereus/formation/1.0.0` — cross-party
32
49
  * strand formation via open invitations. Stranger-facing BY DESIGN: the
33
50
  * initiator is another party, and its token is only checkable inside the
34
- * protocol. The exemption is therefore keyed on EXPECTATION of a stranger,
35
- * not capability to serve one: stranger denial is suspended only while this
36
- * node has at least one UNEXPIRED, NOT-FULLY-CONSUMED open invitation
37
- * outstanding (`StrandSolicitationService.hasOutstandingInvitation` — the
38
- * tokens this process minted or published, plus any still-redeemable
39
- * `FormationInvite` row the usage recorder can see). Registering the
40
- * responder does NOT suspend it, so every node — each registers one at
41
- * `CadreNode.start` — keeps a live gate. The
51
+ * protocol. The window is keyed on EXPECTATION of a stranger, not capability
52
+ * to serve one: it is open only while this node has at least one UNEXPIRED,
53
+ * NOT-FULLY-CONSUMED open invitation outstanding
54
+ * (`StrandSolicitationService.hasOutstandingInvitation` — the tokens this
55
+ * process minted or published, plus any still-redeemable `FormationInvite`
56
+ * row the usage recorder can see). Registering the responder does NOT open
57
+ * it, so on every node — each registers one at `CadreNode.start` — a stranger
58
+ * with no invitation in play stays on the provisional deadline. The
42
59
  * handler's own trust decision remains the per-token check, which is
43
60
  * strictly finer than this one: a peer admitted here can still be rejected
44
61
  * in-protocol for a bogus or spent token.
62
+ * - `/sereus/cadre-invite/1.0.0` — redemption
63
+ * of a cadre invitation at any member machine. Stranger-facing BY DESIGN:
64
+ * the device is not a member until the redemption writes its row, and its
65
+ * proof of possession (a signature with the invitation's private key) is
66
+ * only checkable inside the protocol. Keyed on expectation, as formation's
67
+ * is: open only while this node holds at least one LIVE `CadreInvite` row
68
+ * (`ControlDatabase.hasLiveCadreInvite`: not withdrawn, unexpired, uses left,
69
+ * issuer still an owner). A member that has not yet received the device's
70
+ * row by replication admits the device provisionally instead, seats the row
71
+ * from the invitation bundle during the redemption, and so admits it at the
72
+ * deadline's re-check.
45
73
  *
46
74
  * There is one further connection-level carve-out, which is NOT a protocol
47
- * exemption and needs no stranger window:
75
+ * window:
48
76
  *
49
77
  * - **Announced delegate peers** (`delegate-admission.ts`). A member's strand
50
78
  * node runs as a separate libp2p identity whose peerId no sibling can
51
79
  * recompute. Before starting a strand node, a member's control node
52
80
  * announces that peerId over the already-authenticated strand-addr RPC, and
53
81
  * the receiver holds a short-lived grant for it
54
- * (`CadreNode.grantDelegateAdmission`). The grant admits the CONNECTION,
55
- * admits the peer's RESERVATION at the seam below (without spending the
56
- * unauthorized budget), and nothing else — it is deliberately invisible to
57
- * the per-stream gate, so a delegate still gets refused on every
82
+ * (`CadreNode.grantDelegateAdmission`). The grant admits the CONNECTION
83
+ * outright, admits the peer's RESERVATION at the seam below (without
84
+ * spending the unauthorized budget), and nothing else — it is deliberately
85
+ * invisible to the protocol guard, so a delegate still gets refused on every
58
86
  * members-only protocol.
59
87
  *
88
+ * ## Provisional admission
89
+ *
90
+ * A peer the policy cannot place (`'admit-provisionally'`) gets its connection
91
+ * and a deadline — {@link PROVISIONAL_ADMISSION_DEADLINE_MS} at the default
92
+ * declaration; `CadreNode` passes the one derived from its OWN declared link,
93
+ * because the member is the machine that decides. At the deadline the gate asks
94
+ * the policy again:
95
+ *
96
+ * - `'admit'` — the peer has since become a member, holds a delegate grant, or
97
+ * this node now holds a live invitation (a redeeming device's row was
98
+ * seated): the connection stays, and nothing is re-armed;
99
+ * - `'admit-provisionally'` — the connection is closed (a bounded graceful
100
+ * close, with an abort only as the escalation);
101
+ * - the question throws or outlasts the decision deadline — the connection
102
+ * stays (see "Fail-open, deliberately").
103
+ *
104
+ * A connection that is already gone by then costs no question. One peer may hold
105
+ * several provisional connections; each deadline re-asks on its own.
106
+ *
107
+ * The gate does not decide which peers this node sends control writes to. A
108
+ * provisionally admitted stranger can open or advertise the party's protocols;
109
+ * what keeps it out of the control-database cohort is the control node's
110
+ * membership predicate (`CadreNode.isControlNetworkMember`, wired as Optimystic's
111
+ * `isNetworkMember`). FRET's ring still counts it: `docs/architecture.md` →
112
+ * "Per-stream protocol guard" → "What it does not cover".
113
+ *
60
114
  * ## The relay-reservation seam
61
115
  *
62
116
  * A circuit-relay reservation is established by the reserving peer DIALING the
63
- * relay, so at the relay it is an inbound connection — and killing that
117
+ * relay, so at the relay it rides an inbound connection — and closing that
64
118
  * connection kills the reservation. For a genuine member whose `CadrePeer` row
65
- * has not yet replicated to this node, a connection-level deny here is NOT
66
- * self-healing the way a data connection's is: an outbound reconcile dial
67
- * re-establishes a data link, but no outbound dial can grant the REMOTE peer a
68
- * reservation, and a relay-only peer has no address of its own to dial back —
69
- * the reservation IS its address. Boot ordering makes the window ordinary (a
70
- * node's circuit listener runs inside `libp2p.start()`, before its own row
71
- * could have replicated anywhere), and a stalled replication makes it
72
- * unbounded. So the relay would be answering a RELAY question ("may this peer
73
- * use my forwarding capacity?") with a MEMBERSHIP answer, at a checkpoint where
74
- * a wrong answer is unrecoverable.
75
- *
76
- * On a node whose relay server is enabled the two questions are separated:
77
- *
78
- * - The policy returns `'admit-for-relay'` instead of `'deny'`, and the
79
- * connection is ADMITTED. The fail-closed per-stream gates still refuse such
80
- * a peer every members-only protocol, so it gains identify/ping and the
81
- * relay hop protocol, nothing else.
82
- * - The reservation itself is decided at libp2p's
83
- * `denyInboundRelayReservation` hook (the circuit-relay server consults it
84
- * per RESERVE request): the policy admits members, delegates and configured
85
- * infra outright, and admits peers it cannot place only within a bounded
86
- * budget ({@link UnauthorizedReservationBudget}) — a member whose row is in
87
- * flight always finds a slot under any sane cap, while outsiders cannot
88
- * annex the party's relay capacity. COUNT and lifetime are the only bounds
89
- * on such a peer: a party-run relay forwards without libp2p's per-connection
90
- * data and duration limit by default (`relay-server.ts`), so what a granted
91
- * slot carries is not capped.
92
- * - An `'admit-for-relay'` connection that is NOT reserving is dropped: it has
93
- * {@link RELAY_ADMISSION_RESERVE_DEADLINE_MS} to get a reservation ADMITTED
94
- * at that hook, after which the gate CLOSES the underlying connection so
95
- * both ends let go of the socket. The guarantee above thus weakens on
96
- * relay-enabled nodes from "never in the conversation" to "in it briefly,
97
- * and can speak nothing".
119
+ * has not yet replicated to this node that would NOT be self-healing the way a
120
+ * data connection's close is: an outbound reconcile dial re-establishes a data
121
+ * link, but no outbound dial can grant the REMOTE peer a reservation, and a
122
+ * relay-only peer has no address of its own to dial back — the reservation IS
123
+ * its address. Boot ordering makes the window ordinary (a node reserves at the
124
+ * end of its own `start()`, before its row could have replicated anywhere), and
125
+ * a stalled replication makes it unbounded. So the reservation is decided on its
126
+ * own terms, not by the connection's:
127
+ *
128
+ * - It is decided at libp2p's `denyInboundRelayReservation` hook (the
129
+ * circuit-relay server consults it per RESERVE request): the policy admits
130
+ * members, delegates and configured infra outright, and admits peers it
131
+ * cannot place only within a bounded budget
132
+ * ({@link UnauthorizedReservationBudget}) — a member whose row is in flight
133
+ * always finds a slot under any sane cap, while outsiders cannot annex the
134
+ * party's relay capacity. COUNT and lifetime are the only bounds on such a
135
+ * peer: a party-run relay forwards without libp2p's per-connection data and
136
+ * duration limit by default (`relay-server.ts`), so what a granted slot
137
+ * carries is not capped.
138
+ * - An ADMITTED reservation disarms every provisional deadline the peer holds
139
+ * here, so its connection outlives the deadline even while the peer is still
140
+ * unplaced. A refused one disarms nothing.
98
141
  *
99
142
  * The deadline clears on reservation ADMISSION, not on the reservation's own
100
143
  * success: this gate cannot observe the server-side `reserve()` outcome, so a
101
144
  * peer whose admitted reservation is then refused for server capacity keeps its
102
145
  * connection until either side closes it — bounded and mute, so harmless.
103
146
  *
104
- * Everything else a control node handles — the Optimystic control-DB protocols
105
- * (`/optimystic/control-<party>/{repo,cluster,sync,block-transfer}/…`), wake
106
- * (`/sereus/strand-wake/1.0.0`), and strand-addr (`/sereus/strand-addr/1.0.0`)
107
- * — is members-only, and every one of them enforces that per-stream. Wake and
108
- * strand-addr check `isAuthorizedMember` inside their handlers; the four
109
- * control-DB protocols are gated by the fail-closed
110
- * `CadreNode.authorizeInboundControlStream` (wired as libp2p's
111
- * `authorizeInboundStream` upstream hook), which judges each inbound stream
112
- * against the MATERIALIZED authorized-peer snapshot — synchronous and
113
- * in-memory, because a live DB read from inside the gate would deadlock into
114
- * mutual denial. The two layers complement, not duplicate: this connection
115
- * gate is fail-open over a live DB read (deny only on positive proof of an
116
- * outsider), the stream gate is fail-closed over the snapshot and has NO
117
- * stranger carve-outs — an enrollment window admits a stranger's connection
118
- * for seed delivery, yet its repo streams are still refused.
147
+ * Everything else a control node serves is either libp2p plumbing open to any
148
+ * connection (identify, ping, hole punching, AutoNAT, the relay protocols) or
149
+ * members-only — wake, strand-addr, the Optimystic control-DB protocols and FRET —
150
+ * and the fail-closed layer for all of it is the protocol guard
151
+ * (`control-protocol-guard.ts`), one seam that wraps every handler at dispatch,
152
+ * with a protocol nobody classed treated as members-only. The two layers
153
+ * complement, not duplicate: this connection gate is fail-open over a live DB
154
+ * read and decides only how long a connection lasts, the protocol guard is
155
+ * fail-closed and has NO stranger carve-outs — a live invitation admits a
156
+ * stranger's connection outright for redemption, yet its repo and FRET streams
157
+ * are still refused.
119
158
  *
120
159
  * ## The bring-up quiet period
121
160
  *
@@ -151,62 +190,54 @@
151
190
  *
152
191
  * ## Fail-open, deliberately
153
192
  *
154
- * Outside that window this layer only ever denies on a POSITIVE determination of
155
- * "unauthorized outsider while no stranger path is open". Any error, missing
156
- * dependency, or ambiguous state admits the connection (and the reservation) and
157
- * defers to the fail-closed stream gates — a DB hiccup must not partition a
158
- * legitimate cadre.
193
+ * Outside that window this layer never denies, and it closes a provisional
194
+ * connection only on a positive answer that the peer is still unplaced. Any
195
+ * error, missing dependency, timeout or ambiguous state admits the connection
196
+ * outright (and the reservation), or keeps a provisional connection at its
197
+ * deadline, and defers to the fail-closed stream gates — a DB hiccup must not
198
+ * partition a legitimate cadre.
159
199
  */
160
200
  import debug from 'debug';
161
- import { SEED_PROTOCOL } from './seed-bootstrap.js';
162
- import { FORMATION_PROTOCOL } from './strand-formation-protocol.js';
163
201
  import { withDeadline } from './control-stream.js';
164
202
  import { PARTY_RELAY_RESERVATION_TTL_MS } from './relay-server.js';
165
- import { ADMISSION_DECISION_TIMEOUT_MS, relayAdmissionReserveDeadlineMs } from './link-budget.js';
203
+ import { ADMISSION_DECISION_TIMEOUT_MS, relayedRequestBudgetMs } from './link-budget.js';
166
204
  const log = debug('sereus:cadre:connection-gater');
167
205
  /**
168
- * The protocols a not-yet-authorized peer may legitimately speak on a control
169
- * node (see the module doc above for why each is open and where its own trust
170
- * decision lives). Exported as the single reference point so the allowlist
171
- * cannot silently drift across modules.
172
- */
173
- export const STRANGER_OPEN_PROTOCOLS = [SEED_PROTOCOL, FORMATION_PROTOCOL];
174
- /**
175
- * How long `CadreNode.createInvite` holds the inbound gate open for strangers
176
- * when the invite carries no explicit expiry: the invitee must dial in before
177
- * it is authorized, and an expiry-less invite gives the gate no bound of its
178
- * own. Redeeming after this window still works once the owner re-mints (or the
179
- * caller re-opens the window via `CadreNode.openEnrollmentWindow`).
180
- */
181
- export const DEFAULT_ENROLLMENT_WINDOW_MS = 30 * 60 * 1000;
182
- /**
183
- * How long an `'admit-for-relay'` connection may exist without a relay
184
- * reservation being ADMITTED at the `denyInboundRelayReservation` hook, after
185
- * which the gate closes the underlying connection. A reserving client asks for
186
- * its slot immediately after the connection upgrades (`relay-reservation.ts`
187
- * dials and requests in one drive; a strand node's configured circuit listener
188
- * does the same from inside its own `listen()`), so a connection idle past this
189
- * deadline is not reserving.
190
- *
191
- * Derived from the link ({@link relayAdmissionReserveDeadlineMs}): one link round trip for the
192
- * request to arrive plus one admission decision on it. This is the value at the default
193
- * declaration; `CadreNode` passes the one derived from the relay's OWN declaration, because the
194
- * relay is the machine that decides.
206
+ * How long a provisionally admitted connection lasts before the gate re-asks the
207
+ * policy and closes it unless the peer is admissible by then (see the module
208
+ * doc's "Provisional admission").
209
+ *
210
+ * {@link relayedRequestBudgetMs}: 28 500 ms at the default declaration. The
211
+ * longest exchange a stranger legitimately starts on a fresh connection is a
212
+ * cadre invitation redemption, and the device abandons each member address after
213
+ * that same budget of its own declared link (`redeemAtMembers`): it covers the
214
+ * dial, the request, the member's catch-up push, the seat and the redemption. So
215
+ * a member never cuts an exchange the device is still waiting on, and a
216
+ * reservation request lands well inside it. This is the value at the default
217
+ * declaration; `CadreNode` passes the one derived from its OWN declaration.
218
+ *
219
+ * NOTE: accepted tradeoff — any stranger can hold a mute connection to any
220
+ * enrolled member for this long, weighed against letting a device redeem an
221
+ * invitation at a member that has not yet received its row (maintainer,
222
+ * 2026-10-07, plan `cadre-invite-redeemable-before-the-row-replicates`). It can
223
+ * open only stranger-open and transport streams (the protocol guard), and
224
+ * libp2p's connection-manager limits bound how many it holds. Revisit if stranger
225
+ * connections show up as load on a member.
195
226
  */
196
- export const RELAY_ADMISSION_RESERVE_DEADLINE_MS = relayAdmissionReserveDeadlineMs();
227
+ export const PROVISIONAL_ADMISSION_DEADLINE_MS = relayedRequestBudgetMs();
197
228
  /**
198
- * Bound on the graceful close of an expired relay-only connection. It exists
229
+ * Bound on the graceful close of an expired provisional connection. It exists
199
230
  * because `AbstractMultiaddrConnection.close()` awaits an `idle`/`drain` event
200
231
  * when the connection still has unsent bytes, and that wait has no timeout of
201
232
  * its own — an unsignalled one never ends. This gate writes nothing to a
202
- * stranger, so the wait is not reachable today; the bound is here so a timer
233
+ * stranger, so the wait is not reachable from here; the bound is here so a timer
203
234
  * callback can never hold an unending await.
204
235
  *
205
236
  * Applied through {@link withDeadline}, not `AbortSignal.timeout`: the latter is
206
237
  * not reliably present on React Native/Hermes, which loads this same module.
207
238
  */
208
239
  // eslint-disable-next-line no-restricted-syntax -- link-independent: bounds a local connection close inside a timer callback, and expiry aborts the connection instead
209
- export const RELAY_ADMISSION_CLOSE_TIMEOUT_MS = 2000;
240
+ export const PROVISIONAL_ADMISSION_CLOSE_TIMEOUT_MS = 2000;
210
241
  /**
211
242
  * Default cap on concurrent relay reservations held by peers the membership
212
243
  * check could not place (see {@link UnauthorizedReservationBudget}). Small on
@@ -293,27 +324,30 @@ export class UnauthorizedReservationBudget {
293
324
  * membership — this node decides for itself who to talk to.
294
325
  *
295
326
  * Composition semantics: every hook of `base` is preserved as-is; on the three
296
- * composed hooks a deny from EITHER the base gater or the admission policy
297
- * denies. A policy error — or a decision slower than `decisionTimeoutMs` —
298
- * takes the fail-open outcome (connection admitted / reservation admitted, see
299
- * module doc); the base gater's verdict is still honored first.
327
+ * composed hooks a deny from the base gater denies, and so does the quiet
328
+ * period. The admission policy never denies a connection. A policy error — or a
329
+ * decision slower than `decisionTimeoutMs` — takes the fail-open outcome
330
+ * (connection admitted outright / reservation admitted, see module doc); the
331
+ * base gater's verdict is still honored first.
300
332
  *
301
- * An `'admit-for-relay'` verdict admits the connection and arms a
302
- * `reserveDeadlineMs` timer against it; the timer is disarmed when a
303
- * reservation for that peer is ADMITTED at the reservation hook, and closes the
304
- * underlying `MultiaddrConnection` when it fires first.
333
+ * An `'admit-provisionally'` verdict admits the connection and arms a
334
+ * `provisionalDeadlineMs` timer against it. When the timer fires the policy is
335
+ * asked again, and the underlying `MultiaddrConnection` is closed unless it now
336
+ * answers `'admit'`; a reservation for that peer ADMITTED at the reservation
337
+ * hook disarms the timer first.
305
338
  *
306
339
  * NOTE: `base` is spread, so a gater passed as a CLASS INSTANCE would lose its
307
340
  * prototype methods; every caller in this repo (and libp2p's own default)
308
341
  * supplies a plain object. If a class-based gater ever shows up, delegate
309
342
  * per-hook instead of spreading.
310
343
  *
311
- * Deny timing, as observed by the denied dialer: noise negotiates the muxer in
312
- * the security handshake's early data, so the DIALER's upgrade may complete
313
- * (its `dial()` resolves) before this receiver-side hook runs. The deny then
314
- * aborts the receiver's upgrade — the receiver never registers the connection
315
- * and never creates its muxer, so no protocol can ever be negotiated — and the
316
- * dialer sees its "open" connection close moments later.
344
+ * Deny timing, as observed by the denied dialer (a quiet-period or base-gater
345
+ * deny): noise negotiates the muxer in the security handshake's early data, so
346
+ * the DIALER's upgrade may complete (its `dial()` resolves) before this
347
+ * receiver-side hook runs. The deny then aborts the receiver's upgrade — the
348
+ * receiver never registers the connection and never creates its muxer, so no
349
+ * protocol can ever be negotiated — and the dialer sees its "open" connection
350
+ * close moments later.
317
351
  *
318
352
  * Control node only: strand cohort nodes legitimately connect cross-party
319
353
  * peers, so cadre membership never gates them. An OPEN strand's node receives
@@ -322,8 +356,9 @@ export class UnauthorizedReservationBudget {
322
356
  * evidence, not this module's membership admission — see
323
357
  * `strand-revocation-enforcer.ts`.
324
358
  */
325
- export function createMembershipConnectionGater(policy, base, decisionTimeoutMs = ADMISSION_DECISION_TIMEOUT_MS, reserveDeadlineMs = RELAY_ADMISSION_RESERVE_DEADLINE_MS) {
326
- const pendingReservations = new PendingReserveDeadlines(reserveDeadlineMs);
359
+ export function createMembershipConnectionGater(policy, base, decisionTimeoutMs = ADMISSION_DECISION_TIMEOUT_MS, provisionalDeadlineMs = PROVISIONAL_ADMISSION_DEADLINE_MS) {
360
+ const decideInbound = (remotePeerId) => decideWithinDeadline(() => policy.admitInbound(remotePeerId), 'admit', decisionTimeoutMs, `admitInbound(${remotePeerId})`);
361
+ const provisional = new ProvisionalAdmissions(provisionalDeadlineMs, decideInbound);
327
362
  const quiet = () => policy.bringUpInFlight?.() ?? false;
328
363
  return {
329
364
  ...base,
@@ -348,17 +383,16 @@ export function createMembershipConnectionGater(policy, base, decisionTimeoutMs
348
383
  const remotePeerId = peerId.toString();
349
384
  let verdict;
350
385
  try {
351
- verdict = await decideWithinDeadline(() => policy.admitInbound(remotePeerId), 'admit', decisionTimeoutMs, `admitInbound(${remotePeerId})`);
386
+ verdict = await decideInbound(remotePeerId);
352
387
  }
353
388
  catch (error) {
354
389
  log('admitInbound threw for %s — admitting (fail-open; stream gates decide): %o', remotePeerId, error);
355
390
  return false;
356
391
  }
357
- if (verdict === 'admit-for-relay') {
358
- pendingReservations.arm(remotePeerId, maConn);
359
- return false;
392
+ if (verdict === 'admit-provisionally') {
393
+ provisional.arm(remotePeerId, maConn);
360
394
  }
361
- return verdict === 'deny';
395
+ return false;
362
396
  },
363
397
  denyInboundRelayReservation: async (peerId) => {
364
398
  if (await base?.denyInboundRelayReservation?.(peerId)) {
@@ -374,7 +408,7 @@ export function createMembershipConnectionGater(policy, base, decisionTimeoutMs
374
408
  admitted = true;
375
409
  }
376
410
  if (admitted) {
377
- pendingReservations.disarm(remotePeerId);
411
+ provisional.disarm(remotePeerId);
378
412
  }
379
413
  return !admitted;
380
414
  }
@@ -407,13 +441,12 @@ export async function decideWithinDeadline(decide, fallback, timeoutMs, what) {
407
441
  }
408
442
  }
409
443
  /**
410
- * The not-reserving deadlines for `'admit-for-relay'` connections, keyed by
411
- * remote peerId (a Set per peer — one peer can hold several in-flight
412
- * connections). `arm` starts a timer that closes the connection; `disarm`
413
- * (called when a reservation for that peer is admitted) cancels every pending
414
- * timer for the peer. Timers are unref'd so an armed deadline never holds a
415
- * process open, and a timer that fires against an already-closed connection is
416
- * a no-op (`close()` returns at once on any status but `open`).
444
+ * The deadlines of `'admit-provisionally'` connections, keyed by remote peerId
445
+ * (a Set per peer — one peer can hold several in-flight connections). `arm`
446
+ * starts a timer that re-asks the policy and closes the connection unless it now
447
+ * admits; `disarm` (called when a reservation for that peer is admitted) cancels
448
+ * every pending deadline for the peer, one whose question is already out
449
+ * included. Timers are unref'd so an armed deadline never holds a process open.
417
450
  *
418
451
  * Disarming is final for the connections it cancelled: a peer that reserved
419
452
  * once and then lets its reservation lapse keeps a mute connection (the
@@ -421,15 +454,16 @@ export async function decideWithinDeadline(decide, fallback, timeoutMs, what) {
421
454
  * side closes it. Bounded — only a peer the reservation policy already admitted
422
455
  * can reach that state, so unplaceable peers are bounded by the budget cap.
423
456
  */
424
- class PendingReserveDeadlines {
425
- constructor(deadlineMs) {
457
+ class ProvisionalAdmissions {
458
+ constructor(deadlineMs, decide) {
426
459
  this.deadlineMs = deadlineMs;
460
+ this.decide = decide;
427
461
  this.byPeer = new Map();
428
462
  }
429
463
  arm(remotePeerId, maConn) {
430
464
  const entry = {
431
465
  maConn,
432
- timer: setTimeout(() => this.expire(remotePeerId, entry), this.deadlineMs)
466
+ timer: setTimeout(() => void this.expire(remotePeerId, entry), this.deadlineMs)
433
467
  };
434
468
  entry.timer.unref?.();
435
469
  let entries = this.byPeer.get(remotePeerId);
@@ -438,7 +472,7 @@ class PendingReserveDeadlines {
438
472
  this.byPeer.set(remotePeerId, entries);
439
473
  }
440
474
  entries.add(entry);
441
- log('Admitted %s for relay only — dropping the connection unless a reservation is admitted within %dms', remotePeerId, this.deadlineMs);
475
+ log('Admitted %s provisionally — closing the connection in %dms unless it is admissible by then', remotePeerId, this.deadlineMs);
442
476
  }
443
477
  disarm(remotePeerId) {
444
478
  const entries = this.byPeer.get(remotePeerId);
@@ -450,17 +484,46 @@ class PendingReserveDeadlines {
450
484
  clearTimeout(entry.timer);
451
485
  }
452
486
  }
453
- expire(remotePeerId, entry) {
487
+ async expire(remotePeerId, entry) {
488
+ if (entry.maConn.status !== 'open') {
489
+ this.release(remotePeerId, entry);
490
+ return;
491
+ }
492
+ const verdict = await this.recheck(remotePeerId);
493
+ // False when a reservation admitted while the question was out disarmed this deadline.
494
+ if (!this.release(remotePeerId, entry)) {
495
+ return;
496
+ }
497
+ if (verdict === 'admit') {
498
+ log('%s is admissible at its provisional deadline — keeping the connection', remotePeerId);
499
+ return;
500
+ }
501
+ log('Provisional admission expired for %s — still unplaced after %dms, closing the connection', remotePeerId, this.deadlineMs);
502
+ await this.drop(remotePeerId, entry.maConn);
503
+ }
504
+ /** The policy's answer at the deadline; a throw keeps the connection (fail-open). */
505
+ async recheck(remotePeerId) {
506
+ try {
507
+ return await this.decide(remotePeerId);
508
+ }
509
+ catch (error) {
510
+ log('admitInbound threw for %s at its provisional deadline — keeping the connection (fail-open): %o', remotePeerId, error);
511
+ return 'admit';
512
+ }
513
+ }
514
+ /** Forget `entry`; false when a `disarm` already took it. */
515
+ release(remotePeerId, entry) {
454
516
  const entries = this.byPeer.get(remotePeerId);
455
- entries?.delete(entry);
456
- if (entries?.size === 0) {
517
+ if (!entries?.delete(entry)) {
518
+ return false;
519
+ }
520
+ if (entries.size === 0) {
457
521
  this.byPeer.delete(remotePeerId);
458
522
  }
459
- log('Relay-only admission expired for %s — no reservation admitted within %dms, closing the connection', remotePeerId, this.deadlineMs);
460
- void this.drop(remotePeerId, entry.maConn);
523
+ return true;
461
524
  }
462
525
  /**
463
- * End an expired relay-only connection: a bounded graceful close, with
526
+ * End an expired provisional connection: a bounded graceful close, with
464
527
  * `abort()` only as the escalation. The order cannot be reversed — `abort()`
465
528
  * marks the connection `aborted`, and `close()` returns immediately on any
466
529
  * status that is not `open`, so aborting first would make the close a silent
@@ -469,11 +532,11 @@ class PendingReserveDeadlines {
469
532
  */
470
533
  async drop(remotePeerId, maConn) {
471
534
  try {
472
- await withDeadline(RELAY_ADMISSION_CLOSE_TIMEOUT_MS, `relay-only close for ${remotePeerId}`, (signal) => maConn.close({ signal }));
535
+ await withDeadline(PROVISIONAL_ADMISSION_CLOSE_TIMEOUT_MS, `provisional close for ${remotePeerId}`, (signal) => maConn.close({ signal }));
473
536
  return;
474
537
  }
475
538
  catch (error) {
476
- log('Closing the expired relay-only connection from %s failed — aborting: %o', remotePeerId, error);
539
+ log('Closing the expired provisional connection from %s failed — aborting: %o', remotePeerId, error);
477
540
  }
478
541
  // NOTE: this fallback cannot actually free a WebSocket. `@libp2p/websockets`'
479
542
  // `sendReset()` calls `websocket.close(1006)`, and 1006 is a reserved code
@@ -485,10 +548,10 @@ class PendingReserveDeadlines {
485
548
  // far as this layer can go. Revisit — drop the fallback, or go back to a
486
549
  // plain `abort()` — once that transport sends a legal reset code.
487
550
  try {
488
- maConn.abort(new Error(`relay-only admission expired: no relay reservation admitted within ${this.deadlineMs}ms`));
551
+ maConn.abort(new Error(`provisional admission expired: still unplaced after ${this.deadlineMs}ms`));
489
552
  }
490
553
  catch (error) {
491
- log('Aborting the expired relay-only connection from %s threw: %o', remotePeerId, error);
554
+ log('Aborting the expired provisional connection from %s threw: %o', remotePeerId, error);
492
555
  }
493
556
  }
494
557
  }
@@ -1 +1 @@
1
- {"version":3,"file":"membership-connection-gater.js","sourceRoot":"","sources":["../src/membership-connection-gater.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"membership-connection-gater.js","sourceRoot":"","sources":["../src/membership-connection-gater.ts"],"names":[],"mappings":"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"}