Skip to Content
Numinance
Get started

Evidence quickstart

Verify a real evidence/v1 export offline under pinned keys, then watch a wrong key, a self-stated trust bundle and skipped signatures each change the result.

View as .mdUpdated
Available in public spec
The verifier and the conformance exports are in the public tree. Exporting evidence from a run is an engine function and is not in the open build.
Don't trust the agent. Check the evidence, under keys you chose, without a network and without the system that wrote it.

What you need

  • A built numi and a clone of numinance-spec (install).
  • The conformance fixtures. Run every command below from conformance/evidence/v1 inside the clone. It holds keys/ (public keys) and exports/ (golden export directories). The example export is exports/closed-author: a change that ran to a Closed terminal state at pull-request level.

You do not need to generate an export. numi evidence export is designed and not in the open build; calling it is an unknown subcommand and exits 2.

The pinned-key run

From conformance/evidence/v1
numi evidence verify \
  --runner-key keys/runner.pub \
  --log-key keys/log.pub \
  --log-origin numinance.test/log \
  --complete \
  exports/closed-author
change: chg_01010101010101010101010101010101
records: 12, head sha256:8dec4e3d5cf4bd7650ef6010671298793c05493cb20c3dd946bc3ef805689e48
state: ended Closed
level: verified
chain: records link, hash and end as stated
signatures: verified under the pinned runner keys
anchor: head proved under the pinned log
attestation: signed, re-derived from the chain
credential_scopes: unsourced: no credential broker statement is in the attestation
network_policy: unsourced: no egress proxy statement is in the attestation
not applicable: deployment.json (not applicable at PR level: the change closed from Merging (design section 6) and was never released, deployed or observed)
not applicable: observation.json (not applicable at PR level: the change closed from Merging (design section 6) and was never released, deployed or observed)
result: verified
✓ verifiedfull verification of the closed-author export· numinance-spec @ 3c74d59 · 2026-11-09· 0

The flags

FlagWhat it does
--runner-key FILEA runner public key you pin (64 hex characters). Repeatable. Any pinned key may sign any record, the attestation or the manifest.
--log-key FILE, --log-origin ORIGINThe transparency log you pin. Give both or neither. This is what lets the head be proved as published.
--completeFail if any part of the design list is absent. A part that is not applicable at PR level, such as deployment and observation, is not absent.
--trust-bundle-keysTrust the keys the export states about itself. Caps the result at self-consistent.
--skip-signaturesCheck no signature. Caps the result at unauthenticated.
--allow-unanchored, --allow-incomplete, --allow-unsignedAccept a named weakness; the level is suffixed with it.
--expect-change CHG_ID, --expect-head DIGESTFail unless the chain is that change, or its head matches that digest.
--jsonOne JSON object, including level_enum, weakened_by_flags and anchored_head_record_hash.

Exactly one key mode is required. There is no built-in trust root: a key that comes from the export never reaches verified.

Wrong key: exit 3

Pin a different runner key and the same export fails.

change: chg_01010101010101010101010101010101
records: 0, head 
state: open (no terminal record)
level: failed
chain: failed
signatures: not verified
anchor: not proved
attestation: none
credential_scopes: unsourced: no credential broker statement is in the attestation
network_policy: unsourced: no egress proxy statement is in the attestation
absent: deployment.json (not applicable at PR level: the change closed from Merging (design section 6) and was never released, deployed or observed; owner: release context (Gate B): a change that is released is deployed and observed by it)
absent: observation.json (not applicable at PR level: the change closed from Merging (design section 6) and was never released, deployed or observed; owner: release context (Gate B): a change that is released is deployed and observed by it)
FAIL signer_untrusted: a record names a key that is not trusted
FAIL part_contradiction: a part is declared not applicable and the chain does not bear it out
FAIL parts_absent: a part is absent and --complete was given
FAIL part_contradiction: a part is declared not applicable and the chain does not bear it out
FAIL parts_absent: a part is absent and --complete was given
result: failed
✓ verifiedthe same export with keys/other-runner.pub as the runner key· numinance-spec @ 3c74d59 · 2026-11-09· 3

Exit 3 means the report has at least one finding. signer_untrusted is the root cause. The part_contradiction and parts_absent findings follow because a "not applicable" claim needs a verified chain behind it; when the chain did not verify, nothing shows the change closed at PR level, so each claim counts as a contradiction and the parts as absent.

Trust bundle only: exit 5

Ask the verifier to trust the keys the export states about itself:

Self-stated keys
numi evidence verify --trust-bundle-keys exports/closed-author
change: chg_01010101010101010101010101010101
records: 12, head sha256:8dec4e3d5cf4bd7650ef6010671298793c05493cb20c3dd946bc3ef805689e48
state: ended Closed
level: self-consistent
chain: records link, hash and end as stated
signatures: verified under keys the export states only
anchor: not checked (no log pinned)
attestation: signed, re-derived from the chain
credential_scopes: unsourced: no credential broker statement is in the attestation
network_policy: unsourced: no egress proxy statement is in the attestation
not applicable: deployment.json (not applicable at PR level: the change closed from Merging (design section 6) and was never released, deployed or observed)
not applicable: observation.json (not applicable at PR level: the change closed from Merging (design section 6) and was never released, deployed or observed)
WEAK signatures verified only under keys the export states
WEAK the head was not proved under a pinned log
result: self-consistent
✓ verifiedtrust the keys the export states· numinance-spec @ 3c74d59 · 2026-11-09· 5

Exit 5 means a consistent export that is weaker than verified. The chain is intact, but an attacker who builds a whole chain and signs it with their own key would pass this check too. Self-consistency proves the directory agrees with itself, not that it came from the runner you trust.

Skipping signatures

No signature check, JSON output
numi evidence verify --skip-signatures --json exports/closed-author
{"ok":false,"level":"unauthenticated","level_enum":"unauthenticated","weakened_by_flags":[],"weaknesses":["no signature was checked","the head was not proved under a pinned log"],"signatures":"not checked (--skip-signatures)","anchor":"not checked (no log pinned)"}
✓ verifiedskip signature checks; JSON fields shown are those of the real report· numinance-spec @ 3c74d59 · 2026-11-09· 5

The snippet shows the decision fields of the real report. The full object also carries change_id, records, head_record_hash, anchored_head_record_hash, ended, terminal_state, sealed, chain, attestation, not_applicable, credential_scopes and network_policy. Links, digests and re-derivations are still checked; only signatures are not.

What each level means

LevelMeaningExit
verifiedRecords link and hash, signatures check under your pinned runner keys, and the head is proved under your pinned log.0
unanchored, incomplete, unsignedA single named weakness, reachable by passing the matching --allow- flag.5 without the flag, 0 with it, suffixed in the level
self-consistentConsistent, signed under keys the export itself states.5
unauthenticatedConsistent, but no signature was checked.5
failedAt least one finding.3

Reading results in automation

  • A pass with an allowance, such as verified, unanchored, exits 0. Never test whether level starts with verified.
  • A full pass is exit 0, level_enum equal to verified and an empty weakened_by_flags. Test all three.
  • A verified result can still list absent parts. Read the absent list in the JSON, or pass --complete.
  • Use --expect-change and --expect-head to bind the result to the change and head you expected, not just any valid chain.

What verified does and does not prove

verified proves provenance and chain integrity under the keys you pinned. It does not prove that the code is correct, that tests were thorough, that the model reasoned well, or that a compromised host logged every event. The two unsourced lines above are a reminder: the attestation carries no credential-broker or egress-proxy statement, so those claims are not backed here.

Inspect a chain interactively

The component below shows how records link into a chain and where each level of the verifier gains or loses its guarantee.

Evidence chain inspector

What does verification actually establish, and which inputs does it depend on?

Illustrative · simulated
Key source
Anchor
Tamper

Hash-linked records (drawing 6 of 12)

  1. seq 1link

    previous_record_hash empty (sequence 1)

    signature verified
  2. seq 2link

    links to previous

    signature verified
  3. seq 3link

    links to previous

    signature verified
  4. seq 4link

    links to previous

    signature verified
  5. seq 5link

    links to previous

    signature verified
  6. seq 12 (head)link

    terminal state: Closed

    signature verified

attestation.json

signed summary, re-derived from the chain

verified

head-checkpoint + inclusion proof

checked under the pinned log key and origin

verified

Verifier inputs (what you bring, not what the export says)

  • ✓ pinned runner key(s)
  • ✓ pinned log key + origin
  • provenance/signers.json and any checkpoint in the export are claims, not trust.

numi evidence verify --runner-key keys/runner.pub --log-key keys/log.pub --log-origin numinance.test/log --complete exports/closed-author

simulated output, shape as in the real CLI

change: chg_01010101010101010101010101010101
records: 12, head sha256:8dec4e3d…
state: ended Closed
level: verified
chain: records link, hash and end as stated
signatures: verified under the pinned runner keys
anchor: head proved under the pinned log
attestation: signed, re-derived from the chain
result: verified

exit 0

level: verifiedexit 0

Provenance and chain integrity hold under keys and a log you pinned.

What this does NOT prove, at any level

  • The code is correct.
  • The tests are thorough.
  • The model reasoned well.
  • Completeness against a compromised host: events it never logged are not in the chain.

Level verified, exit 0. No findings or weaknesses.

✓ verified◐ weak (consistent, not authenticated)✕ failed– not checked
Text description

Illustrative and simulated: no export is read. The rules are those of docs/evidence/verification.md; the baseline report is the real output of the open verifier on the conformance export exports/closed-author.

  • You must choose exactly one key mode. Pinned runner keys (--runner-key) are the only way to reach verified. --trust-bundle-keys takes the keys the export claims and tops out at self-consistent. --skip-signatures tops out at unauthenticated.
  • A pinned log (--log-key with --log-origin) is needed to prove the head. Without it the result is unanchored (exit 5) unless --allow-unanchored is given.
  • Any finding makes the level failed (exit 3). Edit or remove a record: chain_broken. A chain signed by a key you did not pin: signer_untrusted. With keys from the export or signatures skipped, the same forged-but-consistent chain is not caught, which is why those levels are weaker.
  • Exit codes: 0 verified, 3 failed, 5 consistent but weaker than verified.

Verified does not prove the code is correct, the tests are thorough, the model reasoned well, or that a compromised host logged every event.

Troubleshooting

SymptomCauseFix
Exit 2, "exactly one key mode"None or more than one of the pinned keys, --trust-bundle-keys, --skip-signatures.Pass exactly one mode.
Exit 4The export directory does not exist.Check the path relative to where you ran the command.
Exit 3 with signer_untrustedThe pinned key is not the one that signed.Pin the correct runner key, from a source you trust.
Exit 3 with expectation_mismatch--expect-change or --expect-head did not match.You may be verifying a different chain than you expected.
Exit 5A consistent export weaker than verified.Pin keys and a log, or decide explicitly which allowance you accept.

Next steps

On this page