feat(error): land the fail-closed key-source error taxonomy
- KeySourceError with exactly five variants (Locked, Absent, Decryption, UnknownKeyVersion, Decode) — ADR-005 decision 4's failure matrix as distinct shapes, the vault taxonomy reshaped never collapsed; no catch-all, no Other/Unknown - payload shapes pinned: Locked/Absent payload-free; Decryption/UnknownKeyVersion carry the vault's opaque messages; Decode carries a message so the RC-pinned ssh-key error type never enters the public API (flagged for the wave-1 gate) - each variant doc-commented with ADR-005 semantics + fail-closed consequence; module stays engine-blind (no vault/russh types) - no From<VaultServiceError>: non-mappable vault variants would force a collapse; w1-key-sources maps explicitly at its seam - exhaustive-match + Display/Debug/Clone unit tests Verified: cargo test (default + all-features), cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --check, cargo doc --no-deps, taskgraph validate
This commit is contained in:
1 parent
78ae905b21
commit
d85299df38
3 files changed
+220
-7
No files matched your search
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: w1-error-model
|
||||
name: Wave 1 — the error model (fail-closed taxonomy)
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [w1-manifest]
|
||||
scope: narrow
|
||||
risk: low
|
||||
@@ -39,13 +39,13 @@ message is the honest content), flagged for the wave-1 gate.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `KeySourceError` has exactly the five pinned variants; no
|
||||
- [x] `KeySourceError` has exactly the five pinned variants; no
|
||||
catch-all, no `Other`/`Unknown`
|
||||
- [ ] Doc comments state each variant's ADR-005 semantics and its
|
||||
- [x] Doc comments state each variant's ADR-005 semantics and its
|
||||
fail-closed consequence
|
||||
- [ ] Unit tests construct every variant and assert `Display`/`Debug`
|
||||
- [x] Unit tests construct every variant and assert `Display`/`Debug`
|
||||
paths compile clean
|
||||
- [ ] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
|
||||
- [x] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
|
||||
`cargo fmt --check` pass
|
||||
|
||||
## References
|
||||
@@ -56,8 +56,43 @@ message is the honest content), flagged for the wave-1 gate.
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
> Payload shapes pinned (flagged for the wave-1 gate): `Locked` and
|
||||
> `Absent` are payload-free — no honest content beyond the variant
|
||||
> itself (the caller knows which source it requested);
|
||||
> `Decryption(String)` and `UnknownKeyVersion(String)` carry the
|
||||
> vault's opaque messages (`VaultServiceError::Encryption` /
|
||||
> `InvalidPath` arrive as strings per POC-2 §3 — string is the honest
|
||||
> content). `Decode` carries `String` rather than the typed
|
||||
> `ssh_key::Error` (`russh::keys::decode_secret_key`'s error type):
|
||||
> the ssh-key RC type is deliberately kept out of the published
|
||||
> public API — when the RC settles the payload can be re-typed, but
|
||||
> freezing an RC error type now would be a worse one-way door. The
|
||||
> module doc comment records the deliberately-not-error classes
|
||||
> (auth declines = dispositions per ADR-004; wire decline reasons =
|
||||
> wave-2; config validation = none unless w1-config finds a need —
|
||||
> the OQ-08 fields decline at request time). No `From<VaultServiceError>`
|
||||
> blanket impl on purpose: alkvault's taxonomy has variants
|
||||
> (`Mnemonic`, `Derivation`, `AlreadyUnlocked`, `UnsupportedKeyType`)
|
||||
> that do not map onto the five without collapsing, and the ADR's
|
||||
> reshape-never-collapse rule kills the conversion; w1-key-sources
|
||||
> maps explicitly at its seam. The module stays engine-blind — no
|
||||
> alkvault or russh types referenced at the error layer. Tests: an
|
||||
> exhaustive `match` (no wildcard — the closed-variant invariant is
|
||||
> compile-time enforced) plus `Display` string assertions over all
|
||||
> five variants, `Debug` output, and `Clone` payload carrying.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
> `src/error.rs` landed: `KeySourceError` with exactly five variants
|
||||
> (`Locked`, `Absent`, `Decryption(String)`, `UnknownKeyVersion(String)`,
|
||||
> `Decode(String)`), each doc-commented with its ADR-005 semantics and
|
||||
> fail-closed consequence (locked → no dial + no server; absent/decryption/
|
||||
> unknown-version/decode → no dial; host-key path → no server
|
||||
> construction throughout). Re-exported from the crate root
|
||||
> (`mod error; pub use error::KeySourceError;` — the alktty pattern).
|
||||
> No catch-all, no `Other/Unknown`, no blanket `From` from the vault's
|
||||
> taxonomy. Four unit tests (exhaustive match over the enum,
|
||||
> `Display`, `Debug`, `Clone`). Verified: `cargo test` (4/4 + doc
|
||||
> tests), `cargo test --all-features`, `cargo clippy --all-targets
|
||||
> -- -D warnings` (default + all-features), `cargo fmt --check`,
|
||||
> `cargo doc --no-deps` (no warnings), `taskgraph validate` clean.
|
||||
Reference in new issue
Block a user