review-001 decomposition: 6 remediation tasks from verified findings
Verify every review-001 finding before decomposition: - S-1 re-confirmed by fresh executable probe (X.509 + raw-key impersonation both complete the handshake with the victim's fingerprint extracted server-side) - U-2/U-3 uncovered-line inventory re-derived from cargo llvm-cov (--all-features); matches Part C exactly - rcgen 1975/4096 defaults, rustls cert-type negotiation arm, packaging list, doc texts: all verified against sources Tasks (all verified, none speculative): - fix-accept-any-cert-verifier-posture (S-1 + N-1 + OQ-TLS-09 + probe) - handshake-tests (U-3 suites 1-3; suite 4 lives in the S-1 task) - coverage-cheap-closes (U-2's seven groups) - acme-event-loop-test (U-1; depends on coverage-cheap-closes for the tracing-capture pattern) - config-validation-and-trivia (C-2 ALPN dedup, C-3 empty-domains, N-6 excludes, N-7 https doc line) - docs-pin-c1-c4-n3-n4 (C-1, C-4, N-3 decision note, N-4 negotiation note) Graph: acme-event-loop-test is generation 2; the rest run in generation 1. taskgraph validate: 14 tasks, no cycles. Verification: cargo test (default + --all-features) green before and after; probe file deleted after its run.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
---
|
||||
id: config-validation-and-trivia
|
||||
name: Config robustness + trivia batch — ALPN dedup, empty-domains validation, packaging excludes, https doc line (C-2, C-3, N-6, N-7)
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: narrow
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [robustness, packaging, docs, review-001, c2, c3, n6, n7]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Four small findings in one pass (all verified in the decomposition
|
||||
session):
|
||||
|
||||
1. **C-2** — `acme-tls/1` is appended unconditionally
|
||||
(src/server.rs:87-89); a caller who already includes it in `alpns`
|
||||
gets it twice (probed: `alpn_protocols == [acme-tls/1, acme-tls/1]`).
|
||||
Harmless to rustls-acme's challenge dispatch today, but the
|
||||
duplication leaks into the wire config and the ACME/non-ACME
|
||||
asymmetry is undocumented. Fix: a one-line
|
||||
`if !alpn.contains(&b"acme-tls/1".to_vec())` guard — **or** pin the
|
||||
current shape in a doc note + test. The guard is the better
|
||||
default (idempotent construction), but either way a test pins the
|
||||
chosen shape.
|
||||
2. **C-3** — `TlsIdentity::Acme` with an **empty** `domains` list
|
||||
constructs successfully (probed) and spawns the order loop that
|
||||
then fails per-order at runtime as logged-only events. A one-line
|
||||
validation (`if domains.is_empty() { return
|
||||
Err(TlsError::AcmeConfig("empty domain list".into())) }`) at
|
||||
construction is additive and cheap. Note: empty `contact` stays
|
||||
legal (RFC 8555 §7.3 allows zero-contact accounts) — do NOT
|
||||
validate that.
|
||||
3. **N-6** — `tasks/*.md` and `docs/architecture/**` ship in the
|
||||
published package (`cargo package --list` re-verified). One-line
|
||||
`exclude` addition: `"tasks/`, `"docs/architecture/` per the
|
||||
alktunnels house pattern (internal SDD notes + architecture docs
|
||||
don't belong in the public package).
|
||||
4. **N-7** — `AcmeDirectory::Custom(String)` accepts any string and
|
||||
the URL goes to rustls-acme verbatim, so an `http://` custom
|
||||
directory silently runs ACME over plaintext (token-bearing). One
|
||||
doc line on the variant ("must be an `https://` ACME directory
|
||||
URL") closes it. Do not add runtime URL validation — the doc line
|
||||
is the fix (a caller pointing at a non-https *test* directory
|
||||
should not be blocked).
|
||||
|
||||
## Work
|
||||
|
||||
1. C-2: the dedup guard (preferred) + a test pinning
|
||||
idempotence (caller-supplied `acme-tls/1` → single entry).
|
||||
2. C-3: the empty-domains validation + a test
|
||||
(`TlsServerConfig::new(&Acme{domains: vec![]}, ..)` →
|
||||
`TlsError::AcmeConfig`), feature-gated like the existing ACME
|
||||
tests.
|
||||
3. N-6: `exclude = [... , "tasks/", "docs/architecture/"]`;
|
||||
re-run `cargo package --list --allow-dirty` + `cargo publish
|
||||
--dry-run --allow-dirty`.
|
||||
4. N-7: the doc line on `AcmeDirectory::Custom`.
|
||||
|
||||
## Verification
|
||||
|
||||
- [ ] Dedup: caller-supplied `acme-tls/1` yields exactly one entry
|
||||
(test pinned)
|
||||
- [ ] Empty-domains ACME construction errors with
|
||||
`TlsError::AcmeConfig` (test pinned)
|
||||
- [ ] `cargo package --list --allow-dirty` contains neither `tasks/`
|
||||
nor `docs/architecture/`; `cargo publish --dry-run
|
||||
--allow-dirty` passes
|
||||
- [ ] The `Custom` variant's doc states the https requirement
|
||||
- [ ] `cargo test`, `--all-features`, clippy, fmt, doc green
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] All four findings resolved (or explicitly doc-pinned with a
|
||||
test, per finding)
|
||||
- [ ] No behavior change beyond the three intended ones
|
||||
|
||||
## References
|
||||
|
||||
- docs/reviews/001-implementation-review.md §C-2, §C-3, §N-6, §N-7
|
||||
- src/server.rs:87-89 (ALPN append), src/server.rs:62-76
|
||||
(`new_acme` — where the domains validation goes),
|
||||
src/identity.rs:64-66 (`AcmeDirectory::Custom`), Cargo.toml:11
|
||||
(exclude list)
|
||||
|
||||
## Notes
|
||||
|
||||
> Agent fills this during implementation.
|
||||
|
||||
## Summary
|
||||
|
||||
> Agent fills this on completion.
|
||||
Reference in New Issue
Block a user