Evidence refs
Evidence Refs
Every fact must be backed by evidence. evidence_refs is the primitive that stores provenance: where a claim came from, when the event happened, when Mnemix learned it, and how much trust it earns. It is the foundation of Mnemix's audit guarantee, and it's why a locked fact can never be created out of thin air.
Vector databases retrieve similar text. Mnemix retrieves provenance-backed truth.
What an evidence ref is
An evidence ref is a pointer to a source plus the metadata needed to defend a claim later. When an enterprise asks "why did the agent approve this $5,000 refund?", Mnemix points to the exact evidence ref and the exact locked fact that was active at that millisecond.
Schema
The substrate table (as shipped in the live migrations):
| Column | Type | Description |
| :--- | :--- | :--- |
| ref_id | uuid | Primary key. |
| tenant_id | uuid | Row-level security isolation. |
| source_type | text | user_confirmed, system_inferred, document_extracted, … |
| source_uri | text | Pointer to the raw data: a message ID, a document URL, a GitHub PR link. |
| content_hash | text | Hash of the cited content — detects drift if the source changes. |
| source_priority | int | Trust rank — drives supersession ordering. |
| parent_ref_id | uuid | Lineage self-reference (which evidence this was derived from). |
| event_time | timestamptz | When the event happened in the world (caller-supplied). |
| ingestion_time | timestamptz | When Mnemix processed it (set by the system). |
| valid_range / tx_range | tstzrange | Generated bi-temporal ranges over the two timestamps, GiST-indexed for as-of queries. |
| tenant_secret_hash | text | Reserved (nullable) for tamper-evident audit keying. |
Two things are deliberately absent:
- No namespace or key column. Evidence is address-agnostic by design — addressing lives on
locked_facts(entity_id+fact_key). Adding a domain key to evidence is a locked-out schema change. - No mutable validity scalars. The bi-temporal window is the generated
valid_range/tx_rangepair — see Bi-temporal Validity.
Source types and trust
source_type plus source_priority rank how much trust a claim earns. A user_confirmed source outranks a system_inferred one — and that ordering drives supersession (a higher-priority source supersedes a lower one).
| source_type | Meaning | Typical trust |
| :--- | :--- | :--- |
| user_confirmed | A human explicitly confirmed it. | Highest |
| document_extracted | Pulled from a cited document (statement, contract, PR). | High |
| system_inferred | Derived by the system from other facts. | Lower |
Creating an evidence ref
You don't create one over a public REST route today — evidence rows are written by the substrate when facts are asserted (the supersession-safe stored procedures record the fact and its provenance together). A public facts/evidence API is on the beta roadmap; until it ships, evidence enters through the ingestion paths (calls, observations) and internal tooling.
Why content hashing matters
The content_hash lets Mnemix detect when a cited source changed underneath a fact. If the August bank statement is re-uploaded with different numbers, the hash no longer matches — the system can flag the locked fact for re-confirmation rather than continuing to assert a value whose evidence has shifted.
Evidence refs surface in verdicts
Every gate verdict is designed to include the evidence refs that justify it (Weld B in the architecture — non-negotiable): a denial that can't cite its evidence is a bug. The gate itself is in development; the contract is spec-frozen so integrations can design against it now.
Relationship to other primitives
- locked_facts require provenance — no evidence, no fact.
- bi-temporal validity is implemented on the
valid_range/tx_rangepairs here and on facts. - The gate returns these refs so verdicts are defensible and rerunnable.
See also
- Locked Facts — what evidence refs back.
- Bi-temporal Validity — the time model these ranges implement.