Files
alktls/docs/architecture/decisions/003-noq-replaces-quinn.md
T
glm-5.3-flash d74a27f764 phase 1: architecture spec — overview, server/client, ADR-001..006
- ADR-001: inherit the alknet TLS design as the baseline; deviations
  recorded as alktls ADRs
- ADR-002: TlsError ships the ADR-088 six-variant shape from day one
  (typed #[from] sources; NoqWrap; no string catch-all)
- ADR-003: the QUIC feature is noq (iroh's extracted fork), pre-
  consumer rename; default = [] per the lean-crate convention
  (corrects the extracted code's default = ["quinn"])
- ADR-004: complete accessors — for_tcp_tls() adopted, rustls_config()
  adopted; server accessors borrow (&self), client accessors consume
- ADR-005: identity + credentials + fingerprint types move into
  alktls; auth layer stays out
- ADR-006: eight-module layout; seed tests + integration invariant
  pins (exact nine-scheme list, client enable_early_data)
- specs: overview (transport picture, terminology), server.md (ACME
  lifecycle, invariants), client.md (verifier selection matrix, root-
  store fallback); open-questions.md promotes OQ-TLS-01..08 (all
  resolved at entry)
- Cargo.toml: quinn feature -> noq (per ADR-003); AGENTS.md aligned

Architecture review pass done: 0 critical, 2 major (ADR-002 AcmeConfig
doc comment contradiction; ADR-003 unrecorded default deviation) and
8 minors all addressed; cross-references verified against alknet ADRs,
rustls/noq/iroh sources.

Verified: cargo test, test --all-features, clippy -D warnings,
fmt --check, doc --no-deps
2026-09-10 05:37:55 +00:00

119 lines
4.6 KiB
Markdown

---
status: accepted
last_updated: 2026-09-10
---
# ADR-003: The QUIC feature is `noq`, not `quinn`
## Status
Accepted (2026-09-10)
## Context
The extracted crate's `quinn` feature (`for_quinn()` accessors,
quinn-gated wrap) predates the noq split: iroh has extracted its
internal quinn fork into the standalone, published `noq` project
(`noq` / `noq-proto` / `noq-udp`; noq 1.2.0 on crates.io), and iroh
1.1.0 is built on noq 1.2.0, re-exporting `noq::*` as public API.
The alknet rewrite will standardize on noq for QUIC — both the bare
QUIC transport and iroh's internal one — eliminating the duplicate
QUIC implementations.
Phase 0 verified the seam is API-compatible with quinn 0.11
(`docs/research/phase-0.md` §Prior art: noq):
- `noq_proto::crypto::rustls::QuicServerConfig::try_from(
rustls::ServerConfig)` / `QuicClientConfig::try_from(
rustls::ClientConfig)` — same constructor shape, same
`NoInitialCipherSuite` failure type, different crate path.
- noq 1.2 pins `rustls ^0.23.33`; iroh 1.1 pins `rustls 0.23.33` —
the same 0.23 line this crate pins. One rustls tree across all
paths.
- noq's `rustls-aws-lc-rs` feature selects the aws-lc-rs provider;
iroh's `tls-aws-lc-rs` does the same on the iroh side. The ADR-084
posture composes unchanged.
- noq's MSRV is 1.88 — the ecosystem floor (adopted 2026-09-10),
so no MSRV tension remains.
The `quinn` feature has no published consumer: alktls is
pre-consumer, and the alknet rewrite (its only planned consumer)
targets noq. Carrying both features would double the accessor surface
with nothing to transition.
## Decision
**The QUIC feature is `noq`.** The `quinn` feature never existed in a
published alktls, so the rename is pre-consumer and free:
```toml
[features]
default = []
noq = ["dep:noq", "dep:noq-proto"]
tcp = ["dep:tokio-rustls"]
acme = ["dep:rustls-acme"]
[dependencies]
noq = { version = "1.2", optional = true, default-features = false, features = ["rustls"] }
noq-proto = { version = "1.2", optional = true, default-features = false }
```
`default = []` — all transport features opt-in, matching the
inherited alknet spec's feature-gate shape and AGENTS.md convention 9
(the default crate compiles lean; a consumer that never runs QUIC
should not pull `noq` + `noq-proto`). Note the extracted code's
`Cargo.toml` carries `default = ["quinn"]` — a silent deviation from
the alknet spec that this port corrects rather than carries forward.
The `noq` dep is enabled with `default-features = false,
features = ["rustls"]` so noq's provider-selection features do not
fight the crate's explicit provider posture; `noq-proto` rides along
for the `NoqWrap` error source.
- `TlsServerConfig::for_noq(&self) -> Result<noq::ServerConfig,
TlsError>` (feature-gated on `noq`) —
`noq::ServerConfig::with_crypto(Arc::new(
noq::crypto::rustls::QuicServerConfig::try_from(inner)?))`.
- `TlsClientConfig::for_noq(self) -> Result<noq::ClientConfig,
TlsError>` (feature-gated on `noq`) — the client-side mirror.
- `TlsError::NoqWrap(#[from]
noq_proto::crypto::rustls::NoInitialCipherSuite)` (ADR-002).
- There is no `for_quinn()`, no `quinn` dependency, no quinn feature.
- iroh remains key-not-config (ADR-001): iroh's endpoint is fed the
Ed25519 secret key; the `noq` feature does not attempt to serve
iroh's TLS, and iroh does not appear in this crate's dependency
tree.
- The `tcp` feature (`tokio-rustls`) and `acme` feature are
unaffected.
Provider wiring on the QUIC path: the rustls configs this crate builds
already carry the aws-lc-rs provider (every path constructs its own
provider via `builder_with_provider`); noq's `rustls` feature
consumes that provider from the config.
## Consequences
**Positive:**
- One QUIC implementation across the bare-QUIC and iroh transports;
no duplicate quinn/noq stacks in the rewrite's binaries.
- `TlsError` never has a dead `QuinnWrap` variant.
- The crate's MSRV floor (1.88) is honest for the whole tree rather
than feature-dependent.
**Negative:**
- If a future consumer needs quinn (none is known), that is a new
feature alongside `noq` — additive, cheap, and only paid if real.
- noq is young (1.2.0, first release Feb 2026); its API may churn
faster than quinn 0.11's frozen line (accepted — n0-computer owns
both noq and iroh, and the rewrite rides their stack; pin `noq =
"1.2"` and bump deliberately).
## References
- `docs/research/phase-0.md` §Prior art: noq — the verified seam facts
- `/workspace/noq`, `/workspace/iroh` — the upstream clones inspected
- ADR-001 — the inheritance baseline (quinn-era accessors inherited
with deviations recorded here)
- ADR-002 — `TlsError` (`NoqWrap`)
- ADR-004 — accessor shapes (`&self` vs `self`)