Files
alknet/docs/architecture/questions/009-wasm-target-boundaries.md
T
glm-5.2 2aa6363e57 docs(arch): sync specs to transport generalization sweep (ADR-064, ADR-065)
Three code commits landed a clean sweep discovered when building an
external app against the crates. This syncs the architecture specs to
match the codebase and amends the affected decisions.

ADR-064 (supersedes ADR-005): irpc was never integrated — no .rs file in
the workspace ever imported it. The wire protocol (wire.rs) is hand-rolled
length-prefixed JSON; the EventEnvelope shape was derived from the
@alkdev/pubsub TypeScript prior art (ADR-013), not from irpc. ADR-005's
premise ('irpc as the call protocol foundation') was never implemented as
stated. Superseded with a clear header; the body is kept as historical
record.

ADR-065: Connection::from_stream / from_bidi — Connection now accepts any
AsyncRead + AsyncWrite pair via ConnectionKind::Stream (yield-once
accept_bi contract: QUIC yields many streams, everything else yields one
then ConnectionClosed). Unblocks TCP+TLS, SSH channel dispatch,
WebTransport streams, and wasm streams through the same HandlerRegistry
as QUIC connections, with zero handler code changes. MockConnection /
ConnectionKind::Mock removed (tests use from_stream with sink/empty).
Stream-level Mock variants renamed to Stream (they were already generic).

Amended ADRs: ADR-003 (irpc removed from dep table), ADR-007 (from_stream
opens the server-side door; MockConnection removed), ADR-010 (TCP+TLS can
now dispatch through the registry via from_bidi; iroh 1.0 migration noted).

Updated specs: core-types.md (Connection/SendStream/RecvStream sections),
endpoint.md (TCP section, iroh note), call-protocol.md, operation-registry
(irpc Integration section replaced), overview.md, http-server.md,
webtransport.md, call README. OQ-09 (WASM) resolution amended: the
Connection door is now open via from_stream; the accept-loop runtime door
remains closed (tokio doesn't run on WASM).

See docs/research/transport-generalization/findings.md for the full trace.
2026-07-09 07:40:51 +00:00

3.3 KiB

OQ-09: WASM Target Boundaries

  • Origin: overview.md
  • Status: deferred
  • Door type: One-way (when applicable)
  • Priority: low
  • Blocked on: A concrete server-side WASM use case, or a deliberate confirmation that WASM stays a client-side design constraint. Tracked as architecture/oq-09-wasm-server-use-case in tasks/architecture/.
  • Resolution: Not an active question — WASM compatibility is a design constraint (see ADR-009, overview.md design principles), not a deliverable. Specific WASM targeting decisions will be made when individual crates are implemented. BiStream being a trait preserves the client-side stream door — a browser can implement BiStream over WebTransport streams. The server-side connection door is now open via Connection::from_stream (ADR-065): from_stream accepts any AsyncRead + AsyncWrite pair, including wasm-compatible streams, so a Connection can be constructed from a wasm stream and dispatched through the HandlerRegistry like any QUIC connection. What remains closed is the accept-loop runtime: the AlknetEndpoint accept loops use tokio::spawn (tokio does not run on WASM), and the call-protocol dispatch internals (PendingRequestMap, CallAdapter) use tokio oneshot/mpsc channels. A WASM server-side peer would require a runtime-abstracted accept loop (not tokio::spawn) and a runtime-abstracted channel set — the Connection door is open, the runtime door is not. The browser path is client-side via a JS SDK, not server-side Rust-to-WASM. This is an explicit one-way door (the runtime), not an oversight; the Connection door was a one-way door that ADR-065 opened (additively, without a trait change).
  • Cross-references: ADR-007 (Amendment 1 — from_stream opens the server-side door), ADR-009, ADR-065

Amendment (2026-07-09)

The original resolution (above) stated: "The server-side dispatch door is NOT preserved by ADR-007 and is a known, accepted closure: Connection is a concrete quinn-bound struct (not a trait), the accept loop uses tokio::spawn (tokio does not run on WASM)..." That was accurate when written: until ADR-065, Connection had only QUIC variants (ConnectionKind::Quinn / ConnectionKind::Iroh) plus a ConnectionKind::Mock test stub — no way to construct a Connection from a non-QUIC stream.

ADR-065 opens the Connection door. Connection::from_stream / from_bidi accept any AsyncRead + AsyncWrite pair, including wasm-compatible streams. A Connection can now be constructed from a wasm stream and dispatched through the HandlerRegistry like any QUIC connection — the connection door is open. The resolution text above has been updated to reflect this.

What is still closed: the accept-loop runtime. The AlknetEndpoint accept loops use tokio::spawn, and the call-protocol dispatch internals (PendingRequestMap, CallAdapter) use tokio oneshot/mpsc channels. Tokio does not run on WASM. A WASM server-side peer would require a runtime-abstracted accept loop and a runtime-abstracted channel set — the Connection door is open, the runtime door is not. This is the remaining one-way door, and it is still a runtime door, not a connection door. The blocking condition (a concrete server-side WASM use case) is unchanged.