Files
alktls/docs/architecture/decisions/006-module-layout-and-tests.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

4.2 KiB
Raw Blame History

status, last_updated
status last_updated
accepted 2026-09-10

ADR-006: Module layout and test surface

Status

Accepted (2026-09-10)

Context

The extracted crate is organized as four modules plus the error (lib.rs, server.rs, client.rs, pem.rs, signing.rs) with all tests as in-module #[cfg(test)] blocks. alktls adds three modules of moved types (ADR-005) and, per the repo's conventions, needs a decided module map and test layout before the port starts.

Two shape questions need answers: where the moved types live relative to the config constructors, and how the seed tests port (no external workspace exists here, so in-module tests are the only cross-module surface a full-crate crate has).

Decision

Module layout (one module per file, re-exported from lib.rs):

src/
├── lib.rs          — crate docs, TlsError (ADR-002), re-exports
├── identity.rs     — TlsIdentity, Ed25519SecretKey, AcmeDirectory (ADR-005)
├── credentials.rs  — ConnectionCredentials, RemoteIdentity (ADR-005)
├── fingerprint.rs  — fingerprint_from_cert_der, extract_ed25519_raw_key_from_spki,
│                     DER parser (ADR-005)
├── server.rs       — TlsServerConfig, build_rustls_server_config,
│                     RawKeyCertResolver, AcceptAnyCertVerifier,
│                     SelfSignedCert / generate_self_signed_cert
├── client.rs       — TlsClientConfig, select_server_verifier,
│                     build_client_auth, RawKeyClientCertResolver,
│                     NoClientCertResolver, FingerprintPinVerifier,
│                     load_platform_root_cert_store
├── pem.rs          — load_cert_chain, load_private_key
└── signing.rs      — Ed25519SigningKey (rustls SigningKey + Signer)

Public API surface is lib.rs re-exports only (AGENTS.md convention 12); modules are pub for discoverability but the re-export block is the documented surface.

Feature gates stay on types and accessors, not modules. The noq feature gates for_noq() + NoqWrap; the tcp feature gates for_tcp_tls(); the acme feature gates the ACME branch of TlsServerConfig::new + the spawned task + the futures dep. Unlike the alktunnels/alktty backends, there are no substrate modules to gate — the transport-specific code is accessor-shaped.

Test surface:

  • Port the extracted crate's in-module tests as the seed (they assert the behavior-preservation invariants: max_early_data_size on the server paths, enable_early_data on the client config, the nine-scheme list, resolver behavior, PEM error paths, signing).
  • Add tests/ integration tests for the cross-module surfaces a single crate has: TlsServerConfig::newfor_noq() / for_tcp_tls() round-trips per identity variant; TlsClientConfig verifier selection matrix (Some/None × raw-key/X.509); the root-store fallback against an empty platform store; acme-tls/1 append on the ACME path only.
  • Pin the exact nine-scheme list in an integration test (Phase 0 OQ-TLS-05's regression-proof shape — the extracted in-module test only checks membership of two schemes), and pin enable_early_data = true on the client config (the client half of the 0-RTT invariant).
  • TlsIdentity::Acme's unreachable! in build_rustls_server_config becomes a config error (the extracted code relies on an internal dispatch invariant; the port replaces the unreachable! with the AcmeConfig variant, keeping no-panics-in-library-code).

Consequences

Positive:

  • The port is mechanically guided: module map + seed tests make the Phase 2 port a diff against the extracted source.
  • The invariant assertions move from "documented" to "tested" at both unit and integration level.

Negative:

  • Integration tests that wrap real QUIC endpoints are out of scope (they belong to transport crates); the seam tests assert config construction, not handshakes — the scope boundary holds.

References

  • AGENTS.md conventions 1, 9, 12 — comments, feature gates, module structure
  • docs/research/phase-0.md §Gaps #5, OQ-TLS-05 — the test-surface question
  • ADR-002 — TlsError (no Config(String) catch-all)
  • ADR-005 — the moved modules