@serfab/cadre-core 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/cadre-node.d.ts +0 -27
  2. package/dist/cadre-node.js +2 -94
  3. package/dist/cadre-node.js.map +1 -1
  4. package/dist/control-schema.js +1066 -1066
  5. package/dist/diagnostics/connection-path.d.ts +1 -18
  6. package/dist/diagnostics/connection-path.js +1 -20
  7. package/dist/diagnostics/connection-path.js.map +1 -1
  8. package/dist/identity-key.d.ts +0 -30
  9. package/dist/identity-key.js +7 -40
  10. package/dist/identity-key.js.map +1 -1
  11. package/dist/index.d.ts +3 -2
  12. package/dist/index.js +6 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/relay-stun.d.ts +24 -0
  15. package/dist/relay-stun.js +51 -0
  16. package/dist/relay-stun.js.map +1 -0
  17. package/dist/seed-bootstrap.js +4 -4
  18. package/dist/strand-membership-writer.js +32 -32
  19. package/package.json +2 -2
  20. package/src/cadre-node.ts +8654 -8753
  21. package/src/control-authorization.ts +117 -117
  22. package/src/control-cohort.ts +128 -128
  23. package/src/control-formation-recorder.ts +353 -353
  24. package/src/control-read-retry.ts +216 -216
  25. package/src/control-schema.ts +1078 -1078
  26. package/src/control-write-retry.ts +567 -567
  27. package/src/diagnostics/connection-path.ts +1 -29
  28. package/src/formation-approval.ts +610 -610
  29. package/src/hibernation-manager.ts +638 -638
  30. package/src/identity-key.ts +7 -62
  31. package/src/index.ts +644 -647
  32. package/src/invitation-bootstrap.ts +40 -40
  33. package/src/joined-strand-store.ts +498 -498
  34. package/src/link-budget.ts +684 -684
  35. package/src/membership-connection-gater.ts +570 -570
  36. package/src/node-local-snapshot.ts +298 -298
  37. package/src/peer-dial.ts +315 -315
  38. package/src/peer-join-backfill.ts +710 -710
  39. package/src/pending-join-runner.ts +735 -735
  40. package/src/relay-reservation.ts +1121 -1121
  41. package/src/relay-server.ts +98 -98
  42. package/src/relay-stun.ts +58 -0
  43. package/src/seed-bootstrap.ts +1448 -1448
  44. package/src/strand-addr-protocol.ts +547 -547
  45. package/src/strand-database.ts +287 -287
  46. package/src/strand-first-sync-gate.ts +391 -391
  47. package/src/strand-formation-deadlines.ts +227 -227
  48. package/src/strand-formation-manager.ts +725 -725
  49. package/src/strand-fret-addrs.ts +145 -145
  50. package/src/strand-instance-manager.ts +1789 -1789
  51. package/src/strand-membership-writer.ts +1974 -1974
  52. package/src/strand-network-state-file.ts +40 -40
  53. package/src/strand-network-state.ts +243 -243
  54. package/src/strand-revocation-enforcer.ts +654 -654
  55. package/src/strand-solicitation.ts +532 -532
  56. package/src/strand-wake-protocol.ts +401 -401
  57. package/src/types.ts +2222 -2222
  58. package/dist/diagnostics/webrtc-turn-tracker.d.ts +0 -50
  59. package/dist/diagnostics/webrtc-turn-tracker.js +0 -196
  60. package/dist/diagnostics/webrtc-turn-tracker.js.map +0 -1
  61. package/src/diagnostics/webrtc-turn-tracker.ts +0 -222
