Durable, component-scoped state on haematite branches.
[ComponentStateStore] is the only owner of haematite's wide capabilities:
its node store and branch/snapshot registries never leave this crate.
Components receive only [ComponentStoreHandle], which contains a component
identity, an incarnation fence, and a private reference back to the facade.
It accepts no branch name and can name a foreign component only through
capability-checked read resolution. Naming is not authority: a matching grant
row must be present at resolution time. The checkout view is created, read, and
dropped inside that call; the public surface returns only owned bytes and never
names [haematite::ReadOnlyView]. That published view's put, delete, and
commit methods all return [haematite::CheckoutError::ReadOnly], and no
mutable foreign branch can be obtained or re-derived in safe Rust. Haematite's
persisted BranchKind and lineage checks provide the
separate storage-enforced half of the boundary.
A durable branch commit materialises only that branch's dirty shards, but its
DiskStore fsync barrier drains the shared store dirty set. Branches are
atomic commit units, not independent physical fsync domains. Coordination
across component namespaces is deliberately not a storage transaction.
Durability grade (stack ruling, 2026-07-12): every "durable" in this crate
is kill-9-verified and power-loss-fenced at the file level (haematite
7e7ab17, crash-tested). Known residual: a commit that creates a brand-new
prefix subdirectory does not fsync the store root's directory entry, so
power loss (not process kill) can vanish that subdirectory while the WAL
marker survives — and a fresh namespace's first commits sit exactly in that
window. The upstream fix is incident-class; this paragraph retires when its
crash pin lands. Until then, [ComponentStateStore::reconcile] treats a
branch ref without a readable store as a refused inconsistency — named
loudly, never silently healed.