trace-verify 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,85 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ validate:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
18
+ with:
19
+ python-version: "3.12"
20
+
21
+ - name: Install dependencies
22
+ run: pip install jsonschema==4.26.0 hatchling
23
+
24
+ - name: Install trace-verify package (editable)
25
+ run: pip install -e .
26
+
27
+ - name: Smoke-test trace-verify CLI
28
+ run: |
29
+ set -euo pipefail
30
+ trace-verify --version
31
+ trace-verify \
32
+ --claim samples/example-trust-record.json \
33
+ --proof samples/inclusion-proof.json \
34
+ --entry registry/2026/06/12.ndjson
35
+ trace-verify \
36
+ --claim samples/example-trust-record.json \
37
+ --proof samples/inclusion-proof.json \
38
+ --entry registry/2026/06/12.ndjson \
39
+ --json | python -c "import json,sys; r=json.load(sys.stdin); assert r['verified'], r"
40
+
41
+ - name: Determine base SHA for append-only check
42
+ id: base
43
+ run: |
44
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
45
+ echo "sha=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT"
46
+ elif [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then
47
+ echo "sha=" >> "$GITHUB_OUTPUT"
48
+ else
49
+ echo "sha=${{ github.event.before }}" >> "$GITHUB_OUTPUT"
50
+ fi
51
+
52
+ - name: Check registry is append-only
53
+ if: steps.base.outputs.sha != ''
54
+ run: python tools/check_append_only.py "${{ steps.base.outputs.sha }}"
55
+
56
+ - name: Validate registry entries against schema
57
+ run: python tools/validate_registry.py
58
+
59
+ - name: Run tool tests
60
+ run: python -m unittest discover -s tests -v
61
+
62
+ - name: Round-trip the sample anchor
63
+ run: |
64
+ set -euo pipefail
65
+ # Re-anchor the committed sample claim and check the recomputed
66
+ # Merkle root matches the committed registry entry.
67
+ recomputed=$(python tools/anchor.py samples/example-trust-record.json \
68
+ --producer ci --proof-dir "$(mktemp -d)" \
69
+ | python -c "import json,sys; print(json.load(sys.stdin)['merkle_root'])")
70
+ committed=$(python -c "import json; print(json.loads(open('registry/2026/06/12.ndjson').readline())['merkle_root'])")
71
+ echo "recomputed: $recomputed"
72
+ echo "committed: $committed"
73
+ test "$recomputed" = "$committed"
74
+ # Verify the committed inclusion proof against the committed entry.
75
+ python tools/verify_inclusion.py \
76
+ --claim samples/example-trust-record.json \
77
+ --proof samples/inclusion-proof.json \
78
+ --entry registry/2026/06/12.ndjson
79
+
80
+ - name: Check for required files
81
+ run: |
82
+ for f in LICENSE README.md CONTRIBUTING.md CODE_OF_CONDUCT.md SECURITY.md; do
83
+ [ -f "$f" ] || { echo "Missing required file: $f"; exit 1; }
84
+ done
85
+ echo "All required community health files present"
@@ -0,0 +1,47 @@
1
+ name: Publish trace-verify to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ dry_run:
9
+ description: "Build and attest without publishing to PyPI"
10
+ required: false
11
+ type: boolean
12
+ default: true
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ environment: pypi
21
+ permissions:
22
+ contents: read
23
+ id-token: write
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
28
+ with:
29
+ python-version: "3.12"
30
+
31
+ - name: Install build tools
32
+ run: pip install build
33
+
34
+ - name: Build wheel and sdist
35
+ run: python -m build
36
+
37
+ - name: Validate artifacts
38
+ run: |
39
+ pip install twine
40
+ twine check dist/*
41
+ ls -lh dist/
42
+
43
+ - name: Publish to PyPI
44
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
45
+ uses: pypa/gh-action-pypi-publish@release/v1
46
+ with:
47
+ skip-existing: true
@@ -0,0 +1 @@
1
+ __pycache__/
@@ -0,0 +1,17 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Positive behavior includes: using welcoming and inclusive language, being respectful of differing viewpoints, gracefully accepting constructive criticism, and focusing on what is best for the community.
10
+
11
+ Unacceptable behavior includes: the use of sexualized language or imagery, trolling, insulting or derogatory comments, personal or political attacks, public or private harassment, and publishing others' private information without permission.
12
+
13
+ ## Enforcement
14
+
15
+ Instances of abusive or unacceptable behavior may be reported to the project team via [GitHub Security Advisories](https://github.com/agentrust-io/trace-registry/security/advisories/new).
16
+
17
+ Adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,18 @@
1
+ # Contributing
2
+
3
+ Thank you for your interest in contributing to the TRACE Registry.
4
+
5
+ ## How to Contribute
6
+
7
+ 1. Fork the repository
8
+ 2. Create a feature branch
9
+ 3. Commit your changes using [Conventional Commits](https://www.conventionalcommits.org)
10
+ 4. Open a pull request against `main`
11
+
12
+ ## Reporting Security Issues
13
+
14
+ Use [GitHub Security Advisories](https://github.com/agentrust-io/trace-registry/security/advisories/new) rather than opening a public issue.
15
+
16
+ ## Code of Conduct
17
+
18
+ See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
@@ -0,0 +1,6 @@
1
+ Creative Commons Attribution 4.0 International (CC BY 4.0)
2
+
3
+ Copyright 2026 AgentTrust Contributors
4
+
5
+ This work is licensed under the Creative Commons Attribution 4.0 International License.
6
+ To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: trace-verify
3
+ Version: 0.1.0
4
+ Summary: Verify TRACE claim inclusion proofs against the public registry
5
+ Project-URL: Homepage, https://github.com/agentrust-io/trace-registry
6
+ Project-URL: Documentation, https://github.com/agentrust-io/trace-registry/blob/main/docs/anchor-format.md
7
+ Project-URL: Bug Tracker, https://github.com/agentrust-io/trace-registry/issues
8
+ Project-URL: Changelog, https://github.com/agentrust-io/trace-registry/blob/main/CHANGELOG.md
9
+ License: CC-BY-4.0
10
+ License-File: LICENSE
11
+ Keywords: ai-governance,audit,inclusion-proof,merkle,trace
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Security :: Cryptography
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+
26
+ [![License: CC BY 4.0](https://img.shields.io/badge/License-CC_BY_4.0-lightgrey.svg)](LICENSE)
27
+ [![TRACE Spec](https://img.shields.io/badge/TRACE-Spec_v0.1-0ea5e9)](https://github.com/agentrust-io/trace-spec)
28
+ [![Discord](https://dcbadge.limes.pink/api/server/9JWNpH7E?style=flat)](https://discord.gg/9JWNpH7E)
29
+
30
+ # TRACE Registry
31
+
32
+ The public accountability layer for TRACE claim anchors. Each entry records the
33
+ Merkle root of a batch of signed TRACE Trust Records, committed to this
34
+ repository as an append-only record. Git's commit history is the
35
+ tamper-evidence layer: any rewrite of a published entry diverges the commit
36
+ hashes that auditors and mirrors have already observed.
37
+
38
+ ## Current Registry State
39
+
40
+ The registry currently contains one development entry (registry/2026/06/12.ndjson).
41
+ This is a software-only example anchor with advisory enforcement and a zeroed
42
+ measurement, committed as a launch-day example. It does not represent a production
43
+ Trust Record. The first production entries will be added after Confidential Computing
44
+ Summit launch on June 23, 2026.
45
+
46
+ The anchor construction (canonical claim bytes, leaf hashing, RFC 6962 Merkle
47
+ tree, inclusion proofs) is specified in
48
+ [docs/anchor-format.md](docs/anchor-format.md). A third party can implement a
49
+ verifier from that document alone; the reference tools in [tools/](tools/) are
50
+ one implementation.
51
+
52
+ > **Status.** The format, reference tooling, schema validation, and a first
53
+ > real entry ([registry/2026/06/12.ndjson](registry/2026/06/12.ndjson)) are
54
+ > live. Anchoring is currently manual and low volume; a continuous anchoring
55
+ > cadence and a packaged `trace-verify` CLI on PyPI are planned but not yet
56
+ > operational.
57
+
58
+ ## Why this exists
59
+
60
+ Anyone holding a TRACE trust record and its inclusion proof can verify that the
61
+ record was anchored in this registry without trusting the operator who issued
62
+ it, using only this public git history and the verifier below. No single
63
+ operator controls the audit trail.
64
+
65
+ ## Registry Format
66
+
67
+ Each daily file in `registry/YYYY/MM/` is newline-delimited JSON, one anchor
68
+ entry per line, validated by CI against
69
+ [schema/registry-entry.schema.json](schema/registry-entry.schema.json):
70
+
71
+ ```json
72
+ {"ts": "2026-06-12T18:09:41Z", "merkle_root": "sha256:9279...bada", "leaf_count": 1, "producer": "cmcp-gateway/0.1.0", "batch_id": "2026-06-12-001"}
73
+ ```
74
+
75
+ Entries are append-only. See [docs/anchor-format.md](docs/anchor-format.md)
76
+ for field semantics.
77
+
78
+ ## Verifying a claim
79
+
80
+ You need three things: your signed claim (Trust Record), the inclusion proof
81
+ your producer gave you, and the registry entry for the batch. Then:
82
+
83
+ ```bash
84
+ git clone https://github.com/agentrust-io/trace-registry.git
85
+ cd trace-registry
86
+ python tools/verify_inclusion.py \
87
+ --claim samples/example-trust-record.json \
88
+ --proof samples/inclusion-proof.json \
89
+ --entry registry/2026/06/12.ndjson
90
+ # OK: claim is included in batch '2026-06-12-001' (root sha256:9279..., ts 2026-06-12T18:09:41Z)
91
+ ```
92
+
93
+ Exit code 0 means the claim is proven included; 1 means it is not. The
94
+ verifier is a single standard-library Python file, so you can audit it (or
95
+ reimplement it from the spec) rather than trust it. The `samples/` files above
96
+ are a real anchored example you can use to exercise the tooling.
97
+
98
+ Inclusion verification proves the signed claim bytes were anchored at the
99
+ entry's timestamp. Validating the claim's signature against the producer key
100
+ is a separate TRACE step.
101
+
102
+ ## Anchoring claims
103
+
104
+ Producers batch signed claims and anchor them with:
105
+
106
+ ```bash
107
+ python tools/anchor.py claim1.json claim2.json \
108
+ --producer my-gateway/1.0 --proof-dir proofs/ \
109
+ >> registry/2026/06/12.ndjson
110
+ ```
111
+
112
+ This emits the registry entry line and writes one inclusion proof per claim to
113
+ hand back to claim holders.
114
+
115
+ ## Canonical Registry
116
+
117
+ This repository exists for independence: TRACE claim anchors can be checked
118
+ without trusting any single operator's infrastructure, and the git history is
119
+ auditable by anyone.
120
+
121
+ ## Community
122
+
123
+ Questions, feedback, integration help: [Discord](https://discord.gg/9JWNpH7E).
124
+
125
+ ## License
126
+
127
+ Creative Commons Attribution 4.0 International (CC BY 4.0). See [LICENSE](LICENSE).
@@ -0,0 +1,102 @@
1
+ [![License: CC BY 4.0](https://img.shields.io/badge/License-CC_BY_4.0-lightgrey.svg)](LICENSE)
2
+ [![TRACE Spec](https://img.shields.io/badge/TRACE-Spec_v0.1-0ea5e9)](https://github.com/agentrust-io/trace-spec)
3
+ [![Discord](https://dcbadge.limes.pink/api/server/9JWNpH7E?style=flat)](https://discord.gg/9JWNpH7E)
4
+
5
+ # TRACE Registry
6
+
7
+ The public accountability layer for TRACE claim anchors. Each entry records the
8
+ Merkle root of a batch of signed TRACE Trust Records, committed to this
9
+ repository as an append-only record. Git's commit history is the
10
+ tamper-evidence layer: any rewrite of a published entry diverges the commit
11
+ hashes that auditors and mirrors have already observed.
12
+
13
+ ## Current Registry State
14
+
15
+ The registry currently contains one development entry (registry/2026/06/12.ndjson).
16
+ This is a software-only example anchor with advisory enforcement and a zeroed
17
+ measurement, committed as a launch-day example. It does not represent a production
18
+ Trust Record. The first production entries will be added after Confidential Computing
19
+ Summit launch on June 23, 2026.
20
+
21
+ The anchor construction (canonical claim bytes, leaf hashing, RFC 6962 Merkle
22
+ tree, inclusion proofs) is specified in
23
+ [docs/anchor-format.md](docs/anchor-format.md). A third party can implement a
24
+ verifier from that document alone; the reference tools in [tools/](tools/) are
25
+ one implementation.
26
+
27
+ > **Status.** The format, reference tooling, schema validation, and a first
28
+ > real entry ([registry/2026/06/12.ndjson](registry/2026/06/12.ndjson)) are
29
+ > live. Anchoring is currently manual and low volume; a continuous anchoring
30
+ > cadence and a packaged `trace-verify` CLI on PyPI are planned but not yet
31
+ > operational.
32
+
33
+ ## Why this exists
34
+
35
+ Anyone holding a TRACE trust record and its inclusion proof can verify that the
36
+ record was anchored in this registry without trusting the operator who issued
37
+ it, using only this public git history and the verifier below. No single
38
+ operator controls the audit trail.
39
+
40
+ ## Registry Format
41
+
42
+ Each daily file in `registry/YYYY/MM/` is newline-delimited JSON, one anchor
43
+ entry per line, validated by CI against
44
+ [schema/registry-entry.schema.json](schema/registry-entry.schema.json):
45
+
46
+ ```json
47
+ {"ts": "2026-06-12T18:09:41Z", "merkle_root": "sha256:9279...bada", "leaf_count": 1, "producer": "cmcp-gateway/0.1.0", "batch_id": "2026-06-12-001"}
48
+ ```
49
+
50
+ Entries are append-only. See [docs/anchor-format.md](docs/anchor-format.md)
51
+ for field semantics.
52
+
53
+ ## Verifying a claim
54
+
55
+ You need three things: your signed claim (Trust Record), the inclusion proof
56
+ your producer gave you, and the registry entry for the batch. Then:
57
+
58
+ ```bash
59
+ git clone https://github.com/agentrust-io/trace-registry.git
60
+ cd trace-registry
61
+ python tools/verify_inclusion.py \
62
+ --claim samples/example-trust-record.json \
63
+ --proof samples/inclusion-proof.json \
64
+ --entry registry/2026/06/12.ndjson
65
+ # OK: claim is included in batch '2026-06-12-001' (root sha256:9279..., ts 2026-06-12T18:09:41Z)
66
+ ```
67
+
68
+ Exit code 0 means the claim is proven included; 1 means it is not. The
69
+ verifier is a single standard-library Python file, so you can audit it (or
70
+ reimplement it from the spec) rather than trust it. The `samples/` files above
71
+ are a real anchored example you can use to exercise the tooling.
72
+
73
+ Inclusion verification proves the signed claim bytes were anchored at the
74
+ entry's timestamp. Validating the claim's signature against the producer key
75
+ is a separate TRACE step.
76
+
77
+ ## Anchoring claims
78
+
79
+ Producers batch signed claims and anchor them with:
80
+
81
+ ```bash
82
+ python tools/anchor.py claim1.json claim2.json \
83
+ --producer my-gateway/1.0 --proof-dir proofs/ \
84
+ >> registry/2026/06/12.ndjson
85
+ ```
86
+
87
+ This emits the registry entry line and writes one inclusion proof per claim to
88
+ hand back to claim holders.
89
+
90
+ ## Canonical Registry
91
+
92
+ This repository exists for independence: TRACE claim anchors can be checked
93
+ without trusting any single operator's infrastructure, and the git history is
94
+ auditable by anyone.
95
+
96
+ ## Community
97
+
98
+ Questions, feedback, integration help: [Discord](https://discord.gg/9JWNpH7E).
99
+
100
+ ## License
101
+
102
+ Creative Commons Attribution 4.0 International (CC BY 4.0). See [LICENSE](LICENSE).
@@ -0,0 +1,7 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ Please do not report security vulnerabilities through public GitHub issues.
6
+
7
+ Use [GitHub Security Advisories](https://github.com/agentrust-io/trace-registry/security/advisories/new) to report vulnerabilities privately. We respond within 72 hours.
@@ -0,0 +1,147 @@
1
+ # TRACE Registry Anchor Format v1
2
+
3
+ This document is the normative specification for how TRACE Trust Records (signed
4
+ claims) are anchored into this registry and how a third party verifies, without
5
+ trusting the registry operator, that a given claim was included in an anchor.
6
+
7
+ The construction follows [RFC 6962](https://www.rfc-editor.org/rfc/rfc6962)
8
+ (Certificate Transparency) Merkle trees. A conforming verifier can be written
9
+ from this document alone; the reference tools in [`tools/`](../tools/) are one
10
+ implementation, not the definition.
11
+
12
+ ## 1. Canonical claim bytes
13
+
14
+ The unit of anchoring is the COMPLETE signed claim object, signature included.
15
+ Anchoring binds the signed artifact, not a pre-signature payload: if either the
16
+ claim body or its signature changes, the anchor no longer matches.
17
+
18
+ `canonical_claim_bytes` is the canonical JSON serialization of the claim object:
19
+
20
+ - Object keys sorted lexicographically (by Unicode code point), recursively.
21
+ - Separators `","` and `":"` with no whitespace.
22
+ - Non-ASCII characters escaped (`ensure_ascii`); output encoded as ASCII bytes.
23
+ - No trailing newline.
24
+
25
+ In Python this is exactly:
26
+
27
+ ```python
28
+ json.dumps(claim, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("ascii")
29
+ ```
30
+
31
+ Claims MUST be JSON objects. TRACE Trust Records contain only strings,
32
+ integers, booleans, nulls, arrays, and objects; claims containing non-integer
33
+ numbers are outside this profile because cross-language float serialization is
34
+ not canonical.
35
+
36
+ ## 2. Leaf hash
37
+
38
+ ```
39
+ leaf = SHA-256(0x00 || canonical_claim_bytes)
40
+ ```
41
+
42
+ The `0x00` domain-separation prefix is the RFC 6962 leaf prefix. It prevents an
43
+ interior node from being presented as a leaf (second-preimage attack).
44
+
45
+ ## 3. Merkle tree
46
+
47
+ The tree over the ordered list of leaves is the RFC 6962 Merkle Tree Hash:
48
+
49
+ - A tree of one leaf has root equal to that leaf hash.
50
+ - Interior nodes: `node = SHA-256(0x01 || left || right)` where `left` and
51
+ `right` are the 32-byte child hashes and `0x01` is the interior prefix.
52
+ - Construction proceeds level by level over the ordered leaves: adjacent pairs
53
+ are hashed together; when a level has an odd number of nodes, the final node
54
+ is promoted unchanged to the next level (it is NOT duplicated). This yields
55
+ the same tree as the RFC 6962 recursive split at the largest power of two.
56
+ - The empty batch (zero leaves) is invalid and MUST be rejected. This registry
57
+ never anchors an empty tree.
58
+
59
+ The root is published hex-encoded, lowercase, prefixed with the algorithm:
60
+
61
+ ```
62
+ sha256:<64 lowercase hex characters>
63
+ ```
64
+
65
+ ## 4. Registry entry format
66
+
67
+ Anchors are recorded in newline-delimited JSON files at
68
+ `registry/YYYY/MM/DD.ndjson` (UTC date of anchoring). Each line is one JSON
69
+ object with exactly these fields:
70
+
71
+ | field | type | meaning |
72
+ |---------------|---------|---------------------------------------------------------------|
73
+ | `ts` | string | Anchoring time, ISO-8601 UTC with `Z` suffix |
74
+ | `merkle_root` | string | `sha256:<hex>` root of the batch tree (section 3) |
75
+ | `leaf_count` | integer | Number of leaves in the batch, >= 1 |
76
+ | `producer` | string | Identifier of the party that produced and submitted the batch |
77
+ | `batch_id` | string | Producer-scoped unique identifier for the batch |
78
+
79
+ Example:
80
+
81
+ ```json
82
+ {"ts": "2026-06-12T18:30:00Z", "merkle_root": "sha256:9c4f...", "leaf_count": 1, "producer": "cmcp-gateway/0.1.0", "batch_id": "2026-06-12-001"}
83
+ ```
84
+
85
+ Entries are append-only: lines are only ever added to the end of a day file,
86
+ and existing files are never rewritten. Git history is the tamper-evidence
87
+ layer; any rewrite of a published entry diverges the commit hashes that
88
+ auditors and mirrors have already observed. The machine-readable schema is
89
+ [`schema/registry-entry.schema.json`](../schema/registry-entry.schema.json)
90
+ and is enforced by CI on every line of every `registry/**/*.ndjson` file.
91
+
92
+ ## 5. Inclusion proof
93
+
94
+ A producer gives each claim holder an inclusion proof:
95
+
96
+ ```json
97
+ {"leaf_index": 0, "audit_path": ["sha256:<hex>", "sha256:<hex>"]}
98
+ ```
99
+
100
+ - `leaf_index`: 0-based position of the claim's leaf in the batch.
101
+ - `audit_path`: the RFC 6962 audit path, ordered leaf-to-root: at each tree
102
+ level the sibling hash needed to recompute the parent. A level where the
103
+ node was promoted (no sibling) contributes no path element. A single-leaf
104
+ batch has an empty `audit_path`.
105
+
106
+ ### Verification algorithm
107
+
108
+ Inputs: the claim object, the proof (`leaf_index`, `audit_path`), and the
109
+ registry entry (`merkle_root`, `leaf_count`). All `sha256:<hex>` strings are
110
+ decoded to 32 raw bytes. The algorithm is the RFC 9162 inclusion-proof check:
111
+
112
+ ```
113
+ 1. If leaf_index >= leaf_count, reject.
114
+ 2. r = SHA-256(0x00 || canonical_claim_bytes) # section 2
115
+ fn = leaf_index
116
+ sn = leaf_count - 1
117
+ 3. For each p in audit_path, in order:
118
+ a. If sn == 0, reject (path too long).
119
+ b. If fn is odd, or fn == sn:
120
+ r = SHA-256(0x01 || p || r)
121
+ If fn is even: # fn == sn, right-edge promotion
122
+ until fn is odd or fn == 0: fn = fn >> 1; sn = sn >> 1
123
+ else:
124
+ r = SHA-256(0x01 || r || p)
125
+ c. fn = fn >> 1; sn = sn >> 1
126
+ 4. Accept iff sn == 0 and r equals the entry's merkle_root.
127
+ ```
128
+
129
+ Any failure (wrong root, leftover `sn`, malformed hash, out-of-range index)
130
+ means the claim is NOT proven included in that entry.
131
+
132
+ ### What verification proves
133
+
134
+ A successful verification proves the exact signed claim bytes were part of the
135
+ batch whose root is committed in the public, append-only git history at the
136
+ entry's timestamp. It does not validate the claim's signature or semantics;
137
+ signature verification against the producer key is a separate TRACE step.
138
+
139
+ ## 6. Reference tooling
140
+
141
+ - [`tools/anchor.py`](../tools/anchor.py): builds the tree over one or more
142
+ claim files, emits the registry entry line and one inclusion proof per claim.
143
+ - [`tools/verify_inclusion.py`](../tools/verify_inclusion.py): standalone
144
+ verifier (claim + proof + entry, exit 0/1). Deliberately self-contained so it
145
+ can be copied and audited in isolation.
146
+
147
+ Both are Python 3 standard library only (`hashlib`, `json`).
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "trace-verify"
7
+ version = "0.1.0"
8
+ description = "Verify TRACE claim inclusion proofs against the public registry"
9
+ readme = "README.md"
10
+ license = { text = "CC-BY-4.0" }
11
+ requires-python = ">=3.9"
12
+ dependencies = []
13
+ keywords = ["trace", "merkle", "inclusion-proof", "audit", "ai-governance"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Security :: Cryptography",
25
+ "Topic :: Software Development :: Libraries :: Python Modules",
26
+ ]
27
+
28
+ [project.scripts]
29
+ trace-verify = "trace_verify.__main__:main"
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/agentrust-io/trace-registry"
33
+ Documentation = "https://github.com/agentrust-io/trace-registry/blob/main/docs/anchor-format.md"
34
+ "Bug Tracker" = "https://github.com/agentrust-io/trace-registry/issues"
35
+ Changelog = "https://github.com/agentrust-io/trace-registry/blob/main/CHANGELOG.md"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/trace_verify"]
@@ -0,0 +1 @@
1
+ {"ts": "2026-06-12T18:09:41Z", "merkle_root": "sha256:9279111218532d83279a0ce4c8d114168e2558b8f85054878c97ee5f428abada", "leaf_count": 1, "producer": "cmcp-gateway/0.1.0", "batch_id": "2026-06-12-001"}