@@ -612,23 +612,6 @@ export declare class CadreNode implements SAppIdLookup {
612
612
  private controlConnectionOpenHandler;
613
613
  /** `connection:close` listener re-arming the growth edge (teardown in {@link stopRecordRefresh}). */
614
614
  private controlConnectionCloseHandler;
615
- /**
616
- * Hooks `globalThis.RTCPeerConnection` to observe whether ICE selected a TURN
617
- * relay candidate for each WebRTC session. Installed in {@link start}, disposed
618
- * in {@link cleanup}; inert on Node.js (no `RTCPeerConnection`).
619
- */
620
- private readonly turnTracker;
621
- /**
622
- * Peer IDs whose current WebRTC connection was observed to be TURN-relayed.
623
- * Populated by {@link handleTurnConnectionOpen} (drains the tracker queue on a
624
- * `/webrtc` `connection:open`), cleared per-peer on `connection:close`. Read by
625
- * {@link getConnectionPaths} to promote `webrtc` → `webrtc-turn` (relayed).
626
- */
627
- private turnRelayedPeers;
628
- /** `connection:open` listener feeding TURN detection (teardown in {@link stopRecordRefresh}). */
629
- private turnConnectionOpenHandler;
630
- /** `connection:close` listener clearing a peer's TURN flag (teardown in {@link stopRecordRefresh}). */
631
- private turnConnectionCloseHandler;
632
615
  constructor(config: CadreNodeConfig);
633
616
  /**
634
617
  * SAppIdLookup implementation - get sAppId for a strand: the claiming config's, else
@@ -1852,16 +1835,6 @@ export declare class CadreNode implements SAppIdLookup {
1852
1835
  * Idempotent.
1853
1836
  */
1854
1837
  private wireControlConnectionListeners;
1855
- /**
1856
- * On a control connection opening: if it is a WebRTC connection, drain the TURN
1857
- * tracker for the just-settled ICE verdict and, when it relayed, mark the peer
1858
- * so {@link getConnectionPaths} classifies it `webrtc-turn` (relayed). The
1859
- * settlement↔open correlation is timing-based and best-effort; an unknown
1860
- * verdict degrades to not-relayed. Never throws to the event loop.
1861
- */
1862
- private handleTurnConnectionOpen;
1863
- /** On a control connection closing, drop any TURN-relayed flag for its peer. */
1864
- private handleTurnConnectionClose;
1865
1838
  /**
1866
1839
  * Publish (or refresh) this node's own self-signed `DeviceToken` row so a server
1867
1840
  * peer can resolve its FCM/APNs push token from its PeerId alone. Mirrors
@@ -51,17 +51,10 @@ import { resolveRelayServer } from './relay-server.js';
51
51
  import { replacesAdvertisedAddrs, resolveAnnounceAddrs } from './announce-addrs.js';
52
52
  import { superviseRelayReservation, resolveRelayReservationState } from './relay-reservation.js';
53
53
  import { PushFanoutService } from './push-fanout.js';
54
- import { summarizeConnectionPaths, classifyTransport } from './diagnostics/connection-path.js';
55
- import { TurnRelayTracker } from './diagnostics/webrtc-turn-tracker.js';
54
+ import { summarizeConnectionPaths } from './diagnostics/connection-path.js';
56
55
  import { timedStep } from './timed-step.js';
57
56
  const log = debug('sereus:cadre:node');
58
57
  const timing = debug('sereus:cadre:timing');
59
- /**
60
- * Window (ms) within which a queued TURN-relay settlement is correlated to a
61
- * `connection:open`. Generous relative to the tight async gap between an
62
- * `RTCPeerConnection` reaching `connected` and libp2p surfacing the connection.
63
- */
64
- const TURN_CONSUME_WINDOW_MS = 1000;
65
58
  /**
66
59
  * How often a running strand re-asks each connected sibling that last ANSWERED
67
60
  * (even with nothing) for its strand-network addresses, and re-merges them into
@@ -734,24 +727,6 @@ export class CadreNode {
734
727
  this.controlConnectionOpenHandler = null;
735
728
  /** `connection:close` listener re-arming the growth edge (teardown in {@link stopRecordRefresh}). */
736
729
  this.controlConnectionCloseHandler = null;
737
- // ── WebRTC TURN-relay detection (turn-relayed-path-metrics) ─────────────────
738
- /**
739
- * Hooks `globalThis.RTCPeerConnection` to observe whether ICE selected a TURN
740
- * relay candidate for each WebRTC session. Installed in {@link start}, disposed
741
- * in {@link cleanup}; inert on Node.js (no `RTCPeerConnection`).
742
- */
743
- this.turnTracker = new TurnRelayTracker();
744
- /**
745
- * Peer IDs whose current WebRTC connection was observed to be TURN-relayed.
746
- * Populated by {@link handleTurnConnectionOpen} (drains the tracker queue on a
747
- * `/webrtc` `connection:open`), cleared per-peer on `connection:close`. Read by
748
- * {@link getConnectionPaths} to promote `webrtc` → `webrtc-turn` (relayed).
749
- */
750
- this.turnRelayedPeers = new Set();
751
- /** `connection:open` listener feeding TURN detection (teardown in {@link stopRecordRefresh}). */
752
- this.turnConnectionOpenHandler = null;
753
- /** `connection:close` listener clearing a peer's TURN flag (teardown in {@link stopRecordRefresh}). */
754
- this.turnConnectionCloseHandler = null;
755
730
  this.config = config;
756
731
  this.hostUnclaimedStrands = config.hostUnclaimedStrands ?? config.profile === 'storage';
757
732
  this.strandManager = new StrandInstanceManager();
@@ -831,18 +806,7 @@ export class CadreNode {
831
806
  * direct sibling is considered stuck (default 10_000ms)
832
807
  */
833
808
  getConnectionPaths(settleWindowMs) {
834
- const conns = this.controlNode?.getConnections() ?? [];
835
- // Annotate each connection with the TURN-relay hint so a WebRTC session whose
836
- // ICE selected a TURN candidate classifies as relayed/webrtc-turn rather than
837
- // direct/webrtc (the multiaddr alone cannot reveal it).
838
- const annotated = conns.map((c) => ({
839
- remotePeer: c.remotePeer,
840
- remoteAddr: c.remoteAddr,
841
- direction: c.direction,
842
- timeline: c.timeline,
843
- turnRelayed: this.turnRelayedPeers.has(c.remotePeer.toString()),
844
- }));
845
- return summarizeConnectionPaths(annotated, settleWindowMs);
809
+ return summarizeConnectionPaths(this.controlNode?.getConnections(), settleWindowMs);
846
810
  }
847
811
  /**
848
812
  * Get all strand instances
@@ -902,10 +866,6 @@ export class CadreNode {
902
866
  // yet), so a node with a zero or NaN declaration would otherwise boot and fail later
903
867
  // inside a best-effort path that logs and carries on. `link-budget.ts`.
904
868
  resolveLinkRoundTripMs(this.config.network?.linkRoundTripMs);
905
- // Install the WebRTC TURN-relay tracker BEFORE any libp2p bring-up, so it
906
- // wraps globalThis.RTCPeerConnection before the control node can create one.
907
- // Inert on Node.js (no RTCPeerConnection); disposed in cleanup().
908
- this.turnTracker.install();
909
869
  // Resolve the node identity (keyStore | privateKey | ephemeral) BEFORE any
910
870
  // libp2p/network bring-up, so a misconfiguration or an access-denied secure
911
871
  // store fails closed before a node is created.
@@ -2535,18 +2495,10 @@ export class CadreNode {
2535
2495
  if (this.controlConnectionCloseHandler) {
2536
2496
  this.controlNode.removeEventListener('connection:close', this.controlConnectionCloseHandler);
2537
2497
  }
2538
- if (this.turnConnectionOpenHandler) {
2539
- this.controlNode.removeEventListener('connection:open', this.turnConnectionOpenHandler);
2540
- }
2541
- if (this.turnConnectionCloseHandler) {
2542
- this.controlNode.removeEventListener('connection:close', this.turnConnectionCloseHandler);
2543
- }
2544
2498
  }
2545
2499
  this.selfPeerUpdateHandler = null;
2546
2500
  this.controlConnectionOpenHandler = null;
2547
2501
  this.controlConnectionCloseHandler = null;
2548
- this.turnConnectionOpenHandler = null;
2549
- this.turnConnectionCloseHandler = null;
2550
2502
  // Reset the write-while-alone re-replication state so a stop()→start() cycle
2551
2503
  // re-arms the growth edge and re-runs BOTH one-shot passes. Any queued
2552
2504
  // local-only writes are moot once the node is torn down: owner inserts are
@@ -3815,47 +3767,6 @@ export class CadreNode {
3815
3767
  this.controlConnectionCloseHandler = () => this.handleControlConnectionClose();
3816
3768
  this.controlNode.addEventListener('connection:open', this.controlConnectionOpenHandler);
3817
3769
  this.controlNode.addEventListener('connection:close', this.controlConnectionCloseHandler);
3818
- // TURN-relay detection: tag/untag peers whose WebRTC ICE used a TURN candidate.
3819
- this.turnConnectionOpenHandler = (evt) => this.handleTurnConnectionOpen(evt.detail);
3820
- this.turnConnectionCloseHandler = (evt) => this.handleTurnConnectionClose(evt.detail);
3821
- this.controlNode.addEventListener('connection:open', this.turnConnectionOpenHandler);
3822
- this.controlNode.addEventListener('connection:close', this.turnConnectionCloseHandler);
3823
- }
3824
- /**
3825
- * On a control connection opening: if it is a WebRTC connection, drain the TURN
3826
- * tracker for the just-settled ICE verdict and, when it relayed, mark the peer
3827
- * so {@link getConnectionPaths} classifies it `webrtc-turn` (relayed). The
3828
- * settlement↔open correlation is timing-based and best-effort; an unknown
3829
- * verdict degrades to not-relayed. Never throws to the event loop.
3830
- */
3831
- handleTurnConnectionOpen(conn) {
3832
- try {
3833
- const addr = conn.remoteAddr?.toString() ?? '';
3834
- // Only a genuine `/webrtc` (ICE) session can be TURN-relayed and promoted to
3835
- // webrtc-turn. Use the classifier (which checks `/webrtc-direct` first) rather
3836
- // than a bare substring — `'/webrtc-direct'.includes('/webrtc')` is true, and a
3837
- // webrtc-direct open must not drain a settlement meant for a real webrtc dial.
3838
- if (classifyTransport(addr).transport !== 'webrtc') {
3839
- return;
3840
- }
3841
- if (this.turnTracker.consume(TURN_CONSUME_WINDOW_MS) === true) {
3842
- const peerId = conn.remotePeer.toString();
3843
- this.turnRelayedPeers.add(peerId);
3844
- log('TURN-relayed WebRTC connection detected for peer %s', peerId);
3845
- }
3846
- }
3847
- catch (error) {
3848
- log('handleTurnConnectionOpen failed: %o', error);
3849
- }
3850
- }
3851
- /** On a control connection closing, drop any TURN-relayed flag for its peer. */
3852
- handleTurnConnectionClose(conn) {
3853
- try {
3854
- this.turnRelayedPeers.delete(conn.remotePeer.toString());
3855
- }
3856
- catch (error) {
3857
- log('handleTurnConnectionClose failed: %o', error);
3858
- }
3859
3770
  }
3860
3771
  // ============================================================================
3861
3772
  // Device-token registry (control-network push-token publish + resolve)
@@ -4217,9 +4128,6 @@ export class CadreNode {
4217
4128
  // Stop self-record refresh timers + address-change listener (before the
4218
4129
  // control node is torn down, so removeEventListener has a live target).
4219
4130
  this.stopRecordRefresh();
4220
- // Restore the wrapped globalThis.RTCPeerConnection and drop TURN-relay state.
4221
- this.turnTracker.dispose();
4222
- this.turnRelayedPeers.clear();
4223
4131
  // Stop hibernation manager
4224
4132
  this.hibernationManager.stop();
4225
4133
  // Stop seed bootstrap service