Skip to main content

emet: byte-level integrity witness. A witness that reports what it found, and decides nothing.

Byte-level integrity witness. Four independent implementations, one verdict lattice.

PyPI license: MPL-2.0 downloads CI python deps: none

EMET checks whether the bytes reaching a model, a reviewer, or a pipeline still match the source they claim to represent, then emits one of three closed verdicts: MATCH, DRIFT, or UNVERIFIABLE. Four clean-room implementations, in stdlib-only Python, Rust, Node.js, and Go, load the same marker corpus and re-derive it identically against a shared conformance suite. Zero dependencies: run it straight from a checkout or pip install emet.

emet is Hebrew for "truth."

Features

  • Portable witness receipts (SPEC s.17). Seal any verdict into a self-contained, content-addressed JSON receipt; a different party re-verifies it offline with emet check, zero shared state, zero trust in the producer. The same subject and verdict yield a byte-identical receipt_id across Python, Rust, and Node.js, and each implementation verifies the others' HMAC signatures. Cross-language parity, including the tampered-receipt negatives, is gated in CI.
  • Stripped-credential rebind (SPEC s.18, experimental). When a re-encode, screenshot, or copy strips a C2PA-style embedded credential, the artifact is orphaned to embedded-metadata verifiers. EMET anchored the raw bytes out of band, so emet rebind re-derives the naked bytes' content hash and rebinds them to a known anchor: MATCH (rebound), DRIFT (a claimed identity over substituted bytes), or UNVERIFIABLE (no known anchor, the honest default).
  • Byte-hash core. anchor pins raw-byte SHA-256 hashes, verify recomputes them, coherence compares a presented view against its source, corroborate hashes the same file through disjoint read paths to catch a tampered read path, not just a broken hash.
  • In-band authority stripping. refuse scans bytes against a versioned marker corpus, reports every embedded authority claim by offset, and writes a neutralized copy. It reports the claims; it never obeys them.
  • Tamper-evident audit chain. Every command appends to a hash-chained log; emet audit recomputes the chain and reports INTACT or BROKEN.
  • Four implementations, one contract. A frozen v1.0 spec, a language-agnostic conformance suite (48 vectors: 35 core, 5 receipt, 4 rebind, 4 eval-receipt), and clean-room ports in Rust, Node.js, and Go, all scored in CI on every push against exactly the capabilities each claims.
  • Machine-readable everywhere. --json on any command emits one canonical-JSON envelope; the governed fields are byte-identical across all four implementations and the exit code is unchanged.
  • Zero dependencies, by construction. Stdlib-only Python, no crates, no npm packages, no Go modules.

Usage

pip install emet
emet selftest        # re-derives the tool's own hash: emet_self_sha256=...

Or run it straight from a checkout, no install step at all:

git clone https://github.com/HarperZ9/emet && cd emet
python membrane.py selftest

emet <cmd> and python membrane.py <cmd> are equivalent. The full command surface:

emet anchor  <path>...              # pin raw-byte hashes
emet verify  <path>...              # MATCH / DRIFT / UNVERIFIABLE
emet coherence <source> <view>      # is a presented view faithful to source?
emet refuse  <file>                 # detect + strip in-band authority claims
emet corroborate <path>             # read-path-diverse agreement
emet audit                          # recompute the tamper-evident log chain
emet receipt --from-json <file|->   # portable, content-addressed witness receipt
emet check <receipt.json>           # stateless offline re-verify
emet rebind <naked> --manifest <m>  # rebind stripped bytes (experimental)
emet <any> --json                   # machine-readable canonical envelope

Exit codes (SPEC section 5): 0 held · 1 a difference found (DRIFT / VIEW_DIFFERS_FROM_SOURCE / QUARANTINE / BROKEN) · 2 UNVERIFIABLE · 3 markers found · 64 usage.

Note: the marker corpus ships separately from the wheel (SPEC s.8), so an installed refuse needs EMET_CORPUS set or a source checkout; without it, the answer is UNVERIFIABLE reason=E_NO_CORPUS, never a silent pass.

