Files
alknet/docs/architecture/crates/http
glm-5.2 125cb49cc4 docs(http): defer h3/WebTransport (ADR-044); browsers use WebSocket for v1
Working through the WebTransport implementation path surfaced a scope
question distinct from the hedging-as-deferral anti-pattern ADR-038 was
written to correct. Three findings drove the re-evaluation:

1. The browser bidirectional call-protocol path doesn't require
   WebTransport — WebSocket is full-duplex, EventEnvelope fits a WS
   binary message boundary cleanly, and the Dispatcher is stream-
   agnostic (ADR-012). What WebTransport gives over WebSocket (native
   multi-stream multiplexing, the ALPN-as-stream substrate) benefits the
   proxy use case, not the call protocol.
2. WebTransport is a draft standard (-07, not RFC) on an experimental
   Rust dependency stack (wtransport/h3 both self-describe as not
   production-ready). Either choice puts a draft protocol on the
   security surface of the first release.
3. The ALPN-stream-proxy (ADR-040) is speculative — its WASM parser
   consumers (browser SSH/SFTP/git clients) don't exist yet, and the
   downstream crates WebTransport deferral blocks (SSH, git, SFTP)
   expose their ALPNs natively over QUIC regardless.

This is a scope decision (per ADR-009: a decision that 'genuinely
doesn't need to be made yet because the use case isn't concrete'), not
hedging. The reversal trigger is concrete: a real deployment needing
the ALPN-stream-proxy.

ADR-038 is superseded (its anti-pattern correction stands; its specific
'h3 in scope now' decision is reversed). ADR-040 and ADR-043 are
parked, not superseded — their designs revive unchanged when WebTransport
revives, with §2 (bidirectionality) and §3 (no-PeerId overlay) of ADR-043
transferring to WebSocket for v1.

ADR-044 §5 also states the 'browser is not a peer' rationale that
ADR-034 §4 closed without arguing: peer = addressable node in the
call-protocol peer graph (stable PeerId, PeerRef::Specific-reachable,
identity stable across reconnects), not 'any endpoint that exchanges
calls during a live session.' A browser is the second but not the first
(no stable crypto identity of its own, ephemeral, not addressable from
other nodes). ADR-034 §4 and Assumption 2 are amended by reference.

The wtransport-vs-hyperium dependency question is recorded (not
resolved — WebTransport is deferred) in ADR-044 §'Research note' and
webtransport.md so the revival doesn't re-derive it: wtransport probably
isn't the right choice (axum-bridge friction — it owns its own HTTP
serving path); the hyperium stack (h3 + h3-quinn + h3-webtransport) fits
the axum integration better but its server-side WebTransport API needs
verification before commitment.

Reviewed by architecture-review subagent; all critical cross-reference
issues (ADR-034 §5 stale 'in scope' assertion, ADR-036 Context listing
h3 as implemented, webtransport.md Design Decisions table) resolved.
2026-06-30 05:55:55 +00:00
..

status, last_updated
status last_updated
draft 2026-06-30

alknet-http

HTTP interface for alknet: serves HTTP/1.1 and HTTP/2 on standard ALPNs (with WebSocket upgrade for browser bidirectional access to the call protocol), and hosts the HTTP-backed call-protocol adapters (from_openapi, to_openapi, from_mcp, to_mcp). HTTP/3 + WebTransport (h3) is deferred per ADR-044.

Documents

Document Status Description
overview.md draft Crate purpose, two roles (server + client host), dependencies, adapter location map
http-server.md draft HttpAdapter (ProtocolHandler for h2/http/1.1 + WS upgrade), axum over QUIC, Bearer auth, stealth, /healthz, WebSocket browser path
http-adapters.md draft from_openapi (reqwest client) and to_openapi (OpenAPI projection); no-env-vars invariant point
http-mcp.md draft from_mcp / to_mcp (feature-gated), streamable-HTTP-only, stdio exclusion
webtransport.md deferred h3/WebTransport handler — deferred per ADR-044; spec kept intact for revival

Applicable ADRs

ADR Title Relevance
001 ALPN-Based Protocol Dispatch HttpAdapter registers on standard HTTP ALPNs
002 ProtocolHandler Trait HttpAdapter implements ProtocolHandler
003 Crate Decomposition alknet-http depends on alknet-core + alknet-call (protocol-foundation exception, Amendment 1)
004 Auth as Shared Core Bearer → resolve_from_token
007 BiStream Type Definition HttpAdapter receives Connection, accepts a stream for hyper
010 ALPN Router and Endpoint Stealth mode = HTTP handler on standard ALPNs
014 Secret Material Flow from_openapi/from_mcp are the credential injection point
015 Privilege Model Adapter-registered ops are Internal by default
017 Call Protocol Client and Adapter Contract OperationAdapter trait; to_* are projections; published-spec contract
022 Handler Registration, Provenance, Composition Authority from_openapi/from_mcp produce leaf bundles
023 Operation Error Schemas from_openapi/to_openapi error fidelity; HTTP_<status> error codes
027 TLS Identity Redesign Browsers require X.509; applies to WebTransport (deferred) and any browser-facing TLS
034 Outgoing-Only X.509 and Three Peer Roles Browsers are not alknet peers (§4 amended by ADR-044 §5 with the addressability rationale)
036 HTTP-to-Call Operation Mapping Direct path mapping; to_openapi is projection, not router
037 MCP Stdio Transport Exclusion Streamable HTTP only; stdio not built
038 HTTP/3 and WebTransport as First-Class HTTP Transports Superseded by ADR-044 (anti-pattern correction stands; specific decision reversed)
039 HTTP Server and Client Host Colocated in alknet-http One crate for server + client host (shared HTTP deps, shared mapping)
040 WebTransport ALPN-Stream-Proxy Parked per ADR-044; revives unchanged when WebTransport revives
041 MCP Tool-Gateway Pattern for to_mcp 4 fixed gateway tools (search/schema/call/batch), not one tool per operation; Subscription excluded
042 OpenAPI Gateway Pattern for to_openapi 5 fixed gateway endpoints (search/schema/call/batch/subscribe), not one path per operation; per-caller AccessControl-filtered
043 WebTransport as a Bidirectional ALPN Transport Substrate Parked per ADR-044; §2/§3 transfer to WebSocket for v1
044 Defer h3/WebTransport; Browsers Use WebSocket h3/WebTransport deferred (scope); browser bidirectional path uses WebSocket; "browser is not a peer" rationale

