phase 2: task decomposition — 8-task port graph
- crate-init: skeleton, feature gates (ADR-003), TlsError (ADR-002) - three parallel foundation ports: identity types, fingerprint, pem+signing - port-server / port-client in parallel (each consumes the foundation; client also carries credentials.rs per ADR-005 co-location) - integration-suite: invariant pins + feature-matrix + seam round-trips - review-impl: spec-conformance gate — the API-freeze point before the alknet rewrite consumes the crate - validated: taskgraph topo (5 generations), no cycles, critical path len 5, risk-path 1.45; medium risk concentrated on the two broad ports + the suite (each a diff against a fixed extraction source, not open-ended work)
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
---
|
||||
id: port-server
|
||||
name: Port server side — TlsServerConfig, resolvers, ACME path (src/server.rs)
|
||||
status: pending
|
||||
depends_on: [port-identity-types, port-pem-signing]
|
||||
scope: broad
|
||||
risk: medium
|
||||
impact: phase
|
||||
level: implementation
|
||||
tags: [server, acme, port, invariants]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Port `src/server.rs` from alknet-tls per the ADRs: `TlsServerConfig`,
|
||||
`build_rustls_server_config`, `RawKeyCertResolver`,
|
||||
`AcceptAnyCertVerifier`, `SelfSignedCert` / `generate_self_signed_cert`,
|
||||
and the ACME branch. This is the biggest port task; the deltas against
|
||||
the extraction source are all ADR-pinned, everything else is a port.
|
||||
|
||||
### The API deltas (from the extracted code)
|
||||
|
||||
- Accessors borrow: `for_noq(&self)` (ADR-004), `for_tcp_tls(&self)`
|
||||
(adopted — did not exist in the extraction), `rustls_config(&self)`
|
||||
(adopted — the field was `pub(crate)`; now the re-exported accessor).
|
||||
- `for_noq` replaces `for_quinn`:
|
||||
`noq::ServerConfig::with_crypto(Arc::new(
|
||||
noq::crypto::rustls::QuicServerConfig::try_from(inner)?))`; the
|
||||
failure maps to `TlsError::NoqWrap` (ADR-002/003).
|
||||
- `build_rustls_server_config`'s `TlsIdentity::Acme` arm: the
|
||||
extracted `unreachable!` becomes a `TlsError::AcmeConfig` return
|
||||
(ADR-006; no panics in library code). The internal dispatch
|
||||
invariant (Acme is handled by `new_acme`) is preserved — the arm is
|
||||
defensive.
|
||||
- Field name: `acme_handle` (ADR-006 unified on the alknet-spec name).
|
||||
|
||||
### The behavior-preservation invariants (all must be test-pinned here)
|
||||
|
||||
- `max_early_data_size = u32::MAX` on every path (X509, RawKey,
|
||||
SelfSigned, ACME branch).
|
||||
- `aws_lc_rs::default_provider()` on every path (constructed via
|
||||
`builder_with_provider`; no process-default fallback).
|
||||
- `AcceptAnyCertVerifier::supported_verify_schemes()` returns the
|
||||
nine schemes verbatim (ED25519; ECDSA P-256/P-384; RSA PSS
|
||||
256/384/512; RSA PKCS1 256/384/512).
|
||||
- `acme-tls/1` appended by the crate on the ACME path only.
|
||||
- Verifier behavior: `offer_client_auth() == true`,
|
||||
`client_auth_mandatory() == false`, empty `root_hint_subjects`,
|
||||
accepts any client cert.
|
||||
- `RawKeyCertResolver`: `only_raw_public_keys() == true`, resolves the
|
||||
SPKI-backed `CertifiedKey`.
|
||||
|
||||
### ACME path (feature `acme`)
|
||||
|
||||
Port `new_acme` per server.md: `rustls_acme::AcmeConfig` + `DirCache`
|
||||
+ directory URL + contacts; `state.resolver()` wired in; `acme-tls/1`
|
||||
appended; the event-loop task spawned (`EventOk`/`EventError` matched
|
||||
to `tracing` logs — port the extracted log lines); returns immediately.
|
||||
Handle stored in `acme_handle`, never aborted (detached; OQ-TLS-06).
|
||||
Without the feature, `Acme` identities return `TlsError::AcmeConfig`.
|
||||
|
||||
## Work
|
||||
|
||||
1. Port the module; apply the deltas above; rewire imports to this
|
||||
crate's types (identity, signing, pem, TlsError).
|
||||
2. Port the extracted in-module tests (they assert most invariants).
|
||||
3. Add the exact nine-scheme list pin (the extracted test only checks
|
||||
two schemes' membership).
|
||||
4. Feature-combo verification (below).
|
||||
|
||||
## Verification
|
||||
|
||||
- [ ] Invariant pins green: `max_early_data_size` per path,
|
||||
nine-scheme exact list, resolver behavior, verifier behavior
|
||||
- [ ] ACME branch (with `--features acme`): spawns, returns
|
||||
immediately, appends `acme-tls/1` (test with a staging URL +
|
||||
tempdir cache; do NOT hit Let's Encrypt — construct and assert
|
||||
config state, assert the ALPN list)
|
||||
- [ ] `Acme` identity without the `acme` feature → `TlsError::AcmeConfig`
|
||||
- [ ] `for_noq` / `for_tcp_tls` round-trip per identity variant
|
||||
(construction-level; handshakes are out of scope)
|
||||
- [ ] `cargo test` (default), `cargo test --all-features`,
|
||||
`cargo clippy --all-targets -- -D warnings`, `cargo fmt --check`
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] All five server invariants are test-asserted (not just compiled)
|
||||
- [ ] `for_noq`, `for_tcp_tls`, `rustls_config` exist with ADR-004
|
||||
signatures (`&self`; `for_tcp_tls` infallible)
|
||||
- [ ] No `unreachable!`/panics in library code
|
||||
- [ ] `lib.rs` re-exports the server surface
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/server.md (the normative doc)
|
||||
- docs/architecture/decisions/002-tlserror-shape.md, 003, 004
|
||||
- Prior art: `/workspace/@alkdev/alknet/crates/alknet-tls/src/server.rs`
|
||||
(port source; note every delta above)
|
||||
|
||||
## Notes
|
||||
|
||||
> Agent fills this during implementation.
|
||||
|
||||
## Summary
|
||||
|
||||
> Agent fills this on completion.
|
||||
Reference in New Issue
Block a user