config robustness + trivia batch: ALPN dedup, empty-domains validation, packaging excludes, https doc line (C-2, C-3, N-6, N-7)

- C-2: new_acme dedups the acme-tls/1 ALPN append (idempotent
  construction); ACME/non-ACME ALPN asymmetry documented on
  TlsServerConfig::new; pinned by
  new_acme_caller_supplied_acme_tls_alpn_is_not_duplicated
- C-3: new_acme rejects an empty domains list with
  TlsError::AcmeConfig before spawning the order loop; contact stays
  unvalidated (RFC 8555 7.3 zero-contact accounts are legal); pinned
  by new_acme_empty_domains_returns_config_error (acme-gated)
- N-6: Cargo.toml exclude gains tasks/ and docs/architecture/
- N-7: AcmeDirectory::Custom documents the https-only caller contract
  (no runtime validation, per finding)

Verification: cargo test (default) and --all-features (77 lib tests,
2 new), clippy -D warnings, fmt --check, doc, package --list (no
tasks/ or docs/architecture/), publish --dry-run — all green
This commit is contained in:
2026-09-12 04:25:55 +00:00
parent 23893d6236
commit 9bdc32d848
4 changed files with 105 additions and 6 deletions
+42 -3
View File
@@ -1,7 +1,7 @@
---
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
status: completed
depends_on: []
scope: narrow
risk: low
@@ -96,8 +96,47 @@ session):
## Notes
> Agent fills this during implementation.
- C-2: implemented the dedup guard (preferred option) in `new_acme`
`if !alpn.contains(&b"acme-tls/1".to_vec())` before the push. Also
documented the ACME/non-ACME ALPN asymmetry on
`TlsServerConfig::new` (ACME always serves `acme-tls/1`, appended
idempotently; non-ACME uses the caller's list verbatim). Pinned by
`new_acme_caller_supplied_acme_tls_alpn_is_not_duplicated`
(`src/server.rs`, `#[cfg(feature = "acme")]`).
- C-3: added the empty-domains validation at the top of `new_acme`
(before any `AcmeConfig` construction or task spawn) returning
`TlsError::AcmeConfig("TlsIdentity::Acme requires a non-empty domain
list")`. `contact` left unvalidated per the finding (RFC 8555 §7.3
zero-contact accounts are legal). Test
`new_acme_empty_domains_returns_config_error` is
`#[cfg(feature = "acme")]`-gated per the task's mechanics note.
- N-6: `exclude` now also lists `"tasks/"` and `"docs/architecture/"`.
Verified `cargo package --list --allow-dirty` contains neither path
and `cargo publish --dry-run --allow-dirty` passes.
- N-7: doc line added on `AcmeDirectory::Custom` (`src/identity.rs`):
the URL goes to rustls-acme verbatim and must be `https://` (an
`http://` URL would run ACME token-bearing over plaintext); explicitly
notes no runtime validation is applied so non-https test directories
stay usable. No runtime check added, per the finding.
## Summary
> Agent fills this on completion.
All four findings resolved. Changes:
1. `src/server.rs``new_acme` dedups the `acme-tls/1` ALPN append
(idempotent construction) and rejects an empty `domains` list with
`TlsError::AcmeConfig` before spawning the order loop; the
ACME/non-ACME ALPN asymmetry is documented on `TlsServerConfig::new`.
2. `src/identity.rs``AcmeDirectory::Custom` documents the
https-only caller contract (no runtime validation, per finding).
3. `Cargo.toml``exclude` gains `"tasks/"` and `"docs/architecture/"`.
New tests (both `#[cfg(feature = "acme")]`): caller-supplied
`acme-tls/1` yields exactly one entry; empty `domains` constructs to
`TlsError::AcmeConfig`.
Verification: `cargo test` (default) and `cargo test --all-features`
(77 lib tests, both new tests pass), `cargo clippy --all-targets -- -D
warnings`, `cargo fmt --check`, `cargo doc --no-deps`,
`cargo package --list --allow-dirty` (no `tasks/` / `docs/architecture/`
entries), `cargo publish --dry-run --allow-dirty` — all green.