docs(arch): tighten tls/endpoint/client specs — remove connect/connect_quic, move CallCredentials to core, shed alknet-call TLS deps
Review of the three new crates (alknet-tls, alknet-endpoint, alknet-client) + revised core found compile-blocking inconsistencies, stale claims, and dep-graph contradictions. All resolved: Critical: - C1: CallClient::connect / ChannelClient::connect_quic REMOVED (not delegated) — keeping them as thin wrappers over AlknetClient::dial_quic would make protocol crates depend on alknet-client, contradicting the dep graph. Callers compose dial + take-over (2 lines). - C2: alknet-client feature gates now pull alknet-core/quinn + alknet-core/iroh (for Connection::from_quinn_with_alpn / from_iroh). - C3: rustls-native-certs + webpki-roots added to alknet-tls deps (always-present, not feature-gated — CA-verify path is transport-agnostic). Warning: - W1: CallCredentials/RemoteIdentity moved to alknet-core (from alknet-call) — the dial must not depend on the call protocol; not a two-way-door, it determines the dep graph. - W2: webpki-roots fallback implemented in spec (ADR-088 §5 added) — the code claimed a fallback that never existed; now the store is never empty, NoRootAnchors unreachable, containerized deployments work. - W3: EndpointError removed entirely (BindFailed + HandlerNotFound both vestigial after ADR-083); shutdown() is now infallible. - W4: FingerprintPinVerifier moved to alknet-tls (from alknet-call) — alknet-call sheds quinn/rustls/rustls-pemfile/rustls-native-certs entirely; CallClient becomes a pure protocol crate. Plus: ClientError removed (only produced by removed connect); S1 (CallCredentials → ClientVerifierContext mapping + auth_token stripped at TLS boundary documented); amendment notes on ADR-017, ADR-069, ADR-080, ADR-082, ADR-087, ADR-090; overview crate graph + README index updated. 29 files, consistency-reviewed.
This commit is contained in:
1 parent
34e3be2801
commit
bf6ce957c0
29 files changed
+524
-267
No files matched your search
@@ -24,7 +24,7 @@ protocol work itself.
|
||||
| [channels-connection.md](channels-connection.md) | draft | `ChannelBidiStreamSource` (implements `BidiStreamSource` — ADR-070/074), `into_sub_streams()` typed destructure, recursive composition |
|
||||
| [channels-adapter.md](channels-adapter.md) | draft | `ChannelsAdapter` (`ProtocolHandler` on `alknet/channels`), `ChannelManager`, demux/mux contracts (REQ-CH-01..04), the two-pump pattern (ADR-078) |
|
||||
| [channel-operations.md](channel-operations.md) | draft | `channel/open`, `channel/close`, `channel/control`, `channel/resources/subscribe` — call-protocol operations on channel 0, ACL flow, `direction` semantics, the hub relay contract (ADR-079) |
|
||||
| [channel-client.md](channel-client.md) | draft | `ChannelClient` — the client side of a channels connection; transport-agnostic `from_connection` primary, `connect_quic` convenience; bidirectionality preserved |
|
||||
| [channel-client.md](channel-client.md) | draft | `ChannelClient` — the client side of a channels connection; transport-agnostic `from_connection` primary; `connect_quic` removed per ADR-089 §5 (dial extracted to `AlknetClient`); bidirectionality preserved |
|
||||
|
||||
## Applicable ADRs
|
||||
|
||||
@@ -39,7 +39,7 @@ protocol work itself.
|
||||
| [077](../../decisions/077-tty-inside-channels.md) | TTY Inside Channels — Sub-Streams, Not Wire Format | TTY's two modes (direct vs channels); 5 sub-streams; control bidirectional via 3/4; amends ADR-052 scope |
|
||||
| [078](../../decisions/078-two-pump-shutdown-on-completion.md) | Two-Pump Shutdown-on-Completion Pattern | The two-pump deadlock contract; handler-level, not channels-layer |
|
||||
| [079](../../decisions/079-hub-relay-translate-not-forward.md) | Hub Relay — Translate, Not Transparently Forward | The hub translates channel 0, byte-forwards data channels with ID rewrite |
|
||||
| [080](../../decisions/080-channelclient.md) | ChannelClient — the Client Side of a Channels Connection | `ChannelClient`, transport-agnostic `from_connection` primary + `connect_quic` convenience; `AlknetClient` dial-seam extracted (ADR-089, resolves OQ-55) |
|
||||
| [080](../../decisions/080-channelclient.md) | ChannelClient — the Client Side of a Channels Connection | `ChannelClient`, transport-agnostic `from_connection` primary; `connect_quic` removed per ADR-089 §5 (dial extracted to `AlknetClient`); `AlknetClient` dial-seam extracted (ADR-089, resolves OQ-55) |
|
||||
| [081](../../decisions/081-channels-subcrate-decomposition.md) | channels Sub-Crate Decomposition | `channels-core` (pure multiplexer) / `channels-call` (call coupling + ChannelClient); hub and worker are consumers, not sub-crates |
|
||||
| [070](../../decisions/070-bidistreamsource-trait.md) | BidiStreamSource Trait | The `Connection` extension point `ChannelBidiStreamSource` implements |
|
||||
| [065](../../decisions/065-connection-from-stream-generic-single-stream.md) | `Connection::from_stream` | The transport-agnostic `Connection` the channels layer rides on |
|
||||
@@ -52,7 +52,7 @@ protocol work itself.
|
||||
|
||||
| OQ | Title | Status | Relevance |
|
||||
|----|-------|--------|-----------|
|
||||
| OQ-55 | AlknetClient / Client Establishment Extraction | resolved (ADR-089) | `ChannelClient`'s API is decided (ADR-080): transport-agnostic `from_connection` primary, `connect_quic` convenience. `AlknetClient` core extraction is now resolved — the native dial seam is `alknet-client` (ADR-089) |
|
||||
| OQ-55 | AlknetClient / Client Establishment Extraction | resolved (ADR-089) | `ChannelClient`'s API is decided (ADR-080): transport-agnostic `from_connection` primary; `connect_quic` removed (ADR-089 §5). `AlknetClient` core extraction is now resolved — the native dial seam is `alknet-client` (ADR-089) |
|
||||
| OQ-56 | Full channel-level flow-control windowing | deferred(scope) | Bounded-buffer is decided (ADR-076); full windowing is an extension blocked on "a real deployment observes HOL blocking on a saturated channel where bounded buffer is insufficient" |
|
||||
| OQ-57 | Two-pump helper extraction to alknet-core | deferred(scope) | The shutdown-on-completion *contract* is decided (ADR-078); the *helper* extraction is blocked on a second two-pump handler existing (shape convergence) |
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ impl ChannelClient {
|
||||
/// it is additive over `from_connection` and is a two-way door —
|
||||
/// `connect_tcp_tls`, `connect_webtransport`, etc. can be added
|
||||
/// alongside it without touching the one-way-door surface.
|
||||
///
|
||||
/// **REMOVED per ADR-089 §5.** The dial is extracted into
|
||||
/// `AlknetClient` (`alknet-client`); `connect_quic` is deleted,
|
||||
/// not delegated, to avoid `alknet-channels-call` depending on
|
||||
/// `alknet-client`. Callers compose `AlknetClient::dial_quic` +
|
||||
/// `from_connection`. See "Relationship to `AlknetClient`" below.
|
||||
pub async fn connect_quic(
|
||||
addr: SocketAddr,
|
||||
credentials: CallCredentials,
|
||||
@@ -130,19 +136,19 @@ a WebTransport `BiStream`, an SSH `direct-tcpip` channel wrapped via
|
||||
ADR-044) — all produce a `Connection` that `from_connection` accepts
|
||||
unchanged. This mirrors the server side's `ChannelsAdapter::handle(Connection)`, which is substrate-agnostic by the same mechanism.
|
||||
|
||||
`connect_quic(addr, credentials)` is a **convenience** constructor — dial
|
||||
QUIC, then `from_connection`. It is additive and two-way-door: transport-specific dial helpers (`connect_tcp_tls`, `connect_webtransport`, …)
|
||||
join it as transports are added, none of which touch the `from_connection`
|
||||
contract. The dial helper set is open-ended by design.
|
||||
`connect_quic(addr, credentials)` was a **convenience** constructor —
|
||||
dial QUIC, then `from_connection`. It is **removed** per ADR-089 §5:
|
||||
keeping it as a thin wrapper over `AlknetClient::dial_quic` would make
|
||||
`alknet-channels-call` depend on `alknet-client`, contradicting the dep
|
||||
graph (the protocol crates are parallel to the dial, not downstream of
|
||||
it). Callers compose `AlknetClient::dial_quic(...).await?` +
|
||||
`ChannelClient::from_connection(conn).await?` — two lines, the dial
|
||||
then the take-over.
|
||||
|
||||
The credential/verifier-selection rule (ADR-034) lives in the transport's
|
||||
own dial path, not in `from_connection` — `from_connection` receives an
|
||||
already-established, already-authenticated `Connection`, exactly as
|
||||
`ChannelsAdapter::handle` does on the server side. The ~20 lines of
|
||||
verifier-selection boilerplate each dial helper rebuilds is the known
|
||||
duplicated cost of not having `AlknetClient` (OQ-55) extracted yet;
|
||||
`from_connection` keeps that boilerplate on the *transport-specific dial*
|
||||
side, not on the channels protocol's one-way-door surface.
|
||||
The credential/verifier-selection rule (ADR-034) lives in the dial
|
||||
(`AlknetClient`), not in `from_connection` — `from_connection` receives
|
||||
an already-established, already-authenticated `Connection`, exactly as
|
||||
`ChannelsAdapter::handle` does on the server side.
|
||||
|
||||
## Bidirectionality preserved
|
||||
|
||||
@@ -170,8 +176,8 @@ provides `AlknetClient` with three dial methods (`dial_quic` /
|
||||
TCP+TLS, iroh); the take-over (`from_connection`) is
|
||||
transport-agnostic. The two concerns are separated.
|
||||
|
||||
`connect_quic` becomes a thin wrapper over `AlknetClient::dial_quic` —
|
||||
dial QUIC, then `from_connection`. A caller that needs transport
|
||||
`connect_quic` is removed (see above) — `AlknetClient::dial_quic` is the
|
||||
dial that feeds `from_connection`. A caller that needs transport
|
||||
selection (QUIC with TCP+TLS fallback) uses `AlknetClient` directly;
|
||||
the fallback policy is a caller concern. See
|
||||
[ADR-089](../../decisions/089-alknetclient-native-dial-seam.md) for the
|
||||
@@ -184,7 +190,7 @@ All design decisions are documented as ADRs in [decisions/](../../decisions/).
|
||||
|
||||
| ADR | Decision | Summary |
|
||||
|-----|----------|---------|
|
||||
| [080](../../decisions/080-channelclient.md) | ChannelClient | Client side; transport-agnostic `from_connection` primary, `connect_quic` convenience; `AlknetClient` dial-seam extracted (ADR-089, resolves OQ-55) |
|
||||
| [080](../../decisions/080-channelclient.md) | ChannelClient | Client side; transport-agnostic `from_connection` primary; `connect_quic` convenience **removed** per ADR-089 §5 (dial extracted to `AlknetClient`); `AlknetClient` dial-seam extracted (ADR-089, resolves OQ-55) |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ All design decisions are documented as ADRs in [decisions/](../../decisions/).
|
||||
| [077](../../decisions/077-tty-inside-channels.md) | TTY Inside Channels | Two modes (direct vs channels); 5 sub-streams; control bidirectional via 3/4 |
|
||||
| [078](../../decisions/078-two-pump-shutdown-on-completion.md) | Two-Pump Pattern | Shutdown-on-completion contract; handler-level |
|
||||
| [079](../../decisions/079-hub-relay-translate-not-forward.md) | Hub Relay | Translate channel 0, byte-forward data channels with ID rewrite |
|
||||
| [080](../../decisions/080-channelclient.md) | ChannelClient | Client side; transport-agnostic `from_connection` primary, `connect_quic` convenience; `AlknetClient` dial-seam extracted (ADR-089, resolves OQ-55) |
|
||||
| [080](../../decisions/080-channelclient.md) | ChannelClient | Client side; transport-agnostic `from_connection` primary; `connect_quic` removed per ADR-089 §5 (dial extracted to `AlknetClient`); `AlknetClient` dial-seam extracted (ADR-089, resolves OQ-55) |
|
||||
| [081](../../decisions/081-channels-subcrate-decomposition.md) | Sub-Crate Decomposition | `channels-core` (pure multiplexer) / `channels-call` (call coupling + ChannelClient); hub and worker are consumers |
|
||||
|
||||
## Open Questions
|
||||
|
||||
Reference in new issue
Block a user