Files
alktls/docs/architecture/open-questions.md
T
glm-5.3-flash ac440f3a9a ADR-008: server-path possession verification — the verifying verifier is the default (OQ-TLS-09 resolved)
Close review 001 §S-1: the default client-cert verifier never checked
the client's CertificateVerify, so anyone holding a peer's *public*
cert/SPKI bytes (public by design — peers publish them to be dialable)
could complete a handshake as that peer, and the auth layer could not
detect it. The consumer designs are known (X.509 and raw-key TCP/QUIC
endpoints with identity-bearing clients), so implementing now — the
zero-consumer moment — avoids the guaranteed breaking republish of
flipping the default later.

- VerifyPresentedCertVerifier (new): request, don't require, verify
  possession — permissive verify_client_cert (self-signed chains and
  bare SPKIs stay valid presentation) + CertificateVerify routing by
  presented cert kind (Ed25519 SPKI -> verify_tls13_signature_with_
  raw_key both TLS versions; X.509 -> standard route), the same
  routing FingerprintPinVerifier implements. Nine-scheme list
  verbatim (shared fn, exact-list pin covers both).
- Default on every TlsServerConfig path — X509 / RawKey / SelfSigned
  / ACME (the verifier install is crate-side rustls in new_acme, not
  rustls-acme's).
- AcceptAnyCertVerifier stays public as the explicit no-pop escape
  hatch, no longer installed by any crate path.
- tests/impersonation_posture.rs: four pins — default rejects the
  attacker (X.509: UnsupportedSignatureAlgorithmForPublicKeyContext;
  raw-key: BadSignature), escape hatch still accepts + extracts the
  victim's fingerprint (both cert types).
- tests/handshake_behavior.rs: suites 4/4b — possession-checked legit
  clients (raw-key pin vs raw-key server; X.509 client vs X.509
  server) complete and the server extracts the fingerprint; suite 3b
  doc updated.
- Docs: ADR-008 written; OQ-TLS-09 -> resolved (option (b));
  ADR-007 §Limits deferral retired to not-planned; server.md/client.md
  invariants/README/overview synced.

Verification: cargo test 81 / --features tcp 95 / --all-features 104
green; clippy -D warnings clean (default + all-features); fmt clean;
cargo doc warning-free.
2026-09-11 11:12:48 +00:00

9.1 KiB

status, last_updated
status last_updated
draft 2026-09-11

Open Questions

Centralized tracker for alktls. Promoted from Phase 0 (docs/research/phase-0.md OQ-TLS-01..08) on 2026-09-10. Statuses here are authoritative; the Phase 0 doc's statuses are the historical record.

Statuses at a glance

OQ Topic Status Priority
OQ-TLS-01 Config-type ownership resolved (ADR-005) high
OQ-TLS-02 SelfSigned on the client path resolved (documented behavior kept) low
OQ-TLS-03 for_tcp_tls() adoption resolved (ADR-004) medium
OQ-TLS-04 Accessor borrow-vs-consume resolved (ADR-004) medium
OQ-TLS-05 Test surface resolved (ADR-006) low
OQ-TLS-06 ACME task shutdown surface resolved (detached-only for v1) low
OQ-TLS-07 iroh key surface resolved (ADR-005, byte access pinned) low
OQ-TLS-08 quinnnoq feature rename resolved (ADR-003) high
OQ-TLS-09 Server-path proof-of-possession resolved (ADR-008) high
OQ-TLS-10 RFC 7250 over TCP: cert-type negotiation gap resolved (ADR-007) high

Identity & types

OQ-TLS-01: Where do the config types live, and what moves?

  • Origin: docs/research/phase-0.md §Gaps #3
  • Status: resolved (2026-09-10)
  • Priority: high
  • Resolution: alktls owns the identity types (TlsIdentity, Ed25519SecretKey, AcmeDirectory), the credential bundle (ConnectionCredentials, RemoteIdentity), and the fingerprint helpers. The auth layer (PeerEntry, AuthPolicy, IdentityProvider) stays out — peer-level identity is not TLS. Decision recorded in ADR-005.
  • Cross-references: ADR-001, ADR-005

OQ-TLS-02: SelfSigned on the client path — encode or document?

  • Origin: docs/research/phase-0.md §Gaps #4
  • Status: resolved (2026-09-10)
  • Priority: low
  • Resolution: keep the current behavior (present nothing via NoClientCertResolver) and document it on the identity type and in the client spec. Type-level enforcement (config error, like Acme) was rejected: SelfSigned as a local identity meaning "present nothing" is coherent — the dev cert exists for the server side, and presenting a self-signed client cert would add nothing the fingerprint path uses.
  • Consequences: a future dev client-auth use case would need a type-level change (additive, not a one-way door).
  • Cross-references: ADR-001 (identity model), client spec

OQ-TLS-07: iroh relationship in the rewrite

  • Origin: docs/research/phase-0.md OQ-TLS-07
  • Status: resolved (2026-09-10)
  • Priority: low
  • Resolution: the requirement is pinned and verified — Ed25519SecretKey keeps 32-byte raw access (from_bytes / as_bytes) with the same byte-level surface iroh's iroh_base::SecretKey consumes (from_bytes / to_bytes; 32 raw bytes in/out — verified against iroh 1.1 in Phase 0). iroh stays key-not-config; no for_iroh(). The rewrite's iroh dial consumes the type alktls owns (ADR-005); no alktls-side work remains.
  • Cross-references: ADR-003, ADR-005

API surface

OQ-TLS-03: for_tcp_tls() — adopt the spec accessor?

  • Origin: docs/research/phase-0.md §Gaps #2
  • Status: resolved (2026-09-10)
  • Priority: medium
  • Resolution: adopted — for_tcp_tls(&self) -> tokio_rustls::TlsAcceptor, feature-gated on tcp, infallible. Decision and rationale in ADR-004.
  • Cross-references: ADR-004

OQ-TLS-04: for_quinn()self or &self?

  • Origin: docs/research/phase-0.md OQ-TLS-04
  • Status: resolved (2026-09-10)
  • Priority: medium
  • Resolution: server accessors take &self (one config feeds N transports — the ADR-082 story, directly expressible); client accessors consume self (per-dial build, zero-cost into_rustls_config). Full rationale in ADR-004.
  • Cross-references: ADR-003, ADR-004

OQ-TLS-08: quinn feature vs noq feature — and the MSRV floor

  • Origin: docs/research/phase-0.md §Prior art: noq
  • Status: resolved (2026-09-10)
  • Priority: high
  • Resolution: the feature is noq (no quinn feature ever published; rename is pre-consumer and free). noq 1.2 pinned ("1.2", default-features off, rustls feature), bump deliberately. The MSRV half of the OQ was separately resolved the same day (ecosystem floor 1.88; time pin dropped). Decision in ADR-003.
  • Cross-references: ADR-002, ADR-003, ADR-004

OQ-TLS-09: Which layer owns proof-of-possession on the server path?

  • Origin: docs/reviews/001-implementation-review.md §S-1 (the impersonation probe: a handshake with the victim's cert bytes + an attacker signer completes, and the server extracts the victim's fingerprint)
  • Status: resolved (2026-09-11) — option (b), ADR-008. VerifyPresentedCertVerifier is the default client-cert verifier on every TlsServerConfig path (including the ACME path — the verifier install is crate-side rustls, not rustls-acme's): request, don't require, verify the CertificateVerify against the presented cert's public key. The extracted fingerprint is possession-checked (attacker-supplied presentations fail the handshake — tests/impersonation_posture.rs pins both directions); who a fingerprint maps to remains the auth layer's concern (ADR-005). AcceptAnyCertVerifier stays public as the explicit no-pop escape hatch, its posture pinned by the same test file.
  • Cross-references: src/server.rs (VerifyPresentedCertVerifier, AcceptAnyCertVerifier), src/client.rs (FingerprintPinVerifier — the routing being mirrored), ADR-008, review 001 §S-1, alknet ADR-034

OQ-TLS-10: How do RFC 7250 raw-key peers negotiate over rustls-driven TCP+TLS?

  • Origin: tasks/handshake-tests.md (review 001 §U-3 execution): the executed handshake suites found that the crate's own pin client cannot complete a handshake against the crate's own raw-key server, and a raw-key client resolver cannot present itself to AcceptAnyCertVerifier — both fail with rustls' HandshakeFailure alert (cert-type negotiation), not a verification outcome. Verified empirically and against the rustls 0.23.44 sources (server/hs.rs::process_cert_type_extension, client/hs.rs::process_cert_type_extension); pinned by tests/handshake_behavior.rs.
  • Status: resolved (2026-09-11) — by deviation from alknet, ADR-007. Option (b) plus a resolver change: FingerprintPinVerifier::requires_raw_public_keys() derives from the pin format (ed25519:true, SHA256:false), and RawKeyClientCertResolver presents the SPKI under the X.509 offer (only_raw_public_keys() == false). The gap was a bug in the prior art (alknet's code never delivered its spec's raw-key-over- TCP promise), not an alknet behavior to preserve — so the behavior-preservation invariant does not cover it. The two pin formats negotiate independently (per-connection verifier, never shared); fail-closed is preserved and strengthened (an ed25519: pin against an X.509 server aborts at negotiation, never a downgrade). The original "defer until the first consumer" rationale was circular — the crate is the component that must enable the raw-key-over-TCP consumer, and the fix required no API change.
  • Cross-references: src/client.rs (FingerprintPinVerifier, RawKeyClientCertResolver), src/server.rs (RawKeyCertResolver, AcceptAnyCertVerifier), review 001 §N-4, ADR-007, iroh iroh/src/tls/verifier.rs (the working prior art)

Quality / process

OQ-TLS-05: Test surface for the invariants

  • Origin: docs/research/phase-0.md §Gaps #5
  • Status: resolved (2026-09-10)
  • Priority: low
  • Resolution: port the in-module seed tests AND add tests/ integration tests for the cross-module surfaces; pin the exact nine-scheme list (regression-proof). Decision in ADR-006.
  • Cross-references: ADR-006

OQ-TLS-06: Does the ACME state machine need a shutdown surface?

  • Origin: docs/research/phase-0.md OQ-TLS-06
  • Status: resolved (2026-09-10)
  • Priority: low
  • Resolution: detached-only — the handle is stored (keeping TlsServerConfig non-Clone) and never aborted; the ACME task runs for the process lifetime. Documented on the type.
  • Consequences: a shutdown() (abort + await) surface would be additive and cheap if the rewrite's graceful-shutdown design wants one later — not a one-way door.
  • Cross-references: ADR-001 (one-ACME-machine rule), server.md

Deferred / Blocked

None — all recorded OQs are resolved. Future questions (e.g. the raw-key-only server-verifier sibling if a foreign strict RFC 7250 server interop ever appears — see ADR-007 §Limits) get new OQ entries rather than reopening these.