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:
2026-09-10 06:32:44 +00:00
parent d74a27f764
commit 05b3832c88
8 changed files with 706 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
---
id: port-identity-types
name: Port identity types — TlsIdentity, Ed25519SecretKey, AcmeDirectory (src/identity.rs)
status: pending
depends_on: [crate-init]
scope: narrow
risk: low
impact: component
level: implementation
tags: [identity, types, port]
---
## Description
Port the identity types from alknet-core `config.rs` into
`src/identity.rs` per ADR-005: `TlsIdentity` (four variants: `X509 {
cert, key }`, `RawKey(Ed25519SecretKey)`, `SelfSigned`, `Acme {
domains, cache_dir, directory, contact }`), `Ed25519SecretKey`, and
`AcmeDirectory` (`Production` / `Staging` / `Custom(String)` with
`url()`).
### The load-bearing surface (do not change)
- `Ed25519SecretKey`: `generate()`, `from_bytes(&[u8; 32])`,
`as_bytes() -> [u8; 32]`, `public() -> ed25519_dalek::VerifyingKey`,
`sign(&self, message) -> ed25519_dalek::Signature`. The byte surface
is what iroh's `iroh_base::SecretKey` consumes (ADR-005; verified
against iroh 1.1 in Phase 0). Backed by `ed25519_dalek::SigningKey`.
- `Debug` must NOT leak key material (the extracted type formats as
`Ed25519SecretKey(..)` — keep it).
- `AcmeDirectory::Production` / `Staging` URLs are pinned strings
(Let's Encrypt production + staging) — assert them in tests.
- Doc comments carry the OQ-TLS-02 resolution: `SelfSigned` on the
client path presents nothing (documented on the variant).
### What moves vs stays
`TlsIdentity`/`Ed25519SecretKey`/`AcmeDirectory` move here wholesale.
`PeerEntry`, `AuthPolicy`, `Identity`, fingerprint → peer-id
resolution stay OUT (auth layer — ADR-005's carve-out). No
`serde` derives unless the extracted code has them (check; do not add
new surface beyond ADR-005's list without noting it).
## Work
1. Port the three types + their inherent methods from
`crates/alknet-core/src/config.rs`.
2. Port the associated in-module tests (`generate`/`from_bytes`
round-trip, `AcmeDirectory` URL assertions).
3. Add the Debug-no-leak test if not present in the extracted tests.
## Verification
- [ ] `cargo test -p alktls identity` passes (ported tests green)
- [ ] `as_bytes`/`from_bytes` round-trip asserted
- [ ] `AcmeDirectory` URLs asserted (production + staging + custom)
- [ ] `Debug` output contains no key bytes (test: format then assert
hex key absent)
- [ ] `cargo clippy --all-targets -- -D warnings`, `cargo fmt --check`
## Acceptance Criteria
- [ ] `src/identity.rs` holds exactly the ADR-005 type set; no auth
layer types present
- [ ] The byte surface matches the load-bearing list above verbatim
- [ ] `lib.rs` re-exports the three types
## References
- docs/architecture/decisions/005-config-types-move-into-alktls.md
- docs/architecture/decisions/006-module-layout-and-tests.md (module map)
- Prior art: `/workspace/@alkdev/alknet/crates/alknet-core/src/config.rs`
(lines 3380: `Ed25519SecretKey`, `TlsIdentity`, `AcmeDirectory`)
## Notes
> Agent fills this during implementation.
## Summary
> Agent fills this on completion.