Worked example: anchor, verify, let the verdict travel

The witness lane: subject, anchor, read paths, recompute, compare, markers, lattice, chain, ending in match, drift, or unverifiable.

$ printf 'hello world\n' > report.md
$ emet anchor report.md
anchored report.md sha256=a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447

$ emet verify report.md
MATCH report.md want=a948904f2f0f479b got=a948904f2f0f479b     # exit 0

$ printf 'hello world CHANGED\n' > report.md
$ emet verify report.md
DRIFT report.md want=a948904f2f0f479b got=9fc0ea6515ceadd9     # exit 1

Two things in that lane are worth naming, because they are what keep the rest of it honest. The closed lattice is structural rather than reviewed: every governed token leaves through governed(channel, token), which raises inside the core when the token is not a member of its channel's set, and TRUSTED is pinned in a forbidden set on top of that. An unsanctioned verdict is a construction error before a byte reaches stdout, not a review miss afterward. And corroborate treats a single working read path as an inability, not as agreement: with nothing to disagree with, it reports UNVERIFIABLE reason=E_NO_SECOND_READ_PATH rather than CORROBORATED.

Seal the verdict into a receipt and hand it to someone else:

emet verify report.md --json | emet receipt --from-json - > receipt.json
emet check receipt.json          # on ANY machine: RECEIPT_VALID / TAMPERED / UNVERIFIABLE

Add --recompute-from-paths to emet check to also re-hash the subject bytes on disk against the recorded digests. For every command with captured real output, the companion tools (monitor.py, organs.py), and a runnable demo, see USAGE.md and examples/.

The receipt lane: envelope, subjects, identity, canonical form, address, signature, re-derive, verdict, ending in receipt valid, receipt tampered, or receipt unverifiable.

The address in the middle of that diagram is a hash of the receipt with its own receipt_id, signature, and per-implementation witness block removed, and the optional HMAC covers that same body. Both therefore describe exactly the same bytes, and a doctored field changes the address the receipt is stored under. Reading one back never trusts the stored id; it recomputes the address and compares. Two precedence rules follow the primary lattice: a confirmed divergence outranks an inability, so a changed subject reads RECEIPT_TAMPERED rather than RECEIPT_UNVERIFIABLE, and a receipt that carries a signature with no key available to check it reads RECEIPT_UNVERIFIABLE, never valid.

DeepEval reporter (emet.reporters.deepeval)

An optional reporter turns a completed DeepEval evaluation into a portable witness receipt. It ships in the wheel as the out-of-core emet.reporters subpackage and pulls DeepEval only as an extra:

pip install emet[deepeval]
from emet.reporters.deepeval import mint_receipt
# `result` is whatever deepeval.evaluate(...) returned.
receipt, record_path, receipt_path = mint_receipt(
    result, model="gpt-4o-2024-08-06",
    config={"temperature": "0", "run": "nightly"}, out_dir="eval-out")
# then, on any isolated machine, zero shared state:
#   emet check eval-out/emet-eval-receipt.json                 -> RECEIPT_VALID
#   emet check eval-out/emet-eval-receipt.json --recompute-from-paths

It seals a canonical eval record (model, dataset digest + count over the test-case inputs, metric/judge name + version, per-case pass/score as strings, config) and mints an emet receipt that binds the record's integrity; corrupting one byte flips the verdict away from RECEIPT_VALID. The record carries no floats and the receipt's verdict_record is empty by design, so it asserts provenance and integrity, never model quality beyond the numbers the metrics already reported. DeepEval is a lazy import: mint_receipt and build_eval_record read an already-completed evaluation structurally and need no DeepEval install; only evaluate_and_mint, which runs the evaluation, imports it and raises a clear error when it is absent. The reporter stays out-of-core: it is excluded from the minimal TCB and the selftest artifact-of-record (SPEC section 10, s.14), and the byte-hash core keeps zero runtime dependencies.

Flywheel evaluation receipts

