Skip to content

ADR-0004: Statement-backing is opt-in per attribute

ADR-0004: Statement-backing is opt-in per attribute

Status

Accepted

Date

2026-06-24

Context

The kernel’s most distinctive bet is that “important real-world facts should be Statements, not only mutable properties” — a Statement carrying source, actor, evidence, confidence, validTime, transactionTime, and authority, with the Projection Engine selecting the current value via authority/conflict rules. The proving case (POC 6): GIS says geometry A, a field survey says geometry B, a supervisor approves B, the projection serves B, and history retains both.

The pack never draws the line between a “fact” (worth the full Statement machinery) and an ordinary attribute. That line is load-bearing. A Statement carries seven dimensions of metadata; attaching all of it to every attribute — a status pill, a comment, a created_at — is crushing write/storage/projection overhead and buries the genuinely contested facts in ceremony. Too narrow, and we lose the differentiator.

Decision

Statement-backing is opt-in per attribute, declared in schema. The default attribute is a plain value, mutated directly by an Action, fully audited via the event log (last-write-by-action). Only source-reconciled / contested facts — those that multiple independent sources assert and that may disagree — are declared statement-backed (via a trait such as evidence.EvidenceBacked or an Asserted<T> value-type wrapper).

Statement-backed attributes get the full Statement → Authority → Projection treatment, including conflict resolution. Plain attributes do not. Canonical statement-backed examples: geometry, capacity, as-built measurements. Canonical plain examples: workflow status, comments, system timestamps.

Alternatives Considered

Statement-backed by default

All domain facts are statements; only system/UI metadata stays plain.

  • Rejected: maximal provenance everywhere at heavy write/storage/projection cost, for facts that are never actually contested.

Everything is a Statement

No plain attributes at all.

  • Rejected: purest model, highest cost, no payoff for uncontested values.

Decide per-realm

Some realms fully statement-backed, others plain.

  • Rejected: contestedness is an attribute-level property (a FiberSpan’s geometry is contested; its name is not). Realm granularity is too coarse.

Consequences

  • The audit/history guarantee holds for all attributes (via the event log, per ADR-0003), independent of statement-backing. Statement-backing adds multi-source conflict resolution, not auditability.
  • The schema compiler must support an attribute-level “statement-backed” flag and generate the conflict-resolution projection only for those attributes.
  • Interacts with ADR-0003: the spike must determine whether authority/conflict resolution for statement-backed attributes runs in the write transaction or the async projection.
  • Interacts with ADR-0013: the GIS-vs-survey conflict is also the offline-sync conflict case; conflict-as-first-class-outcome reuses this machinery.