AQ-EFD-000 — Evidence Fabric Data Model v0
Evidence level Concept; the chaining and verification procedure are at Theory. Architecture tier CA with a Y1 subset marked below. No fabric has been implemented and no record has been written. Version v0 means the field names are expected to change; what is not expected to change is the set of questions a record must answer, because that set is derived from DC-5 rather than from any implementation.
PURPOSE
The Evidence Fabric (L6) exists to satisfy one design commitment: every consequential transition is reconstructable from the Evidence Fabric alone. "Alone" is the load-bearing word. A reconstruction that requires a live node, an engineer's memory, a log correlated by wall-clock time, or a chart produced by a tool that no longer runs is not a reconstruction. The test of this data model is whether a reviewer holding only an exported record set, this document, and the referenced canonical serialisation can say what the node observed, what it concluded, what it decided, why, what it then did, and what happened — and can say, equally clearly, which of those the record set does not establish.
THE TEN QUESTIONS
| # | Question | Field group | Required | When it cannot be answered (DC-2) |
|---|---|---|---|---|
| Q-a | What happened | record_type, values[] | Always | A record with nothing observed is a gap record, never an observation with an empty value list |
| Q-b | When | time{} | Always | time_state = undetermined; no wall-clock value is substituted, and no record is dropped for lacking one |
| Q-c | Where in the system | node_id, boundary, layer | Always | Cannot be undetermined. A writer unable to name its own boundary is refused at write and the refusal is recorded by L9 instrumentation |
| Q-d | Under which configuration | config_id, config_state | Always | config_state = undetermined (AQ-NRA-001); the record remains valid evidence of an event but supports no quantitative claim |
| Q-e | Trust state at the time | trust{state, state_event} | Always | Never absent: RECOVERING is the state a node holds while it does not know, and it is carried explicitly |
| Q-f | What evidence was available | evidence[], raw[] | Always | An empty list is written explicitly and means "nothing was available", which is a finding; it never means "not recorded" |
| Q-g | What was decided | decision.outcome | Decision records | Outcome is one of execute, execute-restricted, safe-hold, abstain, deny. There is no null outcome |
| Q-h | Why | decision.q1..q4, policy_version, constraints[] | Decision records | A decision whose reasoning cannot be serialised may not be emitted; the correct output in that case is abstain with the serialisation failure as its reason |
| Q-i | What action followed | Action record + gate_assert | On execute / execute-restricted | Records the TB-4 gate assertion and its read-back, not merely the intent to act |
| Q-j | What resulted | Result record, linked by event_id | Where observable | If the effect was not observed, a gap record of type G-4 is written in its place. Silence is never read as success |
RECORD SKELETON
Figure 1 - v0 record skeleton (field names indicative, question mapping binding)
record {
event_id : node_id . config_id . epoch_id . sequence [Q-c,Q-d]
record_type : observation | derivation | decision | action |
result | gap | configuration | anchor | review
boundary : TB-1 | TB-2 | TB-3 | TB-4 | TB-5 [Q-c]
layer : L0 .. L9 [Q-c]
config_id : digest of the signed configuration manifest [Q-d]
config_state : bound | undetermined [Q-d]
time { [Q-b]
t_acquired : deterministic counter value captured at TB-2 MEASURED
t_utc : mapping of t_acquired to civil time DERIVED
u_utc : stated uncertainty of that mapping MODELLED
time_state : bound | degraded | undetermined
ref : reference id + event_id of last good discipline
}
trust { [Q-e]
state : NORMAL | RESTRICTED | CRITICAL | DENY | RECOVERING
state_event: event_id of the transition that set this state
}
values[] { [Q-a]
name, value, unit,
dc1 : MEASURED | DERIVED | MODELLED,
source : sensor id | derivation id | model id + version,
method : method id + version
}
evidence[] : event_id references this record consumed [Q-f]
raw[] { [Q-f]
ref_id, algorithm, digest, bytes, store_class,
retention_class, expires_at, state : held | expired | lost
}
decision : present only when record_type = decision [Q-g,Q-h]
prev_digest : digest of the previous record in this chain
digest : digest over the canonical serialisation of the
fields above, excluding this field
}
EVENT IDENTITY
event_id is constructed from the node identifier, the configuration identity, an epoch identifier that changes on every entry to RECOVERING, and a strictly increasing sequence number issued by a single writer per chain. It is deliberately not derived from time: a time value can be wrong, unavailable or repeated, and an identifier that inherits those properties cannot be used to detect the very gaps this model requires. Sequence numbers are dense within an epoch, which is what makes an omission detectable — a missing sequence number is a gap by arithmetic, not by inference. Re-submission of a record with an identifier already present is idempotent and is itself recorded; a re-submission whose content digest differs from the held record is a conflict, is refused, and both digests are recorded.
TEMPORAL BINDING WITH CONFIDENCE
Two distinct time quantities are carried and never conflated. t_acquired is a counter value captured in the deterministic acquisition fabric at the moment of acquisition and is tagged MEASURED. t_utc is the mapping of that counter onto civil time and is tagged DERIVED; its uncertainty u_utc is the output of a model of the discipline chain and is tagged MODELLED. The magnitude of that uncertainty under each discipline condition is a quantity to be established by measurement on the bench and metro rungs; no figure is stated here, and a record that carries t_utc without u_utc is malformed.
bound — discipline to an authenticated reference is current and u_utc is within the characterised envelope for this configuration. degraded — the mapping is being held open-loop; u_utc grows and the record says so. undetermined — no defensible mapping exists. A record in undetermined keeps its t_acquired, keeps its sequence position, and omits t_utc entirely. Substituting a plausible wall-clock reading in that field would convert a known unknown into a false measurement, which is the specific failure DC-2 exists to prevent.
CHAINING AND ANCHORING
Figure 2 - per-node chain and external anchoring
r(n-1).digest ------> r(n).prev_digest
r(n).digest = H( canonical( r(n) minus digest ) )
every K records or T seconds, whichever first:
anchor_record {
chain_head_digest, first_sequence, last_sequence, count,
config_id, signed by L3 identity
}
|
+--> emitted across TB-5 to a witness set outside node control
+--> witness receipts returned and stored as ordinary records
K and T are to be set from measured write rates and the accepted
reconstruction window; no value is asserted in v0.
Chaining establishes that the records presented are in the order the writer produced them and that none has been altered since the anchor that covers it. It does not establish that the content is true, that the writer was honest, or that no record was suppressed before it entered the chain. That last limit is precisely why sequence density and explicit gap records are mandatory: a suppressed record leaves an arithmetic hole that no amount of chaining could otherwise reveal. These limits are stated in the fabric's own documentation so that a reader cannot mistake chain verification for validation of the measurement.
PROVENANCE AND DC-1 TAGGING
Every value in values[] carries its DC-1 class together with the identity and version of what produced it. MEASURED requires an unbroken path from a physical sensing element through TB-2; a value that has passed through inference is not measured, however small the inference. DERIVED names the derivation and its version and lists the event_ids it consumed in evidence[]. MODELLED names the model, its version and its validity domain, and any value produced by L8 advisory analysis is MODELLED without exception. Re-tagging is forbidden: a derived value written back into the fabric by any path retains DERIVED, and a record asserting MEASURED for a value whose source is a derivation identifier is malformed and refused.
RAW-DATA REFERENCES, RETENTION AND EXPIRY
Bulk artefacts — detector traces, waveform captures, image frames — are referenced, not embedded. Each reference carries the digest algorithm and digest, the byte count, a store class, a retention class and an expiry. Retention classes are defined by the reconstruction they support, not by convenience of storage; the concrete durations are set by governance at L9 and recorded in the configuration manifest rather than being fixed in this document.
When a raw artefact expires or is lost, its reference remains in the record with state = expired or state = lost and the time and reason recorded. The record does not become invalid, and it is never rewritten. What changes is what may be claimed from it: any derived value whose only support was that artefact must be reported as no longer independently checkable. A reviewer must be able to see the difference between "this was never captured", "this was captured and has expired", and "this was captured and can still be recomputed".
GAP REPRESENTATION
A gap is a first-class record. The rule is absolute: a gap must be visible as a gap, and must never be renderable as an absence of events, a flat line, a zero, or a benign interval.
| Type | Gap class | What the record must state |
|---|---|---|
| G-1 | Sequence gap | First and last missing sequence numbers, the epoch, and whether the writer knows why |
| G-2 | Acquisition gap | The acquisition path affected, its health verdict at gap entry and exit, and the counter range not covered |
| G-3 | Time gap | The interval over which time_state was degraded or undetermined, and the discipline event that closed it |
| G-4 | Result gap | An action was taken and its effect was not observed; carries the action's event_id and why observation failed |
| G-5 | Storage gap | Records were produced but could not be written or transmitted; carries the count if known, or states that the count is unknown |
| G-6 | Expiry gap | Raw support for a previously reconstructable claim has expired or been lost |
Any surface that displays fabric data — operator view, review tool, export, plot — must render every gap type distinctly from both a normal value and a bad value. A gap interpolated, smoothed, omitted from an axis, or averaged away is a defect in the surface and is reportable as such, regardless of how the underlying records are stored.
DECISION RECEIPTS
Figure 3 - decision receipt content
decision {
outcome : execute | execute-restricted | safe-hold | abstain | deny
q1_sender : identity asserted + how established HARD CONSTRAINT
q2_valid : signature verification result + key id HARD CONSTRAINT
q3_authz : authorisation in force at decision time HARD CONSTRAINT
q4_trust : evaluation under the current trust state
may only REDUCE what q1..q3 allowed;
a q4 result that widens authority is malformed
trust_state : state and the state_event that set it
policy_ver : version of the policy set that was applied
constraints : the specific rules that bound the outcome
inputs : event_id list actually consulted (not merely available)
abstain_why : required when outcome = abstain; free of blame language,
names the missing or insufficient input
gate_assert : for execute outcomes - the TB-4 assertion issued and
the read-back observed, as separate MEASURED values
}
Two properties are enforced at write time. First, inputs lists what was consulted, not what was on hand: a decision that ignored an available observation is a legitimate thing to record and an important thing to review. Second, abstain is a complete and permitted outcome (DC-3) and carries the same receipt structure as any other; a fabric in which abstentions are recorded more thinly than executions will, over time, make abstention look like an absence of work rather than the deliberate output it is.
THIRD-PARTY VERIFICATION PROCEDURE
The procedure below is executable by a reviewer with no access to a node, no access to the programme's systems, and no relationship with the programme. Its inputs are: an exported record set, the canonical serialisation specification, the digest algorithm identifiers, the signed configuration manifests referenced by the set, the anchor list, and the witness receipts.
| Step | Action | A failure means |
|---|---|---|
| V-1 | Re-serialise each record canonically and recompute digest | The record has been altered, or the serialiser specification is incomplete — distinguish these before reporting |
| V-2 | Walk prev_digest from each anchor to the next; confirm continuity | The chain is broken between two anchors; the interval is not evidence |
| V-3 | Verify each anchor signature against the key identifiers named in the corresponding configuration manifest | The anchor was not produced by the article the manifest describes |
| V-4 | Match anchors to independently held witness receipts | The set may have been assembled after the fact; unanchored intervals must be reported as such |
| V-5 | Check sequence density within each epoch; every discontinuity must be met by a G-1 record | Records are missing and their absence was not declared — the most serious failure in this list |
| V-6 | Confirm every config_id appearing in the set resolves to a signed manifest, and recompute the manifest digest | Records exist that no known article configuration accounts for |
| V-7 | Check DC-1 consistency: no MEASURED value whose source is a derivation or model; every DERIVED value's evidence[] resolvable within the set | Provenance is misstated; quantitative claims from those values do not stand |
| V-8 | For each decision record, confirm Q1–Q3 are answered, that Q4 did not widen authority, and that execute outcomes carry a gate assertion and read-back | The decision cannot be reconstructed, which is a DC-5 failure independent of whether the decision was correct |
| V-9 | Recompute the digest of each raw reference still marked held that the reviewer has been given; confirm expired and lost references are matched by G-6 records | Raw support does not match its record, or expiry was silent |
A complete pass of V-1 to V-9 establishes that the record set is internally consistent, ordered as written, unaltered since anchoring, externally witnessed at the anchor points, complete within each epoch or explicitly incomplete, and sufficient to reconstruct each decision. It establishes nothing about whether the measurements were accurate, whether the sensors were characterised correctly, whether the models were appropriate, or whether the decisions were good ones. Those are separate questions answered at other rungs of the evidence ladder, and the fabric's job is to make them answerable rather than to answer them.