7.2 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| contract-suite-scaffold | Contract-suite crate scaffold + ADR-022 (suite layout decision) | completed |
|
narrow | low | phase | implementation |
|
Description
Scaffold the contract suite as a fourth, internal, unpublished crate —
alkstore-contract-suite — per the layout decision recorded in
docs/plans/implementation.md (option (a)): property tests
parameterized over a Store factory, consumed by each engine crate as
a dev-dependency. This discharges ADR-017 §4.2's "layout decided at
implementation" deferral; the decision gets its own ADR (ADR-022) since
it shapes the pairing instrument ADR-017 §4 names.
The crate:
- Workspace member,
publish = false, depends onalkstoreonly. - Exposes a
StoreFactorytrait (or function alias — implementer's choice, but one shape, documented): something that yields a freshBox<dyn Store>-shaped store over an isolated backing store (fresh file / fresh schema), plus teardown. The exact factory shape may evolve when engines adopt it (wave 3/4 feedback) — the ADR records the layout decision, not a frozen API. - A
tests/harness that runs the property set against a supplied factory, structured so each backlog row is one named, independently runnable property with a version-stamp slot (ADR-017 §4.2: each row version-stamped with the contract change that added it — a doc-comment or attribute convention, decided here and used by every later row). - One exemplar property implemented end-to-end to prove the harness
works — the reserved-name/empty-name validation property (pure
contract, engine-independent, runnable against any factory): every
name-bearing entry point rejects empty with
InvalidNameand reserved-prefix withReservedName, on auto-commit and tx paths alike. This row is version-stampedADR-008 §4. - Engine crates get the dev-dependency edge now (empty suite compiles against them trivially once they have code; the edge existing early means wave 3/4 tasks adopt the harness rather than debate it).
Acceptance Criteria
alkstore-contract-suitecrate exists,publish = false, depends on core only, compiles in the workspace- Factory abstraction defined and documented; exemplar property (name validation) green against a trivial in-crate mock store
- Version-stamp convention established and documented in the crate (used by the exemplar row)
- ADR-022 written (
docs/architecture/decisions/022-contract-suite-layout.md): option (a) chosen, rationale (one normative owner per property, ADR-012 §2 mirror), the factory-shape latitude stated, ADR-017 §4.2 deferral discharged; ADR index tables in docs/architecture/README.md and overview.md updated - Engine crate manifests carry the dev-dependency edge
cargo testworkspace-wide, clippy-D warnings, fmt clean
References
- docs/architecture/decisions/017-contract-versioning.md §4.2
- docs/plans/implementation.md (Decided points)
- docs/architecture/core-contract.md §Verification backlog
Notes
- Factory shape (the implementer's choice): a named trait,
StoreFactory { open() -> BoxedFuture<Result<Box<dyn Store>>>; teardown() -> BoxedFuture<Result<()>> }— chosen over a function alias because teardown needs an identity to be idempotent per instance (a bare fn can't carry "this factory's backing store"), and the async surface rides core'sBoxedFutureposture so implementers need no macros. One shape, documented insrc/factory.rs; the ADR records the layout, not a frozen API — wave 3/4 feedback may evolve it. - Version-stamp convention (the "decided here" row convention):
a row's doc comment carries one
Contract stamp:item per contract change pinning the behavior tested, citing ADR § (never bare "v1" or dates); stamps accumulate on amendment; greppable via the exportedSTAMP_MARKERconstant. Normative statement lives insrc/version_stamp.rs— every later row cites against it. The exemplar row is stampedADR-008 §4+ADR-021 §3+ADR-015 §2(its assertions span all three changes' behavior). - Assertion posture: rows panic on violation (labeled with the entry point and expectation) — the test-side-artifact relaxation of the family no-panic rule, documented in the crate docs as deliberate.
- Exemplar scope: the property runs the full validation surface —
all four
Storeconstructor kinds (listen/stream/queue/outbox),try_lock(both name and owner),schedule(both name and queue argument — ADR-021 §3),notify, and every name-bearing*_txtwin onTxHandle(all eleven, incl. ADR-015 §2's non-empty-key rule onpublish_with_key_tx), plus awith_txspot-check proving the commit-atomic path can't bypass validation. Happy-path spot-checks (stream/queue/try_lockwith a reserved-prefixed owner) prove the rejections are the validation's doing, not store-wide failure. Scheduleis#[non_exhaustive](ADR-017 §3): the mock cannot struct-construct it, so the mock'sschedule()returns aDatabasestub after running the row-validation; the row asserts only the validation outcomes, andScheduleconstruction stays core's own tests' business. Same for the mock'ssubscribe(never exercised by the row). Noted so wave 3/4 factory impls copy the posture knowingly.- serde_json is a direct dep of the suite (not just core's): rows
construct payload
Values as contract surface (ADR-020 §4's trait crossing). No driver deps — the ADR-001 §2 mirror holds. - Dev-dep edges are path deps (
path = "../alkstore-contract-suite") with no version: correct for an unpublished internal crate — aversionkey would be meaningless. - ADR-017 §4.2's text gained a layout-resolution annotation (dated, citing ADR-022) at the deferral site — the discharge is visible from the deferring document itself.
Summary
The alkstore-contract-suite crate is scaffolded per the option-(a)
layout decision: publish = false, workspace member, depends on
alkstore only (+ serde_json for payload construction). It defines
the StoreFactory trait (open/teardown over an isolated backing
store), the version-stamp convention (Contract stamp: doc-comment
items, STAMP_MARKER constant, normative statement in
version_stamp.rs), and the exemplar property
name_validation_rejects_empty_and_reserved — full auto-commit + tx
validation surface, stamped ADR-008 §4 / ADR-021 §3 / ADR-015 §2. A
tests/suite_harness.rs runs it green against a trivial in-crate mock
store + factory (3 tests: the exemplar row, happy-path construction,
stamp-marker check). Engine crates carry the dev-dependency edge
(path-dep). ADR-022 written
(docs/architecture/decisions/022-contract-suite-layout.md): option (a)
chosen, one-normative-owner-per-property rationale (ADR-012 §2
mirror), factory-shape latitude stated, ADR-017 §4.2 deferral
discharged (with an annotation added at the deferral site);
ADR index tables in docs/architecture/README.md and overview.md
updated. Workspace cargo build, cargo test (26 tests workspace
wide), cargo clippy --all-targets -- -D warnings, cargo fmt --check all clean.