Skip to content

feat(ocap-kernel): add direct transport support (QUIC + TCP) for Node.js connections#839

Merged
sirtimid merged 11 commits intomainfrom
sirtimid/remote-comms-udp-quic-support
Feb 13, 2026
Merged

feat(ocap-kernel): add direct transport support (QUIC + TCP) for Node.js connections#839
sirtimid merged 11 commits intomainfrom
sirtimid/remote-comms-udp-quic-support

Conversation

@sirtimid
Copy link
Contributor

@sirtimid sirtimid commented Feb 13, 2026

Summary

  • Add directListenAddresses option to RemoteCommsOptions for users to declare direct listen addresses
  • NodejsPlatformServices auto-detects QUIC (/quic-v1) and TCP (/tcp/) transports from address strings
  • ConnectionFactory accepts multiple directTransports (array), merging them into the libp2p config
  • Direct addresses are tried before relay fallback in candidateAddressStrings()
  • kernel.getStatus() exposes listenAddresses when remote comms is connected
  • kernel.registerLocationHints() added for out-of-band address exchange between peers
  • Bootstrap peer discovery made conditional (omitted when no relays provided)
  • Browser environments unaffected (WebSocket/WebRTC only)

Test plan

  • yarn workspace @metamask/ocap-kernel test:dev:quiet — all unit tests pass (1944)
  • yarn workspace @ocap/nodejs test:dev:quiet — all Node.js tests pass (50)
  • yarn workspace @metamask/ocap-kernel lint:fix — clean
  • yarn workspace @ocap/nodejs lint:fix — clean
  • E2E: yarn workspace @ocap/nodejs test:e2e:ci — direct QUIC and TCP between Node.js kernels

Closes #645

🤖 Generated with Claude Code


Note

Medium Risk
Touches core remote-communication setup and dialing behavior and adds new transports/dependencies (QUIC/TCP), which can affect connectivity across environments despite strong test coverage.

Overview
Adds Node.js direct connectivity for remote comms by introducing directListenAddresses (user-facing) and internally mapping it to injected directTransports (QUIC via @chainsafe/libp2p-quic, TCP via @libp2p/tcp), including validation for unsupported multiaddrs.

Updates the libp2p ConnectionFactory to accept directTransports, merge their listen addresses/transports into the libp2p config, skip bootstrap discovery when no relays are configured, and prefer direct address hints (skipping malformed hints) before relay-derived dial attempts.

Exposes new surface area: Kernel.registerLocationHints() for out-of-band direct address exchange and Kernel.getStatus().remoteComms.listenAddresses (plumbed via new PlatformServices.getListenAddresses() / initTransport return value). Browser platform services implement getListenAddresses() as [].

Adds extensive unit coverage plus a new Node.js E2E suite verifying QUIC/TCP direct messaging, and updates mocks/tests accordingly; also broadens .gitignore to ignore **/.claude/settings.local.json.

Written by Cursor Bugbot for commit 8e56a5e. This will update automatically on new commits. Configure here.

…ections

Add direct QUIC (UDP) transport for peer-to-peer Node.js kernel communication
without requiring a relay server. Users declare `directListenAddresses` in
`initRemoteComms` options and the platform layer auto-detects and injects
the `@chainsafe/libp2p-quic` transport.

Key changes:
- ConnectionFactory: options bag API, direct transport merging, conditional
  bootstrap (allows relay-free operation), getListenAddresses()
- Kernel: expose listenAddresses in status, add registerLocationHints()
- NodejsPlatformServices: auto-detect QUIC from address strings, dynamic
  import of @chainsafe/libp2p-quic
- E2E tests proving direct QUIC works without any relay

Closes #645

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@socket-security
Copy link

socket-security bot commented Feb 13, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​chainsafe/​libp2p-quic@​1.1.8761009091100

View full report

Pluralize directTransport to directTransports (array) to support
multiple simultaneous transports. Add TCP transport auto-detection
in NodejsPlatformServices alongside existing QUIC detection.