The optional emet.reporters.flywheel adapter binds Flywheel Inspect evidence, incident-simulation command results, and final process-audit packet bytes to a small metadata record. It adds no runtime dependency and does not execute an evaluation. The receipt keeps verdict_record empty: an intact report can describe a failed task, and EMET does not decide whether that report is true.

For a process-audit packet, call mint_packet_receipt(packet_bytes) and retain the returned commitment's receipt_sha256 whole-receipt hash, or the full commitment that contains it, outside the packet-local digest graph. receipt_id is useful supplementary context but does not bind the whole handoff. write_packet_artifacts(...) can persist fixed-name files and refuses to overwrite existing outputs, but it is not independent storage.

See the adapter contract and example. The review protocol exercises an intact receipt for a failed task, changed bytes and missing evidence. The Python API returns artifact bytes for the caller to store. Keep the original report private when it contains sensitive evidence; this adapter is not a redactor.

For developers

The repo ships its own delivery contract; re-check it any time with python test_forward_delivery_contract.py.

Each implementation declares the optional capabilities it does not yet claim (EMET_SKIP_CAPABILITIES), and the runner scores it only on what it does claim, exactly as CI does:

git clone https://github.com/HarperZ9/emet && cd emet
python conformance/run.py membrane.py                # Python reference: 48/48

( cd impl/rust && rustc -O emet.rs -o emet )
EMET_SKIP_CAPABILITIES=rebind,eval-receipt \
  python conformance/run.py impl/rust/emet           # Rust:    40/40

EMET_SKIP_CAPABILITIES=rebind,eval-receipt \
  python conformance/run.py impl/js/emet.js          # Node.js: 40/40

( cd impl/go && go build -o emet emet.go )
EMET_SKIP_CAPABILITIES=receipt,rebind,eval-receipt \
  python conformance/run.py impl/go/emet             # Go:      35/35 (core)

Per-implementation capability matrix

Implementation Core (35 vectors) Receipt (5, SPEC s.17) Rebind (4, SPEC s.18) Eval-receipt (4, reporter)
Python (reference) yes yes yes yes
Rust (impl/rust) yes yes (HMAC hand-composed over its own SHA-256, verified against RFC 4231) not yet not yet
Node.js (impl/js) yes yes (native crypto) not yet not yet
Go (impl/go) yes not yet ported not yet not yet

The eval-receipt vectors check an ordinary witness receipt minted by the out-of-core DeepEval reporter over an eval record; any receipt-capable implementation can re-verify them, and they are capability-tagged so a port that has not validated the profile skips them.

An unsigned receipt verifies on the content address alone; the HMAC-SHA256 signature is optional and only strengthens integrity when producer and verifier share a key channel (EMET_RECEIPT_SIGNING_KEY). The rebind cross-language port contract is docs/REBIND-SPEC.md.

What it won't do

The nine channels of emet's closed verdict lattice, one to a row, with what each channel judges and the exact tokens it may emit. The primary lattice judges an anchored path re-read now and emits MATCH, DRIFT, or UNVERIFIABLE. Coherence judges a rendered view against the source bytes and emits COHERENT, VIEW_DIFFERS_FROM_SOURCE, or UNVERIFIABLE. Corroboration judges two read paths for one file and emits CORROBORATED, QUARANTINE_READ_PATH_DIVERGENCE, or UNVERIFIABLE. Audit judges the append-only chain of records and emits INTACT or BROKEN. The receipt channel judges a portable receipt offline and emits RECEIPT_VALID, RECEIPT_TAMPERED, or RECEIPT_UNVERIFIABLE. The monitor judges one watched file as MATCH, DRIFT, or MISSING, and the baseline it read from as INTACT or CHANGED. Perception judges a path between two observations as UNCHANGED, DRIFTED, NEW, or GONE. The revert channel judges whether a clean revert path exists and emits REVERTIBLE or NOT_REVERTIBLE. No channel admits a word that asserts authority.

The set above is the whole vocabulary. Every governed verdict is emitted through governed() in emet/verdict.py, which raises on a token outside its channel, so an unsanctioned word fails at construction time rather than in review.

