- 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
4.7 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| core-error-model | Error model — the one-enum family with altitude discipline | completed |
|
single | low | component | implementation |
|
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
Errorenum (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
Backendtrait's methods return this family but its effective members areMissing/Verification/Io/KeyInvalid—KeyInvalidnever fires at the trait boundary (keys arrive opaque there) andGcRefusenever 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 withGcRefuseadded. - Semantics per variant:
Missing— key absent on ops that signal absence viaErr(read_range,delete);get/statsignal absence withNoneand never carryMissing.Verification— put/get hash-check failure (content ≠ key).Io(String)— backend media failure, stringly becausestd::io::Erroris 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
GcRefuseadded") 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
Errorenum with the five variants, thiserror-derived Display/Error impls- Doc comments on the enum and each variant stating the semantics and the altitude discipline verbatim-traceable to store-api.md
- Unit tests: each variant constructs;
Missingdocumented get/stat exclusion stated in docs (behavioral enforcement lands with the facade in wave 2) cargo test,cargo clippy --all-targets -- -D warnings,cargo fmt --checkgreen
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_altitudestest asserting the 4-member trait-shape vs 5-member facade-shape split) — the reading recommended by the task's named design point. Payloads verbatim: onlyIo(String)is annotated with a payload in store-api.md/ADR-012 §6.5;Missing,Verification,GcRefuse,KeyInvalidare 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.ErrorderivesDebug/PartialEq/Eq(test/ctor utility; no behavior added).- Re-exported as
pub use error::Errorfromlib.rs; module remains public per the scaffold shape. - The
missing_is_exclusive_to_err_shaped_opstest 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.