Metadata-Version: 2.5
Name: open-receipt
Version: 0.2.1
Summary: Native offline verification for Open Receipt protocol 0.2.1
Project-URL: Homepage, https://receiptprotocol.com/open-receipt
Project-URL: Repository, https://github.com/JasonSmall/attachreceipt
Project-URL: Issues, https://github.com/JasonSmall/attachreceipt/issues
Author: Receipt Protocol
Maintainer: Receipt Protocol
License-Expression: MIT
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: cryptography>=43
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: pytest<10,>=8; extra == 'dev'
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
Description-Content-Type: text/markdown

# Open Receipt Python verifier

This native Python, verifier-only package performs offline verification for
Open Receipt protocol 0.2.1 and its supported wire `spec_version` values `0.1`
and `0.2`. It checks canonical JSON, payload digests, Ed25519 signatures, v0.1
parent bundles, pinned v0.2 issuer metadata and history, key lifecycle state,
and issuance attestations. It does not create or sign receipts, require a
Receipt account, contact the Receipt API, or fetch trust material from the
network.

Python package candidate available in the repository. PyPI publication follows
independent review and release approval.

## Versioning

The tracked Open Receipt release is 0.2.1. Receipt wire documents continue to
use the supported `spec_version` values `0.1` and `0.2`. Protocol releases,
wire-format versions, and implementation package versions are separate release
coordinates. This unpublished Python candidate is currently versioned 0.2.1.

## Repository installation and quick start

Python 3.10 or newer is supported. From this repository, build and install the
candidate package rather than using a public package index name:

```sh
python -m pip install ./packages/open-receipt-python
```

```python
import json
from open_receipt import verify_receipt

receipt = json.loads(open("receipt.json", encoding="utf-8").read())
result = verify_receipt(receipt)
print("verified" if result.valid else result.errors)
```

The runtime dependency is `cryptography`, used only for maintained Ed25519 key
parsing and signature verification. Canonicalization and protocol evaluation
are implemented directly in Python.

## CLI

```sh
open-receipt verify ./receipt.json
cat receipt.json | open-receipt verify -
open-receipt verify --json ./receipt.json
open-receipt verify --quiet ./receipt.json
```

Input is limited to 1 MiB. Exit code `0` means valid (including valid with
warnings), `1` means invalid, and `2` means indeterminate or a malformed CLI or
operational input. The command reads only a local path or stdin and never
performs an implicit network request.

## Verdict and trust boundaries

`valid` means that the supported protocol checks completed successfully.
`valid_with_warnings` preserves non-fatal trust warnings. `invalid` is a
fail-closed protocol or cryptographic rejection. `indeterminate` means the
cryptography may be sound but the supplied offline trust material cannot
establish the issuer or historical key conclusion.

Embedded keys prove signature consistency, not issuer identity. Supply a
trusted pinned metadata snapshot, its exact canonical hash, and any required
history to establish v0.2 issuer trust. This package never discovers newer key
revocations by itself. Callers must obtain and pin trust material through a
separately reviewed path.

The CLI rejects duplicate JSON member names before verification. A mapping
passed to `verify_receipt` cannot reveal duplicates that a permissive parser has
already discarded, so callers accepting untrusted raw JSON must enforce that
boundary while parsing or use the CLI's strict parser.

## Conformance

From the repository root, run the shared TypeScript/Python corpus with:

```sh
bun run open-receipt:conformance
```

The canonical schemas live under `packages/open-receipt/schemas/`. The shared
vectors, expected verdicts, issuer keys, and metadata fixtures live under
`packages/open-receipt/conformance/`; Python does not carry a copied corpus.
