Skip to Content
Numinance
CLI

numi evidence verify

Verify an evidence export directory offline under keys you pin. Every flag, the three key modes, exit codes, JSON fields and real runs.

View as .mdUpdated
Available in public spec

The verifier and its conformance vectors are public. The open command is a wrapper over the public package sdk/go/evidenceverify.

Don't trust the agent. Check the evidence. verified means the chain is intact and signed by keys you pinned. It does not mean the code is correct.

What it does

numi evidence verify [flags] DIR checks an evidence/v1 export directory offline, read-only and with bounded reads. It needs no Numinance software and no network. It was written from the public specification, the JSON Schemas and the conformance vectors, and it passes every vector under conformance/evidence/v1/.

There is no built-in trust root. A result reaches verified only through runner keys, a log key and a log origin that you supply. A key that the export states about itself never gets there.

Synopsis

numi evidence verify --runner-key FILE [--runner-key FILE ...] --log-key FILE --log-origin ORIGIN DIR

Flags

FlagMeaning
--runner-key FILEA pinned runner public key (64 hex characters, at most 1024 bytes). Repeatable. Any pinned key may sign any record, the attestation or the manifest.
--trust-bundle-keysTrust the keys the export states (provenance/signers.json). The best level is self-consistent.
--skip-signaturesCheck no signature. The best level is unauthenticated.
--log-key FILE, --log-origin ORIGINThe pinned transparency log. Both or neither.
--allow-unanchoredAccept a head not proved under a pinned log.
--allow-incompleteAccept a chain with no terminal record.
--allow-unsignedAccept the export of an Abandoned or RolledBack change.
--completeFail when a part of the design list is absent.
--expect-change CHG_IDFail unless the chain is that change.
--expect-head DIGESTFail unless the last record hash, or the anchored head hash, is that digest.
--jsonPrint one JSON object.

An allowance flag suffixes the level only when the weakness it covers is present. A fully pinned, anchored, Closed export is a bare verified whatever the flags.

Key modes: choose exactly one

ModeFlagsBest levelUse when
Runner keys--runner-key (and --log-key with --log-origin)verifiedYou hold the runner public key and the log key from a source outside the export
Trust the bundle--trust-bundle-keysself-consistentYou only want to know the export is internally consistent
Skip signatures--skip-signaturesunauthenticatedYou only want hash-chain structure

Zero modes or two modes is a usage error.

numi evidence verify: choose exactly one key mode: --runner-key, --trust-bundle-keys or --skip-signatures
usage: numi evidence verify [flags] DIR
...
Exactly one key mode is required. A key the export states never reaches "verified".
✓ verifiednumi evidence verify with no key mode, run against a conformance export· numinance-spec @ 3c74d59 · 2026-11-09· 2
numi evidence verify: --log-key and --log-origin go together
usage: numi evidence verify [flags] DIR
...
✓ verifiednumi evidence verify --runner-key keys/runner.pub --log-key keys/log.pub exports/closed-author (no origin)· numinance-spec @ 3c74d59 · 2026-11-09· 2

A full pass

These runs use the conformance export exports/closed-author and keys from conformance/evidence/v1/, run from that directory.

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: ... same reason)
result: verified
✓ verifiednumi evidence verify --runner-key keys/runner.pub --log-key keys/log.pub --log-origin numinance.test/log --complete exports/closed-author· numinance-spec @ 3c74d59 · 2026-11-09· 0

Read the unsourced lines. They say the export carries no credential-broker statement and no egress-proxy statement, so the verifier did not and could not check credential scopes or network policy. verified is silent about them, and the report is not.

Weaker results and failures

Pin the wrong runner key and the result is a failure, exit 3:

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
result: failed
✓ verifiedthe same export with --runner-key keys/other-runner.pub· numinance-spec @ 3c74d59 · 2026-11-09· 3

(Only the finding lines are shown; the rest matches the pass above. part_contradiction appeared twice.)

Pin the runner key but omit the log, and you get a consistent export that is weaker than verified, exit 5:

level: unanchored
signatures: verified under the pinned runner keys
anchor: not checked (no log pinned)
WEAK the head was not proved under a pinned log
result: unanchored
✓ verified--runner-key keys/runner.pub exports/closed-author· numinance-spec @ 3c74d59 · 2026-11-09· 5

(Excerpt of the report.) Add --allow-unanchored and the same run exits 0, but the level says so:

level: verified, unanchored
anchor: not checked (no log pinned)
result: verified, unanchored (a pass with an allowance: unanchored)
✓ verified--runner-key keys/runner.pub --allow-unanchored exports/closed-author· numinance-spec @ 3c74d59 · 2026-11-09· 0

Trusting only the keys the export states:

level: self-consistent
signatures: verified under keys the export states only
anchor: not checked (no log pinned)
WEAK signatures verified only under keys the export states
WEAK the head was not proved under a pinned log
result: self-consistent
✓ verified--trust-bundle-keys exports/closed-author· numinance-spec @ 3c74d59 · 2026-11-09· 5

An expectation mismatch is a failure even when everything else verifies:

level: failed
FAIL expectation_mismatch: the change is not the one expected
result: failed
✓ verifiedfull pinning plus --expect-change chg_02020202020202020202020202020202· numinance-spec @ 3c74d59 · 2026-11-09· 3
numi evidence verify: the directory does not exist
✓ verified--skip-signatures on a directory that does not exist· numinance-spec @ 3c74d59 · 2026-11-09· 4

Exit codes

CodeMeaning
0A pass, with or without an allowance
1Internal error or cancel
2Usage
3A report with a finding, or a refused directory path
4The directory does not exist
5A consistent export weaker than verified
7An I/O error
8Timeout

Exit 6 is never produced by verify. An allowance-bearing pass such as verified, unanchored exits 0, so automation that needs a full pass must check the JSON, not the exit code alone.

JSON output

{"ok":true,"change_id":"chg_01010101010101010101010101010101","records":12,"head_record_hash":"sha256:8dec4e3d5cf4bd7650ef6010671298793c05493cb20c3dd946bc3ef805689e48","anchored_head_record_hash":"sha256:8dec4e3d5cf4bd7650ef6010671298793c05493cb20c3dd946bc3ef805689e48","ended":true,"terminal_state":"Closed","sealed":false,"level":"verified","level_enum":"verified","weakened_by_flags":[],"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","not_applicable":[{"part":"deployment.json","reason":"...","owner":"...","not_applicable":true},{"part":"observation.json","reason":"...","owner":"...","not_applicable":true}],"credential_scopes":"unsourced: no credential broker statement is in the attestation","network_policy":"unsourced: no egress proxy statement is in the attestation"}
✓ verifiedthe full-pass run with --json· numinance-spec @ 3c74d59 · 2026-11-09· 0

(The reason and owner strings of the two not_applicable entries are shortened here.)

FieldMeaning
okTrue for a pass, including a pass with an allowance. Not a full-pass signal.
change_id, recordsThe change and the number of records in the chain
head_record_hash, anchored_head_record_hashThe last record hash, and the head hash the log proved
ended, terminal_state, sealedWhether the chain ended, how, and whether it is sealed
levelHuman-readable level; may carry a suffix such as , unanchored
level_enumThe machine-readable level. Test this, never a prefix of level
weakened_by_flagsThe allowances that covered a weakness that is present. Empty for a full pass
weaknessesPresent when the level is weaker than verified; for --skip-signatures it read no signature was checked and the head was not proved under a pinned log
chain, signatures, anchor, attestationOne line per check
not_applicableParts declared not applicable, with reason and owner
credential_scopes, network_policyWhether the attestation carries a statement; unsourced means it does not
"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)"
✓ verified--skip-signatures with --json, excerpt of fields· numinance-spec @ 3c74d59 · 2026-11-09· 5

A verified result may still carry parts the index declares absent. Automation must read the absent list in the JSON report when there is one, or pass --complete. A script that needs a full pass should require level_enum == "verified" and an empty weakened_by_flags.

What a pass proves

  • It proves the chain links, hashes and ends as stated, that signatures verify under the keys you pinned, and that the head was proved under the log you pinned.
  • It does not prove the code is correct, the tests are thorough or the model reasoned well. It does not prove every event was logged if the host that wrote the evidence was compromised. This is a provenance check.
  • The open numi can verify an export but cannot create one: numi evidence export is not in the open build (see commands).

Troubleshooting

SymptomLikely cause
Exit 2, choose exactly one key modeNone or several of the three modes
Exit 3, signer_untrustedThe pinned key did not sign a record
Exit 5, level: unanchoredNo log pinned; pin the log or accept --allow-unanchored
Exit 4The directory does not exist

Next steps

On this page