EMET is an advisory integrity witness: it only reports facts. It can't say TRUSTED, doesn't decide whether a model is safe, runs outside whatever it audits, and never edits, signs, or blocks anything. Those constraints are the point, not limitations: see SPEC.md section 6.

Status

v1.3.0. The spec is frozen and stable at 1.0.0. The byte-hash core, the exit-code split, the --json envelope, the marker path, and the audit chain re-derive across four languages and are checked in CI on every push. What the 1.x line asserts is exactly two things: the contract is frozen, and the reference implementations are production-grade. It deliberately does not claim re-derivability is proven: all four implementations share an author, and SPEC section 12's bar, an independent different-author implementation passing the vectors, is not yet met. For a tool whose only credential is reproduction, an inflated claim would refute itself, so the claim is scoped to exactly what CI reproduces today.

Call for an independent implementation

The highest-leverage contribution is not another language but a different-author implementation, written from SPEC.md alone (not by reading the existing code), in any language, that passes the core vectors:

EMET_SKIP_CAPABILITIES=receipt,rebind \
  python conformance/run.py ./your-emet     # expected: CONFORMANCE 35/35

Where your implementation and the spec disagree, the spec is wrong: open an issue; those divergences are the point. Both clean-room ports already did exactly this. The Node.js port surfaced that the marker occurrence count was unpinned (now pinned in SPEC section 16 and a dedicated vector), and the Go port surfaced the reason-code enum and default-JSON-encoder gaps, now pinned; see docs/spec-findings-from-go-impl.md. Claim a language in Discussions so effort isn't duplicated.

Why it matters

A model-facing view can drift from its source, a monitor can observe the wrong artifact, and a generated report can overstate what was checked. EMET is the small external witness for those seams: it re-derives the bytes and reports what matched, what drifted, and what could not be verified, without ever becoming an authority. The public value is exactly that: every verdict is a fact anyone can re-check, same bytes, same answer. It composes with its peer tools forum (accountable multi-agent orchestration) and accountable-surface (live perceive/gate/actuate surface), and stands alone just as well.

Docs

docs/INTRODUCTION.md (start here) · USAGE.md (every command, captured output) · SPEC.md (the frozen normative contract) · RATIONALE.md (why EMET is shaped this way) · conformance/ · THREAT-MODEL.md · COVERAGE.json · SECURITY.md · CONTRIBUTING.md

MPL-2.0.

What this believes

This tool is one lane of a family that holds a single belief steady across every surface: knowledge open to anyone who can attain the means; acceptance decided by external checks, never reputation; every result re-runnable; honest nulls first-class; ownership earned by comprehension; learning woven into the work. The full text lives in CREDO.md. The long form of this belief: The Unbundling.


Zentropy Labs · order out of entropy. An independent lab building evidence-first tools that leave a re-checkable artifact behind. Built by Zain Dana Harper in Seattle. The full workbench is at Project Telos.

Release files for emet 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for emet 1.3.0
File Size Uploaded
emet-1.3.0.tar.gz 54.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for emet 1.3.0
File Interpreter ABI Platform
emet-1.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 109.8 kB

Release files / emet-1.3.0.tar.gz

Download URL emet-1.3.0.tar.gz
Size 54.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b28d6763db1d8db0f376cb6f33dffa3e6e649c65d9843483dd395f71e3f36d02
BLAKE2b-256 checksum
How to use checksums
35738c5c1791a503b5ee0b90de8ee812ced550ce880d00b1a97c5888f29ceae9
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 13, 2026.

Transparency log

Release files / emet-1.3.0-py3-none-any.whl

Download URL emet-1.3.0-py3-none-any.whl
Size 55.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1a2bea4f9a7cdab07bc6b883f8487673bf985f793d125ce18a4cf86d66044a09
BLAKE2b-256 checksum
How to use checksums
53f45857b4edd47d1f26c07413ebf2874545e1bdf6b2b728e3882989e78154d1
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 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page