Veriker
Recompute the answer. Don't trust the claim.
Status · Quick start · How it works · The verdict · Producing bundles · Scope and honesty
A composable, domain-agnostic verifier for re-derivable, attested artifacts. You hand it a self-contained audit bundle: a manifest, the input snapshots, and a re-derivation rule. It independently recomputes the declared output and checks it against what was committed, and returns a structured verdict made of many small checks instead of one opaque pass/fail.
$ python examples/citation_integrity_minimal/build_bundle.py --out-dir /tmp/citation_bundle
$ veriker --bundle-dir /tmp/citation_bundle
veriker 0.2.1 (experimental)
PASS file_integrity
PASS spec_sha_pinning
PASS cross_refs
PASS plugin:spec_sha_pin
PASS plugin:file_integrity_many_small
PASS plugin:fragment_attestation
PASS plugin:coverage_sum_invariant
PASS plugin:source_attributes_consistency
PASS plugin:three_set_sum_invariant
PASS plugin:dispatch_record_wellformed
PASS plugin:stamp_lattice
PASS plugin:refinement_discharge
PASS (12 check(s) passed)
$ echo $?
0
$ echo ' (tampered)' >> /tmp/citation_bundle/snapshots/src-welfare-001.txt # one byte moves
$ veriker --bundle-dir /tmp/citation_bundle
veriker 0.2.1 (experimental)
FAIL file_integrity [bad_file_sha] 'snapshots/src-welfare-001.txt':
manifest_sha='89b92b23…' computed_sha='48fa2a73…'
…
FAIL (3 failures across 12 check(s))
$ echo $?
1
Real output from the citation-integrity pilot (long digests elided for width). The source a citation claims to quote changed by one byte. Two independent integrity checks catch it: the verdict is
REJECT, exit1. A verdict is recomputed, never asserted: each line is a property the verifier re-derived itself, and a cited source can never silently drift from the answer that stands on it.
🚧 Status: experimental
Veriker is v0.x. It is offered under the Apache-2.0 license as is.
Every verdict it produces carries verifier_version and
release_status: experimental on its face: the first line of every run is
veriker <version> (experimental). So a verdict forwarded out of context says
what this section says.
What that does promise. The verdict contract is fail-closed and mechanically
enforced: a bundle the verifier cannot re-derive is refused (ERROR, exit 2),
never passed; the shipped fuzz harnesses under tests/fuzz/ and the named
regression battery run on every change; and a silent false PASS is our
critical bug class: a verdict that says OK about an artifact that was
tampered is the defect this project exists to not have.
What it does not promise. No production, verified, or 1.0 claim is made
before a completed, dated third-party audit of the verifier core and the
DSSE/COSE/Rekor consumption paths, with its findings fixed. That audit is
committed to, and its target date will be published in SECURITY.md once the
engagement is booked. Releases are unsigned until the signing ceremony
(the first signed release is the v0.2 milestone of that plan, not a promise
this build makes). Interfaces may change between 0.x releases; the reason-code
vocabulary and the verdict face are versioned so a change is visible, not
silent.
Break it, and get named for it. If you can make this verifier print PASS
on an artifact you tampered, through any input a producer controls, that is
the finding we most want. SECURITY.md has the disclosure path and the
named-credit policy; audit_bundle/plugins/REASON_CODES.md and
audit_bundle/rederivation/THREAT_MODEL.md state what each check claims to
catch, so you know exactly which claim you are attacking.
💡 Concept
Tampering with an input, swapping the rule, or shipping a weaker specification all fail closed. The verifier distinguishes "the artifact is bad" from "I couldn't conclude," so a green result can never be faked by crashing the checker.
This is the open tier (Apache-2.0): the verifier, the bundle format, the substrate, the producer SDK, and a set of generic domain pilots. It stands alone: it imports no closed-tier code, and the core verify path needs no network and no third-party packages at audit time (stdlib only).
✨ Features
| 🔁 Recompute, don't attest | When a bundle declares outputs, the verifier re-derives the representative output with a verifier-side primitive and compares it to the committed value under a pinned comparator (exact, scalar_epsilon, set, text_normalized, structured). |
| 🧾 Self-contained bundles | A bundle is a directory: manifest + SHA-pinned specs + input snapshots + claimed outputs. The verifier reads no outside state. |
| 🚦 Tri-state verdict | OK (0) / REJECT (1) / ERROR (2). "The artifact is bad" is never conflated with "the verifier couldn't conclude." Neither is ever silently an OK. |
| 🔬 Localized failures | Every property is its own check with its own reason: a failure points at exactly what broke, not at one opaque boolean. |
| 🐍 Offline, stdlib-only verify | The core verify path makes no network calls and imports no third-party packages at audit time. |
| 🔒 Untrusted-bundle posture | The core path never executes bundle-supplied code. Running a bundle's own re-derivation pack is an explicit, flagged opt-in for trusted hosts only. |
| 🧰 Producer SDK | audit_bundle.emitter assembles verifier-conformant bundles (canonical, sorted, digest-matched manifests) with pluggable timestamp / causal-chain / attestation seams. |
| 🧪 Pilot gallery | Self-contained example domains: text extraction, sensor fusion, lockfile resolution, graph traversal, deterministic builds, tabular SQL aggregates, ML inference, streaming windows, and more. Each with its own tests. |
🚀 Quick start
Install the verifier from PyPI:
pip install veriker # the offline bundle verifier — Python ≥ 3.11
That installs veriker and nothing else — no transitive dependencies at all,
which is the packaging that makes the "stdlib-only" badge above checkable rather
than merely stated. You get the veriker command (veriker --bundle-dir <dir>,
equivalently python -m veriker), and most of the pilots below run on that
install alone (measured 2026-09-03: 45 of the 51 that ship both a builder and a
verify.py; the rest need an extra, an SMT solver, or torch, and say so when
you run them).
Four optional extras cover the paths that genuinely need third-party code. None is required to verify a bundle:
| Extra | Pulls | For |
|---|---|---|
veriker[crypto] |
cryptography, rfc8785 |
Ed25519 verdict signatures (examples/caselaw_citation_gate), and the DSSE / Fulcio / revocation consumption paths |
veriker[c19] |
the above + py_ecc, cbor2 |
the C19 cross-host / trusted-time layer |
veriker[hostverify] |
tuf |
host_digest_verify, the network-connected host-digest path |
veriker[all] |
all of the above | if you would rather not choose |
What the extras do not imply. No pilot in this repo ships a DSSE envelope or a Rekor transparency-log anchor, and none imports
audit_bundle.dsse,rekor_anchor,fulcio_identityorc18_tuf_client. Those modules are implemented and unit-tested, but nothing in the shipped example set exercises them end to end — so please do not read the presence oftuforcryptographyin an extra as evidence that transparency-log-backed attestation is proven here. Theverikercommand does import fromaudit_bundle.dsse, but only its stdlib-only part (paeandversion_map); the envelope, payload, set-closure and revocation modules, which carrycryptographyandrfc8785, are imported lazily and are not reached from the CLI.
To build and run the example pilots below, or to develop, clone the repo and install from source instead:
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]" # Python ≥ 3.11; includes the pilots under examples/
Build a pilot: a citation-integrity bundle that proves an AI/RAG answer actually quotes its cited sources. (No LLM in the loop: the verifier re-derives every cited span from the frozen source snapshots and checks each quote against its source under a deterministic, versioned text normalization that is case-, whitespace-, and punctuation-insensitive, not byte-exact.) Then verify it:
python examples/citation_integrity_minimal/build_bundle.py --out-dir /tmp/citation_bundle
veriker --bundle-dir /tmp/citation_bundle # exit 0, 12 checks PASS
Then tamper with any committed snapshot and re-run verify. It fails closed
with exit 1, as in the demo above.
More pilots, more shapes: every examples/ entry is one computation shape
Each pilot under examples/ is a self-contained bundle builder plus its own
tests/, demonstrating one computation shape end-to-end: text extraction,
sensor fusion, lockfile resolution, graph traversal, seed-pinned release,
deterministic build & compilation, raster aggregation, tabular SQL aggregates,
integer- and float-ML inference, audio segmentation, event-time streaming
windows, and more. Each pilot's README states the exact property it
demonstrates, and the explicit limits of that claim.
ls examples/
python examples/<name>/build_bundle.py --help
🔍 How it works
A bundle is a directory the verifier can read with no outside state:
bundle/
├── manifest.json # files + SHA-256 digests, spec pins, declared outputs, typed checks
├── spec/ # the SHA-pinned specification(s) the manifest commits to
├── <inputs>/ # the committed input snapshots (corpus, lockfile, traces, …)
└── outputs/ # the claimed output value(s) the verifier will re-derive and compare
The verifier runs built-in steps (file integrity, spec-SHA pinning,
cross-references) plus a set of typed-check plugins, and, when the bundle
declares outputs, re-derivation dispatch: it recomputes the representative
output with a verifier-side primitive and compares it to the committed value under
a pinned comparator (exact, scalar_epsilon, set, text_normalized,
structured). Every check is reported on its own line so a failure points at
exactly which property broke.
How is this different from a checksum? A checksum answers "are these the same bytes?" This answers "is this output the deterministic result of this rule over these inputs, and does every committed invariant still hold?" It also localizes the answer to individual checks.
🚦 The verdict: OK / REJECT / ERROR
The verifier is tri-state, and the distinction is load-bearing:
| Verdict | Exit | Meaning |
|---|---|---|
OK |
0 |
every gating check passed. |
REJECT |
1 |
the artifact failed a check: tampering, drift, a forged field. |
ERROR |
2 |
the verifier could not conclude: e.g. a bundle claims a re-derivation but the pack was not executed, or an external dependency is absent. Never silently an OK. |
There is no ERROR → retry → accept path: both REJECT and ERROR are non-zero
(not certified). New automation can split "artifact is bad" (1) from "verifier
couldn't conclude / file a bug" (2); old scripts keying on exit != 0 stay
correct. REJECT is about the input; ERROR is about the verifier. That means
a crafted verifier-crashing input can't be laundered into a fake REJECT.
Automation that wants more than the exit code can pass
--verdict-out verdict.json: the verifier writes the full verdict face as JSON
on every exit path: state and exit code, machine-stable reason codes, which
validation layers ran, honest disclosures a green verdict still carries, and the
SHA-256 of the manifest it judged. It is an unsigned operational artifact
(the file says so in its note field): trust comes from deterministically
re-running the verifier on the bundle, never from the file itself.
🧰 Producing bundles — the emitter SDK
The producer side is the open SDK at audit_bundle.emitter. It assembles a
verifier-conformant bundle (canonical, sorted, newline-terminated manifest with
matching digests) and exposes pluggable hook seams:
from audit_bundle.emitter import (
BundleContent, write_bundle, assemble_manifest,
TimestampProvider, CausalChainEmitter, AttestationProvider,
StaticTimestampProvider, NullCausalChainEmitter, NullAttestationProvider,
)
The open defaults (Static* / Null*) emit a clean baseline bundle with no
network calls. The *Provider interfaces are the extension points where richer
timestamp / causal-chain / attestation implementations plug in. Every pilot under
examples/ builds its bundle this way. See any pilot's build_bundle.py (some
are named _build_bundle.py) for a worked example, and
tests/test_emitter_sdk.py for the conformance contract.
Spec-pinned dispatch (how pilots self-verify)
Each pilot proves its published output is the deterministic recompute of its
committed input under an auditor-pinned comparator. The auditor binding is the
pilot's committed spec_pinned/<domain>.spec.json: which primitive recomputes
the representative output, and the comparator kind. The auditor's anchor is
derived from the committed spec bytes, not from the bundle's own copy, so a
bundle that ships a weaker spec yields a digest the anchor does not list and
verification fails closed.
Two wiring styles for this anchored dispatch in examples/
You will see two styles, distinguished by whether a spec_pinned_check.py is
present:
- Current: the anchored dispatch is consumed directly in the pilot's own
verify.pyvia aSpecAnchorand exercised by itstests/; there is no standalone driver. E.g.caselaw_citation_gate_minimal,iso42001_vnv_minimal. - Legacy: the anchored dispatch is a standalone
spec_pinned_check.pybuild→verify driver alongside the pilot's test. E.g.tabular_minimal,raster_minimal. Here the pilot's ownverify.pyis a separate entry point that runs the pilot's re-derivation check, not theSpecAnchordispatch. Either way the acceptance criterion is resolved on the auditor's side: an exact recompute match, or the tolerance pinned in the committedspec_pinned/<domain>.spec.json, never a producer-asserted value.
New pilots should follow the Current style.
📁 Repository layout
| Path | What |
|---|---|
cli/ |
Command-line tools: verify (the bundle verifier, answering "is this bundle internally valid?") and host_digest_verify (the verifier-identity check, wrapping cosign / crane to bind a running container's image digest to the TUF-fetched release digest). For ordinary local bundle verification host_digest_verify is optional; for a public-release ceremony it is the required verifier-identity trust mechanism and its result must be run and retained. verify() cannot answer the identity question itself. Pre-ceremony: the C18 TUF roots are still synthetic and no hardware-signed release has been cut, so the full TUF-gated identity flow is not yet live (it becomes runnable at the C18 key ceremony + first signed release). See SECURITY.md → "Verifier-identity trust boundary (C18)". |
audit_bundle/ |
The substrate: bundle format and manifest, the verifier, the producer emitter SDK, typed-check plugins, extensions, discharge, fragments, and coverage. |
coverage/ |
Closed-world coverage plugin (sum-invariant grading). |
examples/ |
Generic domain pilots, each a self-contained bundle plus its own tests/. |
tests/ |
The open verifier + substrate test suite. |
MANIFEST_SCHEMA.md |
The bundle manifest schema. |
VERIFIER_CONTRACT.md |
The normative offline-verifier contract: every clause indexed to the test that enforces it. |
🧪 Run the tests
pip install -e ".[dev]"
pytest # the open verifier + substrate suite
pytest examples/<name>/tests/ # a single pilot's suite (run per-example)
python scripts/run_example_batteries.py # every pilot's suite
python scripts/run_example_batteries.py --list # what it would run
Each pilot under examples/ ships its own tests/ package and is invoked
separately. The suites are isolated by design. That isolation is required, not
stylistic: pilot-local module names repeat across the fleet (many pilots ship a
_build_bundle.py, a verify.py, a spec_pinned_check.py), and each suite
puts its own directory on sys.path, so collecting several into one process
resolves those imports against whichever pilot was collected first. The runner
above gives each pilot its own interpreter; pytest examples/ is refused with a
message pointing at it, rather than reporting a number that looks measured.
🧭 Scope and honesty
Every pilot's data is synthetic. A pilot demonstrates that the substrate can re-derive a declared output and detect tampering or drift against committed inputs. It is evidence for a verification property, never a claim that a real deployment is "compliant" with any named standard. The check proves the value is the deterministic output of the committed computation over the committed input under the auditor's comparator; it is not a claim that the computation or the input are themselves correct, and a pilot's self-check re-runs the producer's own re-derivation pack (a round-trip), not an independent re-implementation. Read each pilot's README for the exact property it demonstrates and the explicit limits of that claim.
What the CLI re-derives, and where it does not. The tool re-derives an
artifact under an auditor's own anchor wherever a kit ships or the shape is
promoted. It does not re-derive the whole pilot fleet. A spec binds its output
type to a primitive_id; the CLI can run that method when it is one of the
promoted primitives the distribution carries
(PRIMITIVES.md, which also renders
the current reach from the tree), or when the pilot ships an auditor kit you point
it at with --primitives. Where neither holds, the primitive lives in the pilot's
own directory, the CLI cannot load it, and the run reaches UNKNOWN_PRIMITIVE
instead of a verdict. A bundle the CLI cannot re-derive is refused, not passed.
The gap costs you a verdict, never a false green.
Which claims must arrive is your call too. Under dispatch the producer still
chooses the SET of outputs it declares. It can drop a claim and substitute a decoy,
declare an extra one under a valid type, or stop naming a spec so its rules leave
the coverage denominator. --work-set WORK_SET.json hands the CLI your complete
enumeration ({"pins": {"<output_id>": "<type_key>"}}, optionally withheld);
the bundle must then deliver exactly that multiset, each output under its pinned
type, or the verdict is WORK_SET_VIOLATION. Without it the face says selection
was the producer's (type_selection: NO auditor work-set).
The verifier's own guarantees are held to the same standard:
VERIFIER_CONTRACT.md states them as a normative
contract: offline, stdlib-only import boundary, structural-only scope,
tri-state verdict, no silent upgrade of unevaluated evidence. It also indexes
every clause to the test that enforces it. The stdlib-only claim itself is
ratcheted: the test suite imports the verifier and re-verifies bundles under
an import hook that blocks every third-party package.
🔒 Security · Contributing · License
- Security: see SECURITY.md to report a vulnerability.
- Contributing: issues and pull requests are welcome; see
CONTRIBUTING.md (we use the DCO, not a CLA). New pilots
follow the Current spec-pinned wiring above; run
pytestbefore submitting. - Governance & trademark: GOVERNANCE.md, TRADEMARK.md, and our no-relicense pledge.
- License: Apache License 2.0, see LICENSE and NOTICE.
Veriker is built and maintained by the team at Nexi Technologies, Inc. We also build NEXIVERIFY, a commercial audit-trail product for regulated teams. Veriker is and remains free and open under Apache-2.0. See our no-relicense pledge.
Recompute the answer. Don't trust the claim.
Apache-2.0 · offline verify · stdlib-only at audit time
Metadata
Release files for veriker 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| veriker-0.2.1.tar.gz | 1.5 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| veriker-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.4 MB
Release files / veriker-0.2.1.tar.gz
| Download URL | veriker-0.2.1.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
11c50788a8f1f31649cdf72a1eba88bb092fe86d538d49a389e02c22f6f9537a
|
|
BLAKE2b-256 checksum How to use checksums |
8377774046024c911a478f24f1ef1889ab096987cbbf0ac69b9f05d3a699f988
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / veriker-0.2.1-py3-none-any.whl
| Download URL | veriker-0.2.1-py3-none-any.whl |
|---|---|
| Size | 906.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
466dd276f5c57b59316ea0faf64711a76ea6d8944b54c9854bc9f82796016dea
|
|
BLAKE2b-256 checksum How to use checksums |
afd86b2548ad50c4edd3d8fb319fa4a24280474494145773ad7f618895b91dfd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logSecurity for veriker 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for veriker-0.2.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.