- src/error.rs: thiserror Error enum with the five ADR-012 \u00a76.5 variants (Missing, Verification, Io(String), GcRefuse, KeyInvalid); doc comments carry store-api.md \u00a7Error model's semantics and the one-enum/two-altitude discipline (trait's effective members are Missing/Verification/Io/KeyInvalid; facade re-exposes with GcRefuse) - no #[non_exhaustive] per the ADR-pinned variant set; Error derives Debug/PartialEq/Eq - lib.rs re-exports Error - unit tests: variant construction, the single-enum altitude shape, and the Missing-is-never-get/stat-absence doc contract (facade behavioral enforcement lands in wave 2) - tasks/core-error-model.md: status completed; Notes + Summary filled Verified: cargo test, cargo clippy --all-targets -- -D warnings, cargo fmt --check
101 lines
4.7 KiB
Markdown
101 lines
4.7 KiB
Markdown
---
|
|
id: core-error-model
|
|
name: Error model — the one-enum family with altitude discipline
|
|
status: completed
|
|
depends_on: [scaffold-crate-features]
|
|
scope: single
|
|
risk: low
|
|
impact: component
|
|
level: implementation
|
|
tags: [wave-1, errors]
|
|
---
|
|
|
|
## Description
|
|
|
|
Implement the crate's error family (`src/error.rs`, re-exported from
|
|
`lib.rs`) per store-api.md's error model and ADR-012 §6.5:
|
|
|
|
- One `Error` enum (thiserror) with exactly the five distinguished
|
|
variants: `Missing`, `Verification`, `Io(String)`, `GcRefuse`,
|
|
`KeyInvalid`.
|
|
- **The altitude discipline in doc comments** (store-api.md's "one
|
|
enum, both altitudes"): the `Backend` trait's methods return this
|
|
family but its *effective* members are
|
|
`Missing`/`Verification`/`Io`/`KeyInvalid` — `KeyInvalid` never
|
|
fires at the trait boundary (keys arrive opaque there) and
|
|
`GcRefuse` never fires below the facade (arbitration answers flow up
|
|
as data; the facade decides and owns the refusal). The facade's
|
|
public surface re-exposes the family with `GcRefuse` added.
|
|
- Semantics per variant: `Missing` — key absent on ops that signal
|
|
absence via `Err` (`read_range`, `delete`); `get`/`stat` signal
|
|
absence with `None` and never carry `Missing`. `Verification` —
|
|
put/get hash-check failure (content ≠ key). `Io(String)` — backend
|
|
media failure, stringly because `std::io::Error` is not stable
|
|
across versions. `GcRefuse` — direct delete refused (protected key:
|
|
pinned, registered-source-live, or protect-callback-named).
|
|
`KeyInvalid` — malformed key bytes at the boundary (truncated,
|
|
unknown algorithm — rejects, never guesses).
|
|
- **Named design point for the review gate**: store-api.md's wording
|
|
("one enum, both altitudes… the trait's effective members… the
|
|
facade re-exposes them with `GcRefuse` added") is implemented as a
|
|
*single* enum with the altitude discipline carried by doc comments
|
|
and construction discipline (not two types). The gate audits this
|
|
reading against the spec text; if the gate reads it as requiring two
|
|
types, that is a cheap fix now.
|
|
|
|
No panics; no `unwrap`/`expect` outside tests; `#[non_exhaustive]` is
|
|
**not** applied unless the spec requires it (the variant set is
|
|
ADR-pinned; new failure families are new ADRs — match the family's
|
|
posture on alkstore's error taxonomy).
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [x] `Error` enum with the five variants, thiserror-derived
|
|
Display/Error impls
|
|
- [x] Doc comments on the enum and each variant stating the semantics
|
|
and the altitude discipline verbatim-traceable to store-api.md
|
|
- [x] Unit tests: each variant constructs; `Missing` documented
|
|
get/stat exclusion stated in docs (behavioral enforcement lands
|
|
with the facade in wave 2)
|
|
- [x] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
|
|
`cargo fmt --check` green
|
|
|
|
## References
|
|
|
|
- docs/architecture/store-api.md (§Error model)
|
|
- docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §6.5, §1
|
|
|
|
## Notes
|
|
|
|
- Implemented as a *single* enum carrying the altitude discipline in
|
|
doc comments (module doc, per-variant docs, and a
|
|
`one_enum_both_altitudes` test asserting the 4-member trait-shape
|
|
vs 5-member facade-shape split) — the reading recommended by the
|
|
task's named design point. Payloads verbatim: only `Io(String)` is
|
|
annotated with a payload in store-api.md/ADR-012 §6.5; `Missing`,
|
|
`Verification`, `GcRefuse`, `KeyInvalid` are the unit variants the
|
|
spec text itself writes, so no payloads were invented for them.
|
|
- `#[non_exhaustive]` not applied per the task's ADR-pinned variant
|
|
set. `Error` derives `Debug`/`PartialEq`/`Eq` (test/ctor utility;
|
|
no behavior added).
|
|
- Re-exported as `pub use error::Error` from `lib.rs`; module remains
|
|
public per the scaffold shape.
|
|
- The `missing_is_exclusive_to_err_shaped_ops` test is the marker for
|
|
the get/stat-exclusion doc contract; behavioral enforcement is
|
|
deferred to the wave-2 facade task, as scoped.
|
|
|
|
## Summary
|
|
|
|
`src/error.rs` now defines the crate's error family: one
|
|
thiserror-derived `Error` enum with exactly the five distinguished
|
|
variants (`Missing`, `Verification`, `Io(String)`, `GcRefuse`,
|
|
`KeyInvalid`), doc comments traceable to store-api.md §Error model and
|
|
ADR-012 §6.5/§1 stating each variant's semantics plus the one-enum/
|
|
two-altitude discipline (trait boundary: `Missing`/`Verification`/`Io`/
|
|
`KeyInvalid` effective; `KeyInvalid` never fires at the boundary,
|
|
`GcRefuse` never fires below the facade — the facade re-exposes the
|
|
family with `GcRefuse` added). Re-exported from `lib.rs`. Three unit
|
|
tests cover variant construction, the single-enum altitude shape, and
|
|
the `Missing`-is-never-`get`/`stat`-absence doc contract. Verified:
|
|
`cargo test`, `cargo clippy --all-targets -- -D warnings`, `cargo fmt
|
|
--check` all green. |