Users can now pass both QUIC and TCP addresses:
  directListenAddresses: ['/ip4/0.0.0.0/udp/0/quic-v1', '/ip4/0.0.0.0/tcp/0']

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sirtimid sirtimid changed the title feat(ocap-kernel): add QUIC direct transport for Node.js connections feat(ocap-kernel): add direct transport support (QUIC + TCP) for Node.js connections Feb 13, 2026
sirtimid and others added 4 commits February 13, 2026 15:07
Add missing getListenAddresses method to PlatformServices mocks in
kernel-test, ocap-kernel test helpers, Kernel.test, and
PlatformServicesServer.test to match the updated type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap dynamic QUIC/TCP imports with actionable error messages
- Validate unrecognized direct listen addresses (throw instead of silently dropping)
- Fix timer leak in ConnectionFactory.stop() via clearTimeout in .finally()
- Remove unnecessary `undefined as unknown as Libp2p` type assertion
- Add missing listenAddresses to kernel-test status assertion
- Add registerLocationHints to mock RemoteManager and unit test in Kernel.test
- Add tests for dynamic import failures, empty relays+hints, unsupported addresses

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 78%
⬆️ +0.10%
6343 / 8132
🔵 Statements 77.96%
⬆️ +0.10%
6445 / 8267
🔵 Functions 75.95%
⬆️ +0.01%
1598 / 2104
🔵 Branches 78%
⬆️ +0.17%
2352 / 3015
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/kernel-browser-runtime/src/PlatformServicesClient.ts 89.55%
⬇️ -1.35%
75.86%
🟰 ±0%
77.27%
⬇️ -3.68%
89.55%
⬇️ -1.35%
110, 132, 290-301, 338-341
packages/nodejs/src/kernel/PlatformServices.ts 92.92%
⬆️ +1.91%
89.74%
⬆️ +7.14%
84.21%
⬆️ +0.88%
92.92%
⬆️ +1.91%
151-154, 192, 222-227, 398-401
packages/ocap-kernel/src/Kernel.ts 87.37%
⬆️ +0.12%
76.66%
🟰 ±0%
80.43%
⬆️ +0.43%
87.37%
⬆️ +0.12%
122, 252-255, 272, 296, 364-374, 466, 534, 600-603, 616, 626-627, 670
packages/ocap-kernel/src/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/types.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/remotes/types.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/remotes/platform/connection-factory.ts 97.27%
⬆️ +0.50%
90%
⬆️ +2.50%
96.29%
⬆️ +0.84%
97.22%
⬆️ +0.49%
261, 406, 440
packages/ocap-kernel/src/remotes/platform/transport.ts 82.37%
⬇️ -0.37%
80.72%
🟰 ±0%
74.19%
⬇️ -2.47%
82.37%
⬇️ -0.37%
116, 157-158, 163-167, 209-218, 251, 285-303, 327, 411, 455-458, 482, 506-511, 514-515, 519-522, 563, 593, 612-614, 623, 734
packages/ocap-kernel/src/vats/VatSupervisor.ts 72.72%
🟰 ±0%
42.42%
🟰 ±0%
58.33%
🟰 ±0%
72.72%
🟰 ±0%
125, 136, 144, 182, 220-224, 235, 244-245, 266-268, 271, 275-277, 309-311, 328, 345-353
Generated in workflow #3734 for commit 8e56a5e by the Vitest Coverage Report Action

sirtimid and others added 2 commits February 13, 2026 15:30
Both @chainsafe/libp2p-quic and @libp2p/tcp are hard dependencies that
ship with @ocap/nodejs. Wrapping their imports adds noise without value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both packages are hard dependencies of @ocap/nodejs. Dynamic imports
added unnecessary indirection with no benefit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sirtimid sirtimid marked this pull request as ready for review February 13, 2026 14:33
@sirtimid sirtimid requested a review from a team as a code owner February 13, 2026 14:33
@sirtimid sirtimid enabled auto-merge February 13, 2026 18:15
Copy link
Contributor

@grypez grypez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just a few comments for maintainability.


Could declare and reuse this type in a few places.

type DirectTransport = {
  transport: unknown;
  listenAddresses: string[];
};

- Add clarifying comment for conditional peer discovery
- Use multiaddr().getPeerId() instead of string matching for direct
  address detection in candidateAddressStrings()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

sirtimid and others added 2 commits February 13, 2026 19:39
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y fallback

A malformed hint passed to multiaddr() would throw and abort address
generation before relay addresses were built. Now invalid hints are
caught and skipped so relay fallback dialing still works.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sirtimid sirtimid requested a review from grypez February 13, 2026 18:41
@sirtimid sirtimid added this pull request to the merge queue Feb 13, 2026
Merged via the queue into main with commit b05af68 Feb 13, 2026
29 checks passed
@sirtimid sirtimid deleted the sirtimid/remote-comms-udp-quic-support branch February 13, 2026 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remote comms: Add direct transport support (QUIC + TCP) for Node.js connections

2 participants