# Verification

How enruta-verify 0.3.0 checks a payment record or a linked record, offline, and what PASS and FAIL mean.

Status: Live · Updated: 2026-09-14
Source: https://enruta.ai/docs/verification

`enruta-verify` is a single-file, dependency-free program, Apache-2.0, shipped inside every export. It needs no network and no Enruta account. Version 0.3.0 verifies all three schemas and every linked kind.

## What it checks

1. **Canonical form.** Re-canonicalizes the record (RFC 8785), confirms the bytes are canonical, and names the schema it found (`enruta/0`, `enruta/0.2` or `enruta/0.3`).
2. **Seal.** Recomputes SHA-256 over the canonical bytes and compares it with `seal.hash` and the record id.
3. **Chain.** Confirms `seal.prev` matches the previous record when it is present in the same export, and reports a gap otherwise. Linked records are chain members like any other; `chain.of_hash` is checked against the referenced record when both are present.
4. **Attestations.** Validates each RFC 3161 token against the snapshotted authority certificates, and checks the daily-root inclusion proof and the root’s signature. An OpenTimestamps proof of the daily checkpoint, when the bundle lists one, is reported as `ots: pending` or `ots: attested`, without network access.
5. **Keys.** Confirms every key referenced in `keys` is in the bundle with a provenance tag, and that signatures over the approval, the policy, the mandate, the merchant’s checkout and receipt, a linked record’s `subject` and the `risk` assessment verify under those keys.
6. **Evidence.** On `enruta/0.3` records, re-hashes each anchor’s evidence in `artifacts.identity[]` against its `evidence_hash`, and the model’s input and output in `artifacts.judgement_io` against `judgement.model.input_hash` and `output_hash`.
7. **Strength.** Reports the record’s own strength labels, including `strength.subject` on linked records. It never upgrades a self-asserted claim.

## Running it

```bash
npx enruta-verify rec_01M25129GZMJXTNQ47TMZRDGHN.json     # one record, bundle found alongside
npx enruta-verify ./export-2026-09/                    # a whole export, chain checked end to end
npx enruta-verify rec_01M2G8Z0Q4W7T2K9N5B3D6H1XC.json --json   # machine-readable report
```

| Exit code | Meaning |
|---|---|
| `0` | PASS: every check passed |
| `1` | FAIL: at least one check failed; the report names it |
| `2` | Could not verify: missing bundle or unreadable input; nothing is claimed either way |

## A linked record

```text
# enruta-verify 0.3.0
# rec_01M2G8Z0Q4W7T2K9N5B3D6H1XC  org_halvern  #13  kind reversal  reversal_of rec_01M25129GZMJXTNQ47TMZRDGHN
# canonical form   ok       RFC 8785, schema enruta/0.2
# seal             ok       sha256:c19b…8e02
# chain            ok       prev rec_01M25129GZMJXTNQ47TMZRDGHN, of_hash matches
# attestations     ok       1 time-stamp valid, daily root 2026-09-13 checkpoint ok
# keys             ok       3 referenced, snapshot 2026-09
# strength         ok       subject=third_party_signed (merchant key_merchant_store_2026-09), policy=customer_attested
# PASS
```

## What FAIL looks like

```text
# canonical form   ok       RFC 8785, schema enruta/0.2
# seal             FAIL     hash mismatch: record bytes were modified after sealing
# chain            ok       prev rec_01M25129GZMJXTNQ47TMZRDGHN
# attestations     ok       1 time-stamp valid
# keys             ok       3 referenced, snapshot 2026-09
# strength         ok       subject=third_party_signed
# FAIL (1 of 6 checks failed)
```

A back-dated record fails on attestations: the time-stamp tokens prove the seal existed no earlier than the authority said, and a `created_at` before that is reported. A reversal whose `subject.amount` was edited fails on the seal, and its merchant signature no longer verifies.

## Reproducing it

The schema, the canonicalization rules, the test vectors and the verifier source are published together. The vectors cover a valid v0 chain, a tampered record, a back-dated record, a chain gap, and since 0.2.0 `valid-v02/` (a payment followed by a reversal, a settlement record and a reconciliation line) and `tampered-linked/` (a reversal whose amount was edited), and since 0.3.0 `valid-v03/` (a clarified, model-judged payment at assurance A3, and a recurrence) and `tampered-identity/` (an identity anchor whose evidence was changed). Anyone can write another verifier and check it against them.