Relevant Open Questions

OQ Title Status Relevance
OQ-11 Handler-level auth resolution observability resolved HTTP handler stores resolved identity on Connection via set_identity
OQ-12 TLS identity provisioning resolved Browsers require X.509 (applies to WebTransport when it revives; WebSocket uses the same TLS as h2/http1.1)
OQ-13 Operation path format resolved /{service}/{op} is the HTTP path (ADR-036)
OQ-17 Call protocol client and adapter contract resolved OperationAdapter trait; to_* projections
OQ-24 Operation error schemas resolved from_openapi/to_openapi error fidelity
OQ-26 OperationAdapter error type resolved AdapterError variants reused by HTTP adapters
OQ-37 X.509 outgoing-only / three peer roles resolved Browsers are not peers; hub with mixed fingerprints
OQ-38 WebTransport standalone relay service scope open (scope, not deferral) The standalone relay (future alknet-relay, fork of iroh-relay) — distinct from the in-process ALPN-stream-proxy (ADR-040)
OQ-39 to_openapi published-spec versioning open Versioning strategy for generated OpenAPI specs
OQ-40 reqwest client config and connection pooling open Two-way-door: pooling/retry config shape

Key Design Principles

  1. HTTP is both a server surface and a client transport for adapters. Inbound HTTP (h2/http/1.1 + WebSocket upgrade) is served by axum over a QUIC stream; outbound HTTP (from_openapi/from_mcp forwarding) uses reqwest. Both directions share the same HTTP dependencies, which is why they live in one crate rather than being split. See overview.md.
  2. The HTTP surface is a projection of the call protocol. An HTTP request at POST /fs/readFile becomes a call.requested for /fs/readFile. The HTTP path IS the operation path on the direct-call surface. to_openapi describes a different surface — the 5-endpoint gateway (/search, /schema, /call, /batch, /subscribe) that gates discovery and invocation behind a fixed entry set. See ADR-036 (direct-call surface) and ADR-042 (to_openapi gateway, superseding ADR-036's original to_openapi clause).
  3. Standard ALPNs, not alknet ALPNs. h2, http/1.1 are IANA-registered ALPN strings. Any HTTP client (browser, curl, axios) connects without knowing about alknet — the TLS handshake negotiates h2 or http/1.1 normally. This is the stealth mapping (ADR-010).
  4. from_openapi/from_mcp are the no-env-vars injection point. The forwarding handlers read context.capabilities, not std::env::var. This is the architectural mechanism that makes aisdk's env-var reads unreachable. See ADR-014, client-and-adapters.md.
  5. MCP streamable HTTP only; stdio is not built. stdio = spawn arbitrary executable = RCE. Streamable HTTP is network-isolated, auth-gatable, and runs under alknet's auth model. See ADR-037.
  6. WebSocket is the browser bidirectional path. A browser upgrades an HTTP/1.1 or HTTP/2 request to WebSocket and speaks the call protocol over binary WS messages — full-duplex, both sides can initiate calls (the call protocol's native bidirectionality, ADR-012). HTTP/3 + WebTransport (h3) is deferred per ADR-044 — a scope decision (the browser bidirectional path doesn't require WebTransport's stream model; WebSocket suffices). The reversal trigger is a concrete ALPN-stream-proxy use case (a browser running a WASM SSH/SFTP/git client).
  7. Browsers are not alknet peers. A browser over WebSocket (or, when it revives, WebTransport) authenticates by bearer token, gets no PeerId, and its registered ops land in a connection-local Layer 2 overlay. "Peer" means an addressable node in the call-protocol peer graph (stable PeerId, PeerRef::Specific-reachable, identity stable across reconnects) — not "any endpoint that exchanges calls during a live session." A browser is the second but not the first: no stable cryptographic identity of its own, ephemeral, not addressable from other nodes. See ADR-034 §4 (amended by ADR-044 §5 with the addressability rationale).

References

  • docs/research/alknet-http/phase-0-findings.md — Phase 0 research (directionally close; DH-2's deferral framing was corrected by ADR-038, then ADR-038 was superseded by ADR-044 which re-defers h3/WebTransport as a genuine scope decision)
  • docs/research/alknet-call-completion/gap-analysis.md — adapter location map, no-env-vars invariant
  • /workspace/@alkdev/operations/src/from_openapi.ts, /workspace/@alkdev/operations/src/from_mcp.ts — TypeScript prior art
  • /workspace/rust-sdk/ — MCP Rust SDK (rmcp v1.8.0); streamable HTTP transport examples
  • /workspace/wtransport/ — pure-Rust WebTransport reference implementation (read during research; not a dependency. See ADR-044 §"Research note" for why wtransport is probably not the right revival choice — the hyperium stack fits the axum integration better.)