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.
This commit is contained in:
1 parent
865fef6210
commit
2aa6363e57
20 files changed
+782
-87
No files matched your search
@@ -198,4 +198,60 @@ pub enum HandlerError {
|
||||
- iroh Router pattern: `docs/research/references/iroh/`
|
||||
- Reference implementation: `alknet-main/crates/alknet-core/src/server/serve.rs`
|
||||
- Reference stealth mode: `alknet-main/crates/alknet-core/src/server/stealth.rs`
|
||||
- Reference iroh transport: `alknet-main/crates/alknet-core/src/transport/iroh_transport.rs`
|
||||
- Reference iroh transport: `alknet-main/crates/alknet-core/src/transport/iroh_transport.rs`
|
||||
|
||||
## Amendments
|
||||
|
||||
### Amendment 1 (2026-07-09): TCP+TLS can dispatch through the ALPN router via `from_stream`
|
||||
|
||||
This ADR's Decision section states: **"TCP mode is not an endpoint concern."**
|
||||
The rationale was that bare TCP (SSH over port 22) does not use QUIC or
|
||||
ALPN, so TCP access is handled by individual handlers listening on a TCP
|
||||
socket independently — a handler-specific concern, not a core endpoint
|
||||
concern.
|
||||
|
||||
That rationale holds for *bare TCP* (no TLS, no ALPN). But
|
||||
**[ADR-065](065-connection-from-stream-generic-single-stream.md)** adds
|
||||
`Connection::from_stream` / `from_bidi`, which construct a `Connection`
|
||||
from any `AsyncRead + AsyncWrite` pair — including a
|
||||
`TlsStream<TcpStream>`. A TCP+TLS accept loop can now call
|
||||
`Connection::from_bidi(tls_stream, alpn, remote_addr)` and dispatch through
|
||||
the **same `HandlerRegistry`** as QUIC connections, by the ALPN negotiated
|
||||
in the TLS handshake. This is not a parallel listener bypassing the core —
|
||||
it's the same ALPN dispatch, over a non-QUIC transport.
|
||||
|
||||
**Revised reading of "TCP is not an endpoint concern":** the
|
||||
`AlknetEndpoint` struct (quinn + iroh) remains QUIC-only — the endpoint
|
||||
does not own a TCP+TLS accept loop. But a TCP+TLS accept loop can be
|
||||
constructed *outside* the endpoint (by the assembly layer or a handler)
|
||||
and feed connections into the same `HandlerRegistry` the endpoint uses.
|
||||
The endpoint is one accept-loop source; a TCP+TLS loop is another source
|
||||
that shares the registry. The "not an endpoint concern" framing is
|
||||
preserved at the struct level (no `tcp: Option<TcpListener>` on
|
||||
`AlknetEndpoint`); the "TCP can't participate in ALPN dispatch" framing
|
||||
is **reversed** — `from_stream` is the primitive that lets TCP+TLS
|
||||
participate without changing the endpoint design.
|
||||
|
||||
The unblocked follow-ups (not part of ADR-065, but enabled by it):
|
||||
|
||||
- **Standard HTTP over TCP+TLS** (`api.alk.dev`'s requirement): a TLS
|
||||
accept loop wraps each `TlsStream<TcpStream>` as a `Connection` via
|
||||
`from_bidi` and dispatches to `HttpAdapter` by the negotiated ALPN
|
||||
(`h2`/`http/1.1`). `HttpAdapter::handle` calls `accept_bi` once (yielded
|
||||
by the single stream), then runs hyper over it — unchanged from the
|
||||
QUIC path. No handler code changes.
|
||||
- **SSH channel dispatch**: an SSH handler wraps each russh channel as a
|
||||
`Connection` via `from_stream` and dispatches by channel-type (treated as
|
||||
the ALPN string) through `HandlerRegistry`. One SSH connection carries
|
||||
heterogeneous channels — a multiplexing power QUIC's per-connection ALPN
|
||||
doesn't provide natively.
|
||||
- **WebTransport stream dispatch** (parked per ADR-044, unblocked
|
||||
structurally): the WT handler wraps each WT stream via `from_stream`.
|
||||
|
||||
The `iroh 0.35 → 1.0.2` migration (commit `acd049e`, 2026-07-09) is a
|
||||
related cleanup: it bumps the iroh dep to 1.0, unblocking `alknet-blobs`
|
||||
(which pulls `iroh 1.0` transitively). It is not an architectural change —
|
||||
6 API surface edits in `endpoint.rs` / `types.rs` (the `Endpoint::builder`
|
||||
preset, `SecretKey::from_bytes`/`generate` signatures,
|
||||
`Connection::remote_id`/`alpn` return types). No ADR needed; the endpoint
|
||||
design is unchanged.
|
||||
Reference in new issue
Block a user