docs(arch): unweld ChannelClient from QUIC — from_connection primary, connect_quic convenience (ADR-080 amendment)
The channels protocol is transport-agnostic by design (ADR-071 substrate
modes; ADR-065 unwound the server-side QUIC-welding via
Connection::from_stream/from_bidi). ADR-080 had welded the client-side
one-way-door API to QUIC and masked it as a deferral ('QUIC-only
initially', 'can be generalized later') — anti-patterns #8/#9/#11
(door-type-as-deferral + resolved-with-escape-hatch). 'Can be
generalized later' meant 'can be rewritten later' — the expensive
reversal the one-way-door classification exists to prevent.
Fix: split the constructor surface.
- from_connection(connection: Connection) — transport-agnostic primary,
one-way door. Mirrors server-side ChannelsAdapter::handle(Connection)
and the existing CallClient::spawn_dispatch pattern.
- connect_quic(addr, credentials) — QUIC convenience, two-way door,
additive. Future connect_tcp_tls / connect_webtransport join it
without touching the one-way-door surface.
OQ-55 reframed: the deferred thing is the shared dial+TLS seam
(AlknetClient), not a QUIC-welded client API. The client take-over APIs
(CallClient::spawn_dispatch, ChannelClient::from_connection) are
transport-agnostic and decided; only the shared dial across transports
is blocked on a second transport's dial existing.
Files:
- decisions/080-channelclient.md: amendment section, Decision code
block, Transport-agnostic by construction (replaces QUIC-only
initially), Consequences, Door type, subscribe_resources added to
Decision block (was referenced by Door type but missing)
- crates/channels/channel-client.md: from_connection primary API,
Transport-agnostic by construction section, OQ-55 relationship
- crates/channels/overview.md, crates/channels/README.md,
crates/core/README.md, README.md, open-questions.md,
questions/055-...md: cross-reference summaries aligned
This commit is contained in:
1 parent
3006e29afc
commit
73c621bf21
8 files changed
+276
-103
No files matched your search
@@ -8,14 +8,17 @@
|
||||
- **Status**: deferred(scope)
|
||||
- **Door type**: two-way
|
||||
- **Priority**: medium
|
||||
- **Blocked on**: a **second transport's** real client existing, not just a
|
||||
second QUIC client. The blocking condition is met when, e.g., the SSH
|
||||
crate's raw-TCP client or the HTTP-wrapped call client exists — so the
|
||||
transport-polymorphic establishment seam is extractable from two
|
||||
- **Blocked on**: a **second transport's** real dial existing, not just a
|
||||
second QUIC dial. The blocking condition is met when, e.g., the SSH
|
||||
crate's raw-TCP dial or the HTTP-wrapped call dial exists — so the
|
||||
transport-polymorphic dial+TLS seam is extractable from two
|
||||
*different* transport implementations, not two QUIC variants.
|
||||
`ChannelClient` over QUIC does not unblock this; it is a second *client*
|
||||
but the same *transport shape*. The deferral is on transport-polymorphism,
|
||||
not on client count.
|
||||
`ChannelClient`'s `connect_quic` does not unblock this; it is a second
|
||||
*client* but the same *transport shape*. `ChannelClient`'s
|
||||
`from_connection` (the transport-agnostic take-over, ADR-080) is decided
|
||||
and is not the thing being deferred — the shared *dial* is. The deferral
|
||||
is on transport-polymorphism of the dial, not on client count or on the
|
||||
channels protocol's API.
|
||||
- **Resolution**: Not yet decidable. The shared substance across
|
||||
TLS-carrying transports is ADR-034's verifier-selection rule (PeerEntry
|
||||
presence → fingerprint pin : CA-verify / fail-closed) and the
|
||||
@@ -23,25 +26,28 @@
|
||||
rule. But the *dial* is transport-specific, and we have one of ~5 shapes
|
||||
implemented (QUIC; the others being HTTP, TCP+TLS, WebTransport, raw
|
||||
TCP). Extracting a QUIC-shaped connector to core and naming it
|
||||
`AlknetConnector` would bake QUIC in as *the* establishment shape — the
|
||||
`AlknetClient` would bake QUIC in as *the* establishment shape — the
|
||||
same welding ADR-065 unwound on the server side, repeated on the client
|
||||
side. The dial is transport-polymorphic; the shared rule is narrow. Until
|
||||
a second transport's client exists, the seam between "dial + TLS" (per-
|
||||
a second transport's dial exists, the seam between "dial + TLS" (per-
|
||||
transport) and "spawn the dispatcher" (per-crate) is not extractable from
|
||||
two real shapes — it's guessable from one.
|
||||
- **What does NOT block on this**: each crate building its own client
|
||||
standalone. `CallClient` stays QUIC-only; `ChannelClient` will be
|
||||
QUIC-only initially; the SSH crate's TCP client builds standalone; the
|
||||
HTTP call client builds standalone. Core already permits all of this —
|
||||
`Connection::from_stream` / `from_bidi` (ADR-065) handles the non-QUIC
|
||||
transport on the server side, and nothing prevents a client from
|
||||
constructing a `Connection` the same way after its own transport-specific
|
||||
dial. The friction is duplicated boilerplate (each client rebuilds
|
||||
verifier selection), not a missing capability. The bidirectionality
|
||||
standalone, and each transport-specific dial helper. `CallClient`'s
|
||||
transport-agnostic take-over (`spawn_dispatch`) and `ChannelClient`'s
|
||||
transport-agnostic take-over (`from_connection`, ADR-080) are decided;
|
||||
`connect_quic` dials QUIC and calls `from_connection`. The SSH crate's
|
||||
TCP client, the HTTP call client, a `connect_tcp_tls` / `connect_webtransport` helper — each builds its own dial standalone. Core
|
||||
already permits all of this — `Connection::from_stream` / `from_bidi`
|
||||
(ADR-065) handles the non-QUIC transport on the server side, and nothing
|
||||
prevents a client from constructing a `Connection` the same way after
|
||||
its own transport-specific dial. The friction is duplicated boilerplate
|
||||
(each dial helper rebuilds verifier selection), not a missing
|
||||
capability and not a QUIC-welded client API. The bidirectionality
|
||||
criterion (a crate needs a Client type when (a) the endpoint has
|
||||
protocol-level authority — e.g., channels' id allocation — or (b) the
|
||||
protocol needs a reliable establishment interface) is met by each crate
|
||||
independently; `AlknetClient` is the eventual *shared* establishment seam,
|
||||
independently; `AlknetClient` is the eventual *shared dial+TLS seam*,
|
||||
not a prerequisite for any single client to exist.
|
||||
- **Cross-references**: ADR-034 (verifier selection — currently in
|
||||
`CallClient`, would move to the extracted seam when this is resolved),
|
||||
|
||||
Reference in new issue
Block a user