Zain Dana HarperEMET · external witness

If an agent touched it, you should be able to check what it did.

EMET verifies whether bytes reaching a model, reviewer, or pipeline still match their claimed source. It anchors and compares content, neutralizes embedded authority, audits drift, and mints portable closed-verdict receipts across four implementations.

A witness isn’t a judge. All it does is say what it compared. Whether to trust the result is yours, not the tool’s.

emet, Hebrew for truth · 1.3.0 on PyPI · 48-vector reference suite · four implementations with declared capability coverage
Plate 01 A structure dissolving into sorted runs: what drift looks like before the witness names it.

It works out the fingerprint itself.

An AI model is always handling files: one it edits, a prompt it’s given, a view it shows you and calls a true copy of the original. EMET opens those files directly and works out the fingerprint again from scratch, using SHA-256 (a standard, widely trusted recipe for turning any file into one short, unique fingerprint). Then it compares that to the fingerprint it saved before. The answer comes only from running the same recipe over the same file, never from the system telling you it’s fine. It stands outside the thing it’s checking.

Knowing where a file came from is one thing. It still doesn’t tell you whether the copy the model is looking at right now is unchanged. That’s the gap this closes.

Three answers. None of them trusted.

There are exactly three answers it can give (MATCH, DRIFT, UNVERIFIABLE), and there will only ever be three. That’s not a promise written in a comment somewhere; the code is shaped so a fourth answer simply has nowhere to come from. It can never tell you to trust something, because it was never given any trust to hand out.

MATCH the file’s fingerprint still matches the one saved earlier · it means nothing has moved, not that the file is good
DRIFT the file, or the view shown to you, no longer matches its saved fingerprint · it just reports that something changed, and doesn’t decide whose fault that is
UNVERIFIABLE it couldn’t read the file, or had no saved fingerprint to compare against · so it says “I can’t tell” out loud, with a clear reason. It never guesses, and never just crashes
If there’s no DRIFT, the answer is either MATCH or UNVERIFIABLE. There is no path through the code that turns “no drift” into “trust it.”

Don’t take the answer on my word. Watch it flip.

A single character is enough to change everything. Check a file, add one character to it, then ask again. The same core rules have implementations in Python, Rust, Node.js, and Go, with capability-specific conformance coverage stated below.

Live the verdict depends on the bytes, nothing else
$ python membrane.py verify demo_sample.txt
MATCH  demo_sample.txt   want=d02206abca2a…  got=d02206abca2a…   (exit 0)

# append one byte to the file, ask the same question
$ python membrane.py verify demo_sample.txt
DRIFT  demo_sample.txt   want=d02206abca2a…  got=b072d611645e…   (exit 1)

# one spec, four separate language implementations, CI on every push
membrane.py        →  CONFORMANCE 48/48 vectors pass
impl/rust/emet     →  CONFORMANCE 40/40 supported vectors pass
impl/js/emet.js    →  CONFORMANCE 40/40 supported vectors pass
impl/go/emet       →  CONFORMANCE 35/35 core vectors pass

Change a single character in the file and the answer drops from MATCH to DRIFT. It reads the file itself, not anyone who promises it’s fine.

The shared suite contains 48 vectors: 35 core, 5 receipt, 4 rebind, and 4 evaluation-receipt cases. Python covers all 48; Rust and Node cover 40 with rebind and evaluation-receipt skipped by declared capability; Go covers the 35 core vectors. Honest limit: I wrote all four versions myself, so this demonstrates same-author cross-language agreement, not independent reproduction. See a sample proof-surface report →

Limitations kept visible.

The conformance implementations are same author, so they prove that the rules are clear enough to implement in several languages. They do not prove independent authorship, semantic quality, model quality, or third-party adoption.

Its closed verdict records byte agreement, drift, or inability to verify. A human or downstream process still decides what that result means.

PyPI: emet  ·  Email: zaindharper@gmail.com  ·  License: MPL-2.0  ·  ← the map  ·  the index

EMET v1.3.0 release evidence.

The current public release is v1.3.0 on GitHub and emet 1.3.0 on PyPI. The GitHub release is public, not draft, and not prerelease; no release assets are attached there. PyPI serves the wheel and source archive.

ReleaseGitHub tag v1.3.0 uses annotated tag object 6fa3985cb02dfc84e77f7e3c5872bc988304b18d and peels to source commit b37da003951866ece403fb08fe3d028d00c39f4f
PyPIwheel SHA-256 1a2bea4f9a7cdab07bc6b883f8487673bf985f793d125ce18a4cf86d66044a09; source archive SHA-256 b28d6763db1d8db0f376cb6f33dffa3e6e649c65d9843483dd395f71e3f36d02
ProtocolPinned Flywheel review protocol, a development compatibility exercise that requires source checkouts
Python48/48 conformance cases in the current reference path
Rust40/40 conformance cases
Node40/40 conformance cases
Go35/35 core conformance cases

These same-author implementations demonstrate rule clarity, not independent authorship, semantic quality, regulatory assessment, model assessment, policy endorsement, or third-party adoption. The machine-readable maturity record is security-tools.json.