trail-evidence (Python)
Reference implementation of the Trail Evidence Record contract
(trail.evidence/1, format 0.2) in Python: seal, sign and verify
hash-chained JSON evidence records, and check payloads against registered
profiles. Standard library only (RFC 8785 canonicalisation and Ed25519
verification are implemented in the package, the profile registry ships as
package data), Python 3.9 or newer.
A Trail Evidence Record is one JSON object that describes one event a system wants to be able to prove later, chained to the previous record by a hash and optionally signed. A journal is JSON Lines, one record per line. The verifier needs nothing but the file, and a public key if signatures are to be checked.
pip install trail-evidence
trail-evidence-py verify journal.jsonl
trail-evidence-py verify journal.jsonl --pubkey <64 hex chars or file> --require-signatures
trail-evidence-py verify journal.jsonl --allow-incomplete
trail-evidence-py verify journal.jsonl --json
trail-evidence-py hash record.json
trail-evidence-py profiles
Every record gets a state: valid, invalid, unknown (its predecessor is
not in the file) or outside_scope (another format or major version), and a
profile state. The journal gets the verdict valid (exit code 0), invalid
(1) or incomplete (3: no record invalid, but one unknown or outside the
scope). --allow-incomplete accepts incomplete journals (exit code 0), for
logs known to be incomplete such as rotated ones; --require-known-profiles
counts records with an unknown profile as incomplete. Exit code 2 is a usage
or I/O error. python -m trail_evidence is the same CLI.
from trail_evidence import seal, sign, verify_stream, GENESIS_HASH, NO_POLICY
record = {
"producer": {"kind": "ml-pipeline", "id": "run-7f3a", "version": "1.4.0"},
"stream_id": "run-7f3a", "seq": "0", "event_type": "ml.run.completed",
"time": {"recorded_at": "2026-11-02T09:42:10.000Z", "source": "system"},
"actor": {"auth": "operator-token", "id": "ml-ops"},
"policy": NO_POLICY,
"payload": {"metrics": {"dice": "0.9132"}},
}
seal(record, GENESIS_HASH)
sign(record, seed_bytes) # optional
with open("journal.jsonl") as fh:
report = verify_stream(fh, public_key_bytes)
print(report.summary(), report.verdict, report.exit_code())
print([(r.index, r.state, r.profile_state) for r in report.results])
seq is a decimal string ("0" to "18446744073709551615"); seal()
also accepts an int and writes the string.
The pure Python Ed25519 code is written for clarity and test use, not for
throughput or side-channel resistance. Producers that sign at volume should
use a vetted library (for example cryptography) and keep this module for
verification in tooling and tests.
The Go reference implementation, the browser verifier, the specification
(SPEC.md), the JSON Schema and the test vectors live in the repository:
https://github.com/RainerGewalt/trail-evidence. Go, Python and the
browser verifier produce identical reports; scripts/crosscheck.sh
enforces that.
Development, from a checkout:
cd python
python3 -m unittest discover -s tests -v
python3 -m trail_evidence verify ../examples/transfer-worker.jsonl
python3 -m trail_evidence check-vectors ../testdata/vectors.json
Metadata
Release files for trail-evidence 0.2.0
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 | Actions |
|---|---|---|---|---|
| trail_evidence-0.2.0.tar.gz | 33.9 kB | With provenance | Details for trail_evidence-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| trail_evidence-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for trail_evidence-0.2.0-py3-none-any.whl |
Total release size: 62.2 kB
Release files / trail_evidence-0.2.0.tar.gz
| Download URL | trail_evidence-0.2.0.tar.gz |
|---|---|
| Size | 33.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b89789e32697010ae5c087d3af6f4e081ee030f96285c3aa01771d40135b2e58
|
|
BLAKE2b-256 checksum How to use checksums |
d64aff14fa1cd9245b04e91360ff68ea32fe4587fc62b7e552173c145db15679
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 3, 2026.
Transparency logRelease files / trail_evidence-0.2.0-py3-none-any.whl
| Download URL | trail_evidence-0.2.0-py3-none-any.whl |
|---|---|
| Size | 28.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d35294dc49b069f3dc9ebf5ee77388d8356b57f1947247e39b6e2ae6d9180b82
|
|
BLAKE2b-256 checksum How to use checksums |
aa5aa08abee75ec6dfc678f8e96edd66529fb597ec3dadca250ea4292c219bba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 3, 2026.
Transparency logSecurity for trail-evidence 0.2.0
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
Both files in this release have been uploaded with provenance metadata.
Attestation for trail_evidence-0.2.0.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 Nov 3, 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.