The tasks were decomposed (d7db6b1) before 49d4432/ac440f3 landed;
both commits touched exactly the areas the tasks reference. Fixes
grounded in verified sources (vendored rustls-acme 0.12.1, rustls-pemfile
2.2.0, rustls-native-certs 0.8.4) and a fresh cargo llvm-cov run:
- acme-event-loop-test: the termination assertion was impossible —
rustls-acme's Stream for AcmeState never yields None
(state.rs:407-412, poll_next_infinite + 2^16s backoff); the review's
U-1 exit-condition premise is withdrawn and corrected in place.
Replaced with timeout-bounded event collection, a reachable-arm
inventory (Order warn, AccountCacheStore, Load/Parse error arms,
DeployedCachedCert/CertCacheStore via deterministic DirCache file
pre-seeding), and an explicit mark for the full-fake-CA arms.
server.rs:135 flagged as unreachable dead code (delete or accept).
- coverage-cheap-closes: re-baselined per-line ground truth — original
groups 1 and 5 are already closed by the handshake suites; group 2's
TLS 1.3 half is covered, leaving the TLS 1.2 else-arm (client.rs:316);
new group added for VerifyPresentedCertVerifier::verify_tls12_signature
(server.rs:349-366, opened by ADR-008; required for the >=98% bar);
AcceptAnyCertVerifier refs moved to server.rs:468-475 with the stale
OQ-TLS-09 coordination caveat retired.
- docs-pin-c1-c4-n3-n4: N-4 re-scoped (the mechanism analysis already
lives in ADR-007 + the resolver doc block; what remains is a short
server-verifier note covering both verifiers); C-4 updated for
ADR-007's negotiation-earlier failure point; added the
FingerprintPinVerifier pop cross-ref update (post-ADR-008 the default
verifier does verify possession).
- config-validation-and-trivia: added the feature-gate mechanics note
for the C-3 test (a non-gated test passes vacuously under default
features); refreshed drifted line refs with a re-grep advisory.
- review 001: Status block records OQ-TLS-09/-10 resolutions; U-1
carries the termination correction; U-2 carries the supersession
note. ADR-008 gains the suite-number-to-test-name mapping.
Verification: taskgraph validate 14 tasks; cargo doc --no-deps
warning-free; all edits docs-only (no code paths touched).
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.
Resolve the cert-type negotiation gap (review 001 §U-3, OQ-TLS-10) by
deviation from alknet: the gap was a defect in the prior art (alknet's
code never delivered its spec's raw-key-over-TCP promise — ADR-082
"works for both QUIC and TCP+TLS"), not behavior to preserve.
- FingerprintPinVerifier::requires_raw_public_keys() derives from the
pin format: ed25519: -> true (offer [RawPublicKey]), SHA256: ->
false (X.509 offer). Crate pin client now completes against the
crate raw-key server; SHA256: pins negotiate unchanged.
- RawKeyClientCertResolver presents the SPKI under the X.509 offer
(only_raw_public_keys() == false): a raw-only client offer can only
negotiate against a requires_raw server verifier, and
AcceptAnyCertVerifier correctly stays on the default (accepts both
cert types). The server extracts the ed25519: fingerprint from the
SPKI bytes either way.
- Fail-closed preserved and strengthened: an ed25519: pin against an
X.509 server now aborts at negotiation (suite 2b), never a
downgrade; no API change (no public signature affected; the fix is
invisible to consumers apart from working handshakes).
- tests/handshake_behavior.rs: suite 3 now runs crate-native (no
custom iroh-shaped verifier), new negotiation fail-closed suite,
suite 3b inverted to end-to-end success; invariant_pins.rs
resolver-offer assertions flipped; unused imports dropped.
- Docs: ADR-007 written; OQ-TLS-10 -> resolved-by-deviation;
client.md/server.md/overview/README/task postscript synced
(incl. the strict-foreign-server limit in ADR-007 §Limits).
Verification: cargo test 81 / --features tcp 94 / --all-features
105 green; clippy -D warnings clean (default + all-features); fmt
clean; cargo doc warning-free.
Checklist (all six PASS):
1. API surface == ADR-004 — every accessor signature verified verbatim
2. TlsError == ADR-002 — six variants, #[non_exhaustive], typed sources,
AcmeConfig holds exactly the two config-mismatch cases
3. Invariants: all five server invariants + client 0-RTT half +
fail-closed structure, each with a passing behavioral test at unit
and integration level
4. Deltas vs extraction: all ADR-pinned; two surfaced divergences
recorded as ADR amendments — zero un-pinned divergences remain
5. Feature hygiene: default = [] lean, tokio subset (no full),
doc comments on public API, no inline // comments, no panics
6. Docs sync: ADR-002 + ADR-003 amendment notes; overview/server/client
Draft → Reviewed; README carries the API-freeze lifecycle note
5 findings, all low severity, all resolved forward (table in task Notes)
Verification: cargo test (81), cargo test --all-features (92),
clippy -D warnings, fmt --check, doc --no-deps,
publish --dry-run — all green. API FROZEN for the alknet rewrite.