Context
polymorph-iroh retired jco — deltic is their JS leg on main (their #40/#41) — and their upstream-iroh experiments run on a consumer-side synthetic-network provider written in our embedder conventions (experiments/iroh-relay-ws/host/sockets.ts, 438 lines): queue-backed UdpSocket + datagram streams, four routing hooks (registerBridge/registerAddrRoute/socketByLocalPort/pushDatagram), typed WitError stubs for tcp/ip-name-lookup, spread-after-wasiShims() overrides.
This issue tracks adopting the socket surface + hooks into wasi-shims as a sockets() fragment, reversing the earlier "sockets out of deltic" ruling if/when we choose to. The transports/bridges (relay DatagramPipe, WebRTC overlay, address-allocation policy) stay theirs regardless.
Why adopt (when we do)
- They're the flagship deltic consumer now; the surface is generic WASI (any tokio/libc guest doing UDP over virtual transports), and a second implementation already exists — the question is only who maintains it. Spec-shaped surface with a library-grade state model is our competence; their transports are theirs.
- Their implementation is experiment-grade in three ways a library must fix: module-global state (bridges/routes/port maps as module-level maps — two synthetic networks in one process collide; adoption = instance-scoped
SyntheticNetwork), lifecycle gaps (empty Symbol.dispose, no socketsByPort cleanup, ephemeral-port wraparound), and a bridge-specific overlayOwner field baked into the socket class.
- Testing division stays clean post-exam-retirement: deltic ships the fragment with self-contained pins (extend
wasi-shims/tests/testdata/blocking-guest.wat with a UDP echo through a test bridge); no consumer artifacts in our gates; their experiments consume the fragment in their repo.
Sequencing / prerequisites
- First (their side, unblocked by deltic#71): on their next deltic pin bump, their tier-(c)
Pollable/poll/monotonic-clock overrides (~200 lines) should be deleted in favor of the wasi-shims parking kernel — theirs are async functions that suspend on every call (no sync fast paths, pin-(j) hop each time), and their duck-typed PollableLike seam exists only because two Pollable classes coexist. Recorded as IROH-2 in upstream-consumer-findings.md; filing upstream is the operator's call.
- Then adopt the socket surface + hooks here, coordinated so they swap once (kernel + fragment together), not twice.
Scope sketch (~a day when picked up)
wasi-shims/src/sockets.ts: instance-scoped SyntheticNetwork (owns routes/ports/queues) + sockets({network}) fragment; udp real (kernel Pollables via the public constructor seam), tcp + ip-name-lookup as typed WitError stubs; hooks as methods on the network instance.
- Fixes by construction: dispose cleanup, port-collision behavior, fast paths (inherited from the kernel), extension point replacing
overlayOwner.
- Pins: UDP echo through a test bridge driven by the blocking-guest fixture; hook routing (port vs addr precedence); multi-tenant isolation (two networks, no crosstalk).
- Contract: embedder-api WASI-examination note; consumers.md row.
Not in scope
p3 wasi:sockets providers (real UDP over Deno.listenDatagram, the direct-path leg) — that's #4.
Context
polymorph-iroh retired jco — deltic is their JS leg on main (their #40/#41) — and their upstream-iroh experiments run on a consumer-side synthetic-network provider written in our embedder conventions (
experiments/iroh-relay-ws/host/sockets.ts, 438 lines): queue-backedUdpSocket+ datagram streams, four routing hooks (registerBridge/registerAddrRoute/socketByLocalPort/pushDatagram), typedWitErrorstubs for tcp/ip-name-lookup, spread-after-wasiShims()overrides.This issue tracks adopting the socket surface + hooks into wasi-shims as a
sockets()fragment, reversing the earlier "sockets out of deltic" ruling if/when we choose to. The transports/bridges (relay DatagramPipe, WebRTC overlay, address-allocation policy) stay theirs regardless.Why adopt (when we do)
SyntheticNetwork), lifecycle gaps (emptySymbol.dispose, nosocketsByPortcleanup, ephemeral-port wraparound), and a bridge-specificoverlayOwnerfield baked into the socket class.wasi-shims/tests/testdata/blocking-guest.watwith a UDP echo through a test bridge); no consumer artifacts in our gates; their experiments consume the fragment in their repo.Sequencing / prerequisites
Pollable/poll/monotonic-clockoverrides (~200 lines) should be deleted in favor of the wasi-shims parking kernel — theirs areasyncfunctions that suspend on every call (no sync fast paths, pin-(j) hop each time), and their duck-typedPollableLikeseam exists only because two Pollable classes coexist. Recorded as IROH-2 inupstream-consumer-findings.md; filing upstream is the operator's call.Scope sketch (~a day when picked up)
wasi-shims/src/sockets.ts: instance-scopedSyntheticNetwork(owns routes/ports/queues) +sockets({network})fragment; udp real (kernel Pollables via the public constructor seam), tcp + ip-name-lookup as typedWitErrorstubs; hooks as methods on the network instance.overlayOwner.Not in scope
p3
wasi:socketsproviders (real UDP overDeno.listenDatagram, the direct-path leg) — that's #4.