Files
alknet/docs/architecture/questions/064-client-side-tls-helper.md
T
glm-5.2 bf6ce957c0 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.
2026-07-16 11:33:18 +00:00

3.5 KiB

OQ-64: Should alknet-tls Provide a Client-Side TLS Config Helper?

  • Origin: docs/architecture/crates/tls/README.md (the "Server-only for now" section flagged this as deferred); ADR-084 (requires the client-side rustls::ClientConfig to use the same aws_lc_rs provider — previously enforced by convention, not shared code).

  • Status: resolved

  • Door type: one-way (TlsClientConfig as the shared client-side TLS config in alknet-tls is structural — every outbound-dialing crate depends on it. Reversing would re-distribute verifier selection

    • provider wiring across crates.)
  • Priority: high (upgraded from medium — the hub-as-client requirement makes this a prerequisite for the first hub deployment, not a future extraction)

  • Resolution: Yes. alknet-tls provides TlsClientConfig. It is not blocked on the dial-seam extraction (OQ-55).

    The previous deferral linked OQ-64 and OQ-55 as "the same seam," creating a circular dependency: the TLS config is deferred behind the dial, but the dial needs the TLS config. The circle is broken by separating the two concerns:

    1. TlsClientConfig — the rustls::ClientConfig + ADR-034 verifier selection + ADR-084 crypto provider. Transport-agnostic. All decisions are made. Buildable today. It is a prerequisite for any dial, not a consequence of it.
    2. The dial (AlknetClient::dial()) — transport-specific connection establishment. Extracting a transport-polymorphic dial from one shape (QUIC) would bake QUIC in. Legitimate deferral (OQ-55, unchanged).

    TlsClientConfig::new takes a verifier context (the inputs to ADR-034's rule: PeerEntry presence, expected fingerprint, remote cert type) and returns a rustls::ClientConfig. The caller (transport-specific dial helper — now AlknetClient::dial_quic / dial_tcp_tls per ADR-089; the per-protocol CallClient::connect / ChannelClient::connect_quic convenience constructors are removed per ADR-089 §5) passes it to the transport's connector. Iroh is the exception — it has its own TLS and does not consume a rustls::ClientConfig; the iroh dial helper applies the same ADR-034 rule via iroh's NodeId verification API.

    The hub makes this non-optional: a hub dials out to workers it supervises and to other hubs (hub-as-client). The hub's dial_worker_connection / supervise_worker need a TlsClientConfig for the outbound dial. The first hub deployment (web + native) dials workers over QUIC with the worker's fingerprint pinned. There is no "later" — it is on the critical path for the first hub and for alknet-worker.

    See ADR-087 for the full decision, including the circular-hedge analysis, the hub-as-client requirement, and the iroh exception.

  • Cross-references: ADR-087 (the decision), ADR-034 §3 (verifier selection — the rule TlsClientConfig::new centralizes), ADR-084 (provider consistency — enforced by code, not convention, for the client side), ADR-082 (TlsServerConfig — the server-side analogue), OQ-55 (the dial seam — remains deferred; this OQ's resolution does not affect it), OQ-63 (TlsError shape — now covers both server and client variants)