attest
The store dies, the receipt survives.
When a digital store shuts down or delists a title, buyers lose twice. The loud loss is access: the game, book, or film stops working, and everyone talks about that. The quiet loss is evidence: the only record that you ever paid lived in the seller's database, so the proof of purchase dies at the same moment as everything it could have proven — a refund, a dispute, a class action, a preservation project's eligibility check. You go from "customer" to "nobody in particular" the instant the server goes dark.
attest closes that second gap. It is an open standard and reference implementation for signed purchase receipts the buyer holds: the store signs a receipt once at checkout, the buyer keeps the file like a paper receipt, and anyone can verify it offline, forever — even after the store is gone. It covers any digital purchase: games, e-books, film and TV, music, software, courses. No account, no wallet, no blockchain, no server that has to stay alive for the proof to still work.
Try it in your browser: https://svm-98.github.io/attest/ — drop a .attest
bundle (or the built-in sample) and watch it verify entirely client-side; the
page's CSP forbids it from talking to any other host.
The problem
A digital "purchase" today is a revocable license living inside one company's platform, not a thing you hold. When the platform shuts down, delists a title, or changes terms, the buyer's library goes with it — regardless of medium: Robot Cache bricked already-downloaded games at its May 2026 shutdown; Funimation wiped customers' digital anime libraries in 2024; Kindle removed book export in February 2025; Sony ends PlayStation disc production for new games in January 2028, pushing more purchases into pure platform dependency. None of this is hypothetical or gaming-specific — it is what "buy" already means for every kind of digital media.
Policy is waking up to half of the problem. California's AB 2426 and Maryland's HB 208 require disclosure that a digital "purchase" is a license; the EU's Digital Content Directive (2019/770) already grants consumers remedies when digital content fails to conform; and in June 2026 the European Commission — answering the 1.29-million-signature Stop Killing Games initiative — committed to an industry code of conduct on video game end-of-life by the end of 2026. All of those efforts are about access and disclosure. None of them puts proof of purchase on the table — yet a right without evidence is unenforceable. Once the seller's records are the only proof and the seller is gone, there is nothing left to base a remedy on.
What's missing is not more disclosure law — it's an open technical standard for a purchase record the buyer actually holds, independent of whether the seller survives. That evidence layer is what attest is. Deliberately, it is only that: attest does not keep content alive (see below), it makes sure that whatever rights a buyer has can still be exercised after the store is gone.
How it works, for humans
At checkout, the store signs a receipt and hands the buyer an .attest bundle —
a small file the buyer keeps anywhere: disk, cloud, USB, wherever. There is no
account to keep alive and nothing to sync. Later, anyone with a verifier — a
friend, a marketplace, the buyer themself — can check that bundle's signature
offline against the issuer's published key material and confirm it's a genuine,
unrevoked receipt. If the buyer needs to prove the receipt is specifically
theirs (not just a copy that has floated around), they can do so by disclosing
a salt or answering a key challenge, without exposing their identity to the
verifier. Nothing in this loop requires a server: there is no central attest
authority, no registry that must exist, and no phone-home — a verifier needs only
the receipt bytes, the issuer's key material, and, optionally, a revocation feed.
What it is / is not
attest is a normative specification for a signed receipt envelope, a restricted JSON canonicalization profile, a pinned Ed25519 signing/verification ruleset, issuer key/artifact manifests with rotation and compromise handling, a layered offline verification algorithm, revocation-by-class semantics, and buyer-binding proof — plus a Python reference implementation and an independent TypeScript verifier.
It is not a DRM-stripping tool, a content host, an index of content, a
marketplace, a resale/transfer protocol (not in v0.1 — see the reserved
transferable field), a blockchain or NFT product, or a payment instrument. A
receipt is evidence of a license grant, not the artifact itself and not the
transaction that paid for it.
None of this bypasses an unwilling seller: a receipt is issuer-signed, and attest cannot conjure a valid one out of a store that refuses to sign. For incumbents who won't adopt voluntarily, the lever is regulation and market pressure, not forgery.
Status
Spec v0.1 is complete and v0.2 is specified and implemented on main, with two
independent implementations — a Python reference implementation and a TypeScript
verifier — that agree on all 97 conformance vector leaves across 36 groups: 51 of
them the v0.1 corpus, the rest exercising v0.2's hybrid signature profile,
transparency/anchoring behaviour, the upgrade-policy hardening (mixed-keyset
prohibition, artifact-manifest currency, anchor profile v2, logged revocation
deadlines), and Stage 3 issuer-mediated transfer. (A v0.1-only verifier is required
to reject v0.2 envelopes, so it is measured against the 51-leaf subset.) There is also an
end-to-end demo that deletes a store's entire infrastructure mid-lifecycle and
proves the receipt still verifies.
The published packages are 0.3.0, which already ships v0.2 Stages 1 and 2
(hybrid signatures; transparency and anchoring). Stage 3 — issuer-mediated
transfer, this document's own §17 — is the remaining piece 0.4.0 ships.
Three pieces of assurance work go beyond what a test suite can show. They are being finished on branches, and are linked here rather than left invisible:
- Formal verification. A Tamarin model of the wire protocol:
machine-checked theorems that acceptance implies an issuer signature, that key
rotation cannot be hijacked, and that revocation is sound and effective — plus
attack exhibits proved reachable rather than argued in prose, plus negative
controls that must falsify. Each theorem states its own scope in the theory
file; nothing is claimed more broadly there than the prover checked. In
progress on
feature/p1.3-formal-verification. - Threat model.
67 attacks catalogued across the whole receipt lifecycle, each either mitigated
or recorded as out of scope with a reason, a traceability matrix, and the
protocol gaps the exercise found left tracked in the open instead of quietly
fixed. On
pillar-1. - Privacy considerations.
Every field classified by what it reveals to which observer, twenty testable
privacy claims, and a GDPR annex covering what a receipt deliberately does not
record. On
pillar-1. - Transfer economics
(non-normative). The market and legal context behind Stage 3's transfer
profile — resale velocity, the issuer-royalty incentive, and the CJEU case law
(UsedSoft, Tom Kabinet) that makes transfer issuer-mediated rather than a
general resale right. On
pillar-1.
Quickstart
Install the reference implementation from PyPI (the distribution is named
attest-receipts; the import package and the CLI are both attest):
pip install attest-receipts
attest --help
The TypeScript verifier is on npm as
attest-verifier:
npm install attest-verifier
Or work from a checkout of this repo:
uv venv --python 3.12 .venv && uv pip install --python .venv -e '.[dev]'
# or: pip install -e .
.venv/bin/attest --help
.venv/bin/python demo/store_dies.py
.venv/bin/pytest --cov=attest --cov-report=term-missing
and a TypeScript verifier quickstart:
cd verifiers/ts && npm install && npm test
See demo/README.md for what each step of the demo proves, and docs/spec/attest-v0.1.md plus its companion JSON Schema for the normative specification. docs/spec/vectors/ holds the conformance corpus every implementation is checked against.
docs/spec/attest-v0.2.md is an additive delta
specification defining the v0.2 hybrid Ed25519+ML-DSA-65 signature profile
(post-quantum-resistant receipts, attest_version: "0.2"); v0.1 receipts
remain valid and verifiable forever. That profile was Stage 1; Stage 2 — issuer
key transparency and timestamp anchoring, where a log corroborates a receipt's
existence without ever being able to make an unsigned receipt look authentic —
is specified in the same document. Stage 3 — issuer-mediated transfer, giving
license.transferable its first real meaning, layered on top of the Stage 2 log
— is specified there too (§17); business economics around resale are
deliberately out of protocol and live in the non-normative
transfer-economics annex.
docs/spec/attest-versioning.md is the
normative upgrade policy governing both specifications above: the additive
pattern new extensions must follow, the eternal-verifiability guarantee, the
three-state algorithm lifecycle (active / deprecated / unsafe), the
amendment procedure, and the signature-suite, payload-field, revocation-class,
log-entry-type, and transfer-type registries.
docs/spec/attest-threat-model.md is the maintained threat model behind the two specifications above — a living normative companion that analyzes their mechanisms rather than imposing requirements of its own — and docs/spec/attest-privacy.md is its privacy-considerations sibling.
The core protocol properties are machine-checked in Tamarin: formal/ holds the model, the property↔lemma↔spec map, and the honest scope of what is and is not proved, gated in CI by a statement-pinning checker.
Roadmap / north star
Non-normative, and deliberately undated — these are directions, not commitments:
- Authorized preservation escrow. A path where a rights holder deposits a build or copy with a preservation institution and licenses buyers to retrieve it once official distribution ends — with the receipt as the eligibility check. Strictly rights-holder-authorized: attest will never host, index, or distribute content on its own.
- Evidence capture for non-cooperating stores. A research track into TLS-session-proof techniques (the zkTLS/TLSNotary class) that could let a buyer capture their own evidence of a purchase from a store that never signs anything, at weaker-than-issuer-signed trust. Legal review is required before any of this is built.
- Registry / replication layer. An optional layer for replicating verification material, with optional Merkle-root transparency anchoring — separate from the shipped §17.5 chain-of-title audit surface, and still strictly optional.
Licensing, contributing, contact
License. Code is licensed Apache-2.0; the specification and other
documentation are licensed CC BY 4.0 — reuse and derivatives of
the spec must credit the original author, since attribution is a condition of
that license, not a courtesy. NOTICE and AUTHORS carry
the required attribution.
Naming. The name attest identifies this project and implementations that actually conform to it; forks are welcome to use the technology but not the name for a divergent derivative. This paragraph is a naming norm, not a trademark registration — real trademark enforcement would require actually registering the mark, which has not happened.
Contributing. See CONTRIBUTING.md. Implementation pull
requests must pass all 97 conformance vector leaves and keep both the Python and
TypeScript suites green.
Contact. Use GitHub Issues for technical bugs, GitHub Discussions for
everything else, or email SVM-98@proton.me.
Security issues follow a different path — see SECURITY.md, and
do not open a public issue for a vulnerability.
Skeptical about any of this? docs/faq.md answers the first questions a reasonable person asks.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file attest_receipts-0.4.0.tar.gz.
File metadata
- Download URL: attest_receipts-0.4.0.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95959bf8facdbc0babba2764c3f294dd66862203458dec36642c35264a3971bb
|
|
| MD5 |
9b08b6eed2092369889c6670ad21b66b
|
|
| BLAKE2b-256 |
f149645003a018f5cc80fdeff45d73e6f84e164df5f693e2e124b87a0ffc9213
|
Provenance
The following attestation bundles were made for attest_receipts-0.4.0.tar.gz:
Publisher:
release.yml on SVM-98/attest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
attest_receipts-0.4.0.tar.gz -
Subject digest:
95959bf8facdbc0babba2764c3f294dd66862203458dec36642c35264a3971bb - Sigstore transparency entry: 2226582880
- Sigstore integration time:
-
Permalink:
SVM-98/attest@131ef0155674885878e7d133c9d6721ab6bca49b -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/SVM-98
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@131ef0155674885878e7d133c9d6721ab6bca49b -
Trigger Event:
push
-
Statement type:
File details
Details for the file attest_receipts-0.4.0-py3-none-any.whl.
File metadata
- Download URL: attest_receipts-0.4.0-py3-none-any.whl
- Upload date:
- Size: 133.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a8d635925854711707d40b456249d6348145e341ac860fe51f8c7f1e1e0d402
|
|
| MD5 |
7da9e2ecdedc9faa08c0da7c2eaf5f86
|
|
| BLAKE2b-256 |
33ed51f95f0728e19391f657b33058e4a3ba75f27bd2ea38a696fff6bdaed8ff
|
Provenance
The following attestation bundles were made for attest_receipts-0.4.0-py3-none-any.whl:
Publisher:
release.yml on SVM-98/attest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
attest_receipts-0.4.0-py3-none-any.whl -
Subject digest:
0a8d635925854711707d40b456249d6348145e341ac860fe51f8c7f1e1e0d402 - Sigstore transparency entry: 2226583377
- Sigstore integration time:
-
Permalink:
SVM-98/attest@131ef0155674885878e7d133c9d6721ab6bca49b -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/SVM-98
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@131ef0155674885878e7d133c9d6721ab6bca49b -
Trigger Event:
push
-
Statement type: