Summary
Prerequisite feature for #391 (datastore backend for project metadata) and its future siblings (attestation datastore, report datastore, audit-cache datastore). Landed as its own feature so the abstraction can be reviewed on its own merits and land ahead of any specific backend.
Design conversation on 2026-08-23 (chat log; not yet in a spec) landed on:
- darnit-core stays filesystem-only (Constitution I unchanged, storage claim in CLAUDE.md unchanged).
- Alternative storage backends land as plugins behind per-artifact Protocols, mirroring feature 027's
QuestionResolver pattern.
- Discovery via Python entry points (
darnit.stores.<kind>).
- Backend selection in TOML (
[stores.<kind>] backend = "...").
Scope
Protocols (four, one per artifact class):
ProjectStateStore -- read/write .project/project.yaml, maintainers.yaml, extensions.
AttestationStore -- persist feature-025 attestation bundles.
ReportStore -- persist audit reports (Markdown, JSON, SARIF).
AuditCacheStore -- persist per-audit-run cache.
Contracts each Protocol MUST document:
- Sync vs async surface.
- Batched vs per-item write semantics.
- Transactional vs eventually-consistent.
- What a "failed write" means to the caller (WARN? ERROR? exception?).
Per-artifact granularity chosen (over "one Store Protocol with method families per backend") so .project/ can stay YAML-on-disk while attestations go to a database, and so each artifact class can migrate independently.
Core deliverables:
- Four Protocol classes with
@runtime_checkable decoration (per feature 027 convention).
- Filesystem-backed default implementation for each, shipped in
darnit-core. Existing paths (.project/, .darnit/attestations/, .darnit/reports/, .darnit/cache/) become the default backend's on-disk layout.
- Entry-point discovery machinery: register under
darnit.stores.project, darnit.stores.attestation, darnit.stores.report, darnit.stores.cache.
- TOML surface on
FrameworkConfig ([stores.<kind>] backend = "<name>") with schema validation.
- Zero behavior change for any consumer that doesn't set
[stores.*] -- filesystem default is transparent.
Non-goals for v0
Constitution alignment
- I. Plugin Separation: the Protocols and filesystem defaults live in
darnit-core; alternative backends are plugin packages that never touch core.
- III. TOML-First: backend selection is a TOML surface, no Python-code escape hatch.
- V. Sieve Pipeline Integrity: sieve handlers do not touch stores directly; store operations happen at audit-boundary composition, keeping the pipeline's PASS/FAIL/WARN/ERROR contract intact.
Related
Summary
Prerequisite feature for #391 (datastore backend for project metadata) and its future siblings (attestation datastore, report datastore, audit-cache datastore). Landed as its own feature so the abstraction can be reviewed on its own merits and land ahead of any specific backend.
Design conversation on 2026-08-23 (chat log; not yet in a spec) landed on:
QuestionResolverpattern.darnit.stores.<kind>).[stores.<kind>] backend = "...").Scope
Protocols (four, one per artifact class):
ProjectStateStore-- read/write.project/project.yaml,maintainers.yaml, extensions.AttestationStore-- persist feature-025 attestation bundles.ReportStore-- persist audit reports (Markdown, JSON, SARIF).AuditCacheStore-- persist per-audit-run cache.Contracts each Protocol MUST document:
Per-artifact granularity chosen (over "one Store Protocol with method families per backend") so
.project/can stay YAML-on-disk while attestations go to a database, and so each artifact class can migrate independently.Core deliverables:
@runtime_checkabledecoration (per feature 027 convention).darnit-core. Existing paths (.project/,.darnit/attestations/,.darnit/reports/,.darnit/cache/) become the default backend's on-disk layout.darnit.stores.project,darnit.stores.attestation,darnit.stores.report,darnit.stores.cache.FrameworkConfig([stores.<kind>] backend = "<name>") with schema validation.[stores.*]-- filesystem default is transparent.Non-goals for v0
Constitution alignment
darnit-core; alternative backends are plugin packages that never touch core.Related
QuestionResolverProtocol + entry-point discovery) -- direct template for this feature's shape.