pytest-gpu-proof 0.3.0__tar.gz → 0.4.1__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.
- pytest_gpu_proof-0.4.1/.github/workflows/ci.yml +68 -0
- pytest_gpu_proof-0.4.1/.github/workflows/docs.yml +69 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/.gitignore +3 -1
- pytest_gpu_proof-0.4.1/AGENTS.md +29 -0
- pytest_gpu_proof-0.4.1/CHANGELOG.md +180 -0
- pytest_gpu_proof-0.4.1/CLAUDE.md +14 -0
- pytest_gpu_proof-0.4.1/CONTRIBUTING.md +41 -0
- pytest_gpu_proof-0.4.1/PKG-INFO +353 -0
- pytest_gpu_proof-0.4.1/README.md +315 -0
- pytest_gpu_proof-0.4.1/ROADMAP.md +15 -0
- pytest_gpu_proof-0.4.1/SECURITY.md +33 -0
- pytest_gpu_proof-0.4.1/docs/architecture.md +99 -0
- pytest_gpu_proof-0.4.1/docs/ci_gpu_mode.md +64 -0
- pytest_gpu_proof-0.4.1/docs/index.md +40 -0
- pytest_gpu_proof-0.4.1/docs/local_mode.md +87 -0
- pytest_gpu_proof-0.4.1/docs/policy.md +91 -0
- pytest_gpu_proof-0.4.1/docs/quickstart.md +101 -0
- pytest_gpu_proof-0.4.1/docs/security_model.md +115 -0
- pytest_gpu_proof-0.4.1/docs/sharding.md +91 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/mkdocs.yml +3 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/pyproject.toml +27 -9
- pytest_gpu_proof-0.4.1/requirements-dev.txt +8 -0
- pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/__init__.py +1 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/cli.py +110 -2
- pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/compare.py +68 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/config.py +53 -7
- pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/fingerprint.py +166 -0
- pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/gitutils.py +176 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/merge.py +173 -24
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/plugin.py +168 -80
- pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/receipt.py +270 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/signers/ed25519.py +47 -18
- pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/verify.py +591 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/tests/conftest.py +27 -0
- pytest_gpu_proof-0.4.1/tests/test_cli.py +82 -0
- pytest_gpu_proof-0.4.1/tests/test_compare.py +118 -0
- pytest_gpu_proof-0.4.1/tests/test_config.py +123 -0
- pytest_gpu_proof-0.4.1/tests/test_fingerprint.py +209 -0
- pytest_gpu_proof-0.4.1/tests/test_gitutils.py +161 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/tests/test_merge.py +85 -5
- pytest_gpu_proof-0.4.1/tests/test_plugin_capture.py +653 -0
- pytest_gpu_proof-0.4.1/tests/test_receipt.py +341 -0
- pytest_gpu_proof-0.4.1/tests/test_sharding.py +697 -0
- pytest_gpu_proof-0.4.1/tests/test_signing.py +272 -0
- pytest_gpu_proof-0.4.1/tests/test_verifier.py +956 -0
- pytest_gpu_proof-0.4.1/website/README.md +85 -0
- pytest_gpu_proof-0.4.1/website/build_site.py +82 -0
- pytest_gpu_proof-0.4.1/website/check_site.py +90 -0
- pytest_gpu_proof-0.4.1/website/favicon.svg +1 -0
- pytest_gpu_proof-0.4.1/website/index.html +127 -0
- pytest_gpu_proof-0.4.1/website/main.js +17 -0
- pytest_gpu_proof-0.4.1/website/overrides/main.html +4 -0
- pytest_gpu_proof-0.4.1/website/provenance.json +10 -0
- pytest_gpu_proof-0.4.1/website/requirements.txt +2 -0
- pytest_gpu_proof-0.4.1/website/style.css +67 -0
- pytest_gpu_proof-0.4.1/website/test_site.py +89 -0
- pytest_gpu_proof-0.4.1/website/workflow-mobile.svg +32 -0
- pytest_gpu_proof-0.4.1/website/workflow.svg +35 -0
- pytest_gpu_proof-0.3.0/.github/workflows/ci.yml +0 -27
- pytest_gpu_proof-0.3.0/.github/workflows/docs.yml +0 -29
- pytest_gpu_proof-0.3.0/CHANGELOG.md +0 -66
- pytest_gpu_proof-0.3.0/CLAUDE.md +0 -73
- pytest_gpu_proof-0.3.0/PKG-INFO +0 -400
- pytest_gpu_proof-0.3.0/README.md +0 -367
- pytest_gpu_proof-0.3.0/ROADMAP.md +0 -11
- pytest_gpu_proof-0.3.0/docs/architecture.md +0 -92
- pytest_gpu_proof-0.3.0/docs/ci_gpu_mode.md +0 -100
- pytest_gpu_proof-0.3.0/docs/index.md +0 -33
- pytest_gpu_proof-0.3.0/docs/local_mode.md +0 -136
- pytest_gpu_proof-0.3.0/docs/quickstart.md +0 -377
- pytest_gpu_proof-0.3.0/docs/security_model.md +0 -87
- pytest_gpu_proof-0.3.0/docs/sharding.md +0 -109
- pytest_gpu_proof-0.3.0/requirements-dev.txt +0 -3
- pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/__init__.py +0 -1
- pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/compare.py +0 -49
- pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/fingerprint.py +0 -38
- pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/gitutils.py +0 -112
- pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/receipt.py +0 -166
- pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/verify.py +0 -412
- pytest_gpu_proof-0.3.0/tests/test_compare.py +0 -64
- pytest_gpu_proof-0.3.0/tests/test_fingerprint.py +0 -40
- pytest_gpu_proof-0.3.0/tests/test_gitutils.py +0 -69
- pytest_gpu_proof-0.3.0/tests/test_plugin_capture.py +0 -307
- pytest_gpu_proof-0.3.0/tests/test_receipt.py +0 -142
- pytest_gpu_proof-0.3.0/tests/test_sharding.py +0 -282
- pytest_gpu_proof-0.3.0/tests/test_signing.py +0 -96
- pytest_gpu_proof-0.3.0/tests/test_verifier.py +0 -363
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/.github/workflows/publish-testpypi.yml +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/.github/workflows/publish.yml +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/LICENSE +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/RELEASING.md +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/docs/landscape.md +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/Makefile +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/README.md +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/cuda_ctypes_matmul.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/matmul_kernel.cu +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/test_cuda_ctypes_matmul.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/CMakeLists.txt +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/README.md +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/src/bindings.cpp +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/src/matmul_cuda.h +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/src/matmul_kernel.cu +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/test_cuda_nanobind_matmul.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/CMakeLists.txt +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/README.md +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/src/bindings.cpp +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/src/matmul_cuda.h +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/src/matmul_kernel.cu +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/test_cuda_pybind11_matmul.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/github_gpu_runner/.github/workflows/gpu-test.yml +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/CMakeLists.txt +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/README.md +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/jax_ffi_matmul.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/src/matmul_ffi.cu +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/test_jax_ffi_cuda_matmul.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/local_receipt_verify/.github/workflows/verify.yml +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/minimal_python_only/conftest.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/minimal_python_only/test_minimal.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/wrapped_cuda_ctypes/fake_cuda_lib.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/wrapped_cuda_ctypes/test_cuda_wrapper.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/install.sh +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/requirements.txt +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/__main__.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/signers/__init__.py +0 -0
- {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/signers/base.py +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Install package with dev extras
|
|
24
|
+
run: pip install -e ".[dev]"
|
|
25
|
+
|
|
26
|
+
- name: Run test suite (CPU-only)
|
|
27
|
+
run: python -m pytest tests/ -q
|
|
28
|
+
|
|
29
|
+
coverage:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.12"
|
|
36
|
+
- name: Install package with dev extras
|
|
37
|
+
run: pip install -e ".[dev]"
|
|
38
|
+
- name: Enforce 100% line and branch coverage
|
|
39
|
+
run: |
|
|
40
|
+
coverage run -m pytest tests/ -q
|
|
41
|
+
coverage report --fail-under=100
|
|
42
|
+
coverage xml
|
|
43
|
+
- uses: actions/upload-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: coverage-xml
|
|
46
|
+
path: coverage.xml
|
|
47
|
+
|
|
48
|
+
docs-and-package:
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
- uses: actions/setup-python@v5
|
|
53
|
+
with:
|
|
54
|
+
python-version: "3.12"
|
|
55
|
+
- name: Install package with dev extras
|
|
56
|
+
run: pip install -e ".[dev]"
|
|
57
|
+
- name: Build documentation strictly
|
|
58
|
+
run: mkdocs build --strict
|
|
59
|
+
- name: Build and inspect distributions
|
|
60
|
+
run: |
|
|
61
|
+
python -m build
|
|
62
|
+
python -m twine check --strict dist/*
|
|
63
|
+
- name: Smoke-test the wheel
|
|
64
|
+
run: |
|
|
65
|
+
python -m venv /tmp/wheeltest
|
|
66
|
+
/tmp/wheeltest/bin/pip install -q dist/*.whl
|
|
67
|
+
/tmp/wheeltest/bin/gpu-proof --help
|
|
68
|
+
/tmp/wheeltest/bin/python -m pytest -p pytest_gpu_proof --version
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
paths:
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
- 'website/**'
|
|
10
|
+
- 'mkdocs.yml'
|
|
11
|
+
- '.github/workflows/docs.yml'
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: docs-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
|
|
30
|
+
- name: Install website dependencies
|
|
31
|
+
run: pip install -r website/requirements.txt
|
|
32
|
+
|
|
33
|
+
- name: Build and check the complete website
|
|
34
|
+
run: python website/build_site.py
|
|
35
|
+
|
|
36
|
+
- name: Test website checks
|
|
37
|
+
run: python -m unittest discover -s website -p 'test_*.py'
|
|
38
|
+
|
|
39
|
+
- uses: actions/upload-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: website-preview
|
|
42
|
+
path: build/website
|
|
43
|
+
include-hidden-files: true
|
|
44
|
+
|
|
45
|
+
deploy:
|
|
46
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
47
|
+
needs: build
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
permissions:
|
|
50
|
+
contents: write
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
with:
|
|
54
|
+
fetch-depth: 0
|
|
55
|
+
- uses: actions/setup-python@v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: "3.12"
|
|
58
|
+
- run: pip install -r website/requirements.txt
|
|
59
|
+
- uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: website-preview
|
|
62
|
+
path: build/website
|
|
63
|
+
- name: Configure git author
|
|
64
|
+
run: |
|
|
65
|
+
git config user.name "github-actions[bot]"
|
|
66
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
67
|
+
|
|
68
|
+
- name: Deploy to gh-pages
|
|
69
|
+
run: ghp-import --no-jekyll --push --branch gh-pages build/website
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Agent guide
|
|
2
|
+
|
|
3
|
+
This repository is a security-sensitive pytest plugin. Preserve fail-closed
|
|
4
|
+
behavior and treat receipt, fingerprint, signature, Git, merge, and policy code
|
|
5
|
+
as trust boundaries.
|
|
6
|
+
|
|
7
|
+
Before changing behavior, read:
|
|
8
|
+
|
|
9
|
+
- `README.md`
|
|
10
|
+
- `docs/architecture.md`
|
|
11
|
+
- `docs/security_model.md`
|
|
12
|
+
- `docs/policy.md`
|
|
13
|
+
- `CONTRIBUTING.md`
|
|
14
|
+
|
|
15
|
+
Implementation rules:
|
|
16
|
+
|
|
17
|
+
- New receipts are schema 3; keep explicit legacy verification isolated.
|
|
18
|
+
- Signer metadata belongs inside the signed payload.
|
|
19
|
+
- Default fingerprint scope is the full tracked repository; generated inputs
|
|
20
|
+
require explicit extra paths.
|
|
21
|
+
- Never turn receipt-emission failures into success unless the caller selected
|
|
22
|
+
`best_effort`.
|
|
23
|
+
- Never accept unknown policy fields or malformed receipt structure.
|
|
24
|
+
- Keep tests hermetic: mock GitHub key lookup and local identity.
|
|
25
|
+
- Maintain 100% line and branch coverage. Add adversarial cases for new trust
|
|
26
|
+
branches.
|
|
27
|
+
- Do not edit generated `site/` or release artifacts in `dist/`.
|
|
28
|
+
|
|
29
|
+
Run the complete check list from `CONTRIBUTING.md` before proposing a PR.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to pytest-gpu-proof are documented here. The format is
|
|
4
|
+
based on [Keep a Changelog](https://keepachangelog.com/); versions follow
|
|
5
|
+
[SemVer](https://semver.org/) (pre-1.0: minor bumps may break).
|
|
6
|
+
|
|
7
|
+
## [0.4.1] — 2026-10-12
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Shard entries record `dirty` (the recording tree's state); merge ORs shard
|
|
12
|
+
flags into the merged `repo.dirty`, carry-forward refuses a dirty shard, and
|
|
13
|
+
verification refuses any dirty shard unless `allow_dirty` is set.
|
|
14
|
+
- `gpu-proof merge --carry-from` refuses a source receipt recorded with a dirty
|
|
15
|
+
working tree. The merged `repo.dirty` is OR-ed over the fresh inputs only, so a
|
|
16
|
+
carried shard from a dirty recording was laundered into a clean-looking merged
|
|
17
|
+
receipt (found by GRiD's split driver, 2026-10-10). Carried shards now record
|
|
18
|
+
`carried.original_dirty`, and verification refuses a carried shard recorded
|
|
19
|
+
dirty unless `allow_dirty` is set.
|
|
20
|
+
|
|
21
|
+
- The expected-skips mismatch names the delta (unexpected skips and stale
|
|
22
|
+
baseline entries) instead of only reporting that the sets differ.
|
|
23
|
+
- The receipt's `environment.gpu_info` falls back to the same torch probe the
|
|
24
|
+
`gpu_required` marker uses when nvidia-smi is absent or fails (`source`
|
|
25
|
+
records which probe answered), so a torch-only box no longer records
|
|
26
|
+
`gpu_info: null` and then fails a `require_gpu` policy.
|
|
27
|
+
|
|
28
|
+
- Verification refuses a receipt whose session started more than five
|
|
29
|
+
minutes before its commit existed (committer time): a cheap replay and
|
|
30
|
+
forgery guard that needs no nonce.
|
|
31
|
+
|
|
32
|
+
- `mode: ci-gpu` is now bound to the signing key: a ci-gpu receipt verifies
|
|
33
|
+
only when the policy lists `allowed_key_fingerprints` and the receipt was
|
|
34
|
+
signed by one of them (previously the mode was an unverified label).
|
|
35
|
+
- Without an explicit `carried_max_age_days`, a carried shard's original run
|
|
36
|
+
may not be older than the receipt's `max_age_days` (was a fixed 30 days).
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- `gpu-proof merge --verify-inputs`: authenticate every input shard against
|
|
41
|
+
its signer's current GitHub keys before merging (unsigned or tampered inputs
|
|
42
|
+
are refused).
|
|
43
|
+
- `gpu-proof status PATH...`: one-line summaries of receipt files or
|
|
44
|
+
directories (commit, dirty, signed, outcome, counts, shards, carried).
|
|
45
|
+
- `gpu-proof durations RECEIPT... --out map.json`: fold per-test durations
|
|
46
|
+
into a JSON map for shard bin-packing.
|
|
47
|
+
- Command-line equivalents for the toml-only options:
|
|
48
|
+
`--gpu-proof-no-gpu-uuid`, `--gpu-proof-require-gpu`,
|
|
49
|
+
`--gpu-proof-max-age-days N`.
|
|
50
|
+
- `gpu-proof plan --receipt OLD [--repo .] [--json]`: a dry run of the
|
|
51
|
+
carry-forward conditions against the current tree, reporting per shard
|
|
52
|
+
whether it could be carried or must be re-run (and why). Drivers that plan
|
|
53
|
+
partial re-runs no longer reimplement the checks.
|
|
54
|
+
- `record_gpu_uuid` (`[tool.gpu_proof]`, default `true`): set `false` to omit each GPU's
|
|
55
|
+
nvidia-smi UUID from the receipt environment while keeping name, driver, memory and
|
|
56
|
+
compute capability. Verification does not read the UUID.
|
|
57
|
+
|
|
58
|
+
## [0.4.0] — 2026-08-17
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
|
|
62
|
+
- Schema `"3"`: signer username, key fingerprint, key algorithm, exact test
|
|
63
|
+
collection, session outcome, pytest arguments, and per-shard environment/time
|
|
64
|
+
are included in the signed payload.
|
|
65
|
+
- Open contributor and restricted signer policies. Restricted mode supports
|
|
66
|
+
username and exact SSH-key-fingerprint allowlists.
|
|
67
|
+
- Policy pinning for mode, global tracked/extra fingerprint scope, exact test
|
|
68
|
+
manifest, shard names, and per-shard tracked/extra scope.
|
|
69
|
+
- Explicit fingerprint paths for ignored/generated inputs and manifest support
|
|
70
|
+
for symlinks and submodule gitlinks.
|
|
71
|
+
- Explicit receipt-artifact exclusions avoid self-referential whole-tree
|
|
72
|
+
fingerprints and can be pinned by verification policy.
|
|
73
|
+
- `--gpu-proof-best-effort` as an explicit development escape hatch.
|
|
74
|
+
- `min_schema` policy field to refuse legacy schema-1/2 receipts.
|
|
75
|
+
- Python 3.13 CI, strict docs/package jobs, and enforced 100% line and branch
|
|
76
|
+
coverage.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- The default fingerprint scope is the entire Git-tracked repository instead
|
|
81
|
+
of `src,tests`.
|
|
82
|
+
- Receipt creation now fails pytest on Git, fingerprint, key, serialization, or
|
|
83
|
+
write errors; it also removes stale output at session start.
|
|
84
|
+
- Schema-3 verification rejects dirty recording and verification trees by
|
|
85
|
+
default and accepts receipt commits only at the current commit or an ancestor.
|
|
86
|
+
- Setup/teardown failures, missing terminal reports, comparison exceptions,
|
|
87
|
+
skipped tests, and overall session failure are represented and verified.
|
|
88
|
+
- GPU metadata records all devices reported by `nvidia-smi`.
|
|
89
|
+
- Array comparison is shape-safe, uses tolerance only for float/complex data,
|
|
90
|
+
and uses exact equality for other dtypes.
|
|
91
|
+
- Receipt writes are atomic and strict JSON forbids NaN/non-JSON values.
|
|
92
|
+
- Receipt generation rejects xdist workers; use separate shard processes.
|
|
93
|
+
- Legacy schema-1/2 verification derives the policy-checked key fingerprint
|
|
94
|
+
from the key that actually verified the signature; an asserted
|
|
95
|
+
`signature.key_fingerprint` that disagrees is rejected.
|
|
96
|
+
- `signer_mode: restricted` policies reject unsigned receipts even with
|
|
97
|
+
`--allow-unsigned`, and `--github-user` must match the signed schema-3
|
|
98
|
+
identity.
|
|
99
|
+
- The receipt under verification is excluded from the verification-tree dirty
|
|
100
|
+
check, so an untracked just-generated receipt verifies without gitignoring.
|
|
101
|
+
- Passphrase-protected SSH keys prompt correctly on current cryptography
|
|
102
|
+
releases (`ValueError` as well as `TypeError`) and fail closed with an
|
|
103
|
+
actionable message when no terminal is available.
|
|
104
|
+
- Uninitialized submodule checkouts fingerprint their index gitlink commit
|
|
105
|
+
instead of accidentally recording the parent repository's HEAD.
|
|
106
|
+
- Receipt/shard age limits are enforced to the exact day boundary.
|
|
107
|
+
- GitHub usernames are validated before key fetches and key responses are
|
|
108
|
+
size-capped.
|
|
109
|
+
- A stale receipt that cannot be cleared at session start raises a pytest
|
|
110
|
+
usage error (an exit-status write that early would be silently overwritten).
|
|
111
|
+
- Merging receipts without session timestamps is refused with a clear error.
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- Carry-forward now recomputes the stored fingerprint algorithm and preserves
|
|
116
|
+
explicit generated/ignored shard inputs.
|
|
117
|
+
- Signed identity and algorithm substitution are rejected.
|
|
118
|
+
- Empty source scope, unmerged index entries, malformed policies, incomplete
|
|
119
|
+
collections, and stale success artifacts fail closed.
|
|
120
|
+
|
|
121
|
+
## [0.3.0] — 2026-08-08
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
- Schema `"2"` sharded receipts: `--gpu-proof-shard NAME` +
|
|
125
|
+
`--gpu-proof-shard-fingerprint-paths` emit a per-shard narrow fingerprint;
|
|
126
|
+
`gpu-proof merge` unions schema-2 shards (unique names enforced).
|
|
127
|
+
- Verifiable carry-forward: `gpu-proof merge --carry-from OLD` grafts shards
|
|
128
|
+
absent from the fresh inputs iff the old commit is an ancestor AND the
|
|
129
|
+
shard's narrow fingerprint recomputes clean; grafted shards are marked
|
|
130
|
+
`carried` and the verifier rejects them unless the policy sets
|
|
131
|
+
`allow_carried: true` (bounded by `carried_max_age_days`, default 30).
|
|
132
|
+
- Verifier: schema-2 checks (per-shard fingerprint recompute, membership
|
|
133
|
+
partition of `tests[]`, carried-shard policy gate). Schema-1 receipts are
|
|
134
|
+
unchanged and a schema-1 receipt carrying a `shards` block is rejected.
|
|
135
|
+
|
|
136
|
+
## [0.2.0] — 2026-08-07
|
|
137
|
+
|
|
138
|
+
### Added
|
|
139
|
+
- `gpu-proof merge`: union N shard receipts from one commit into a single
|
|
140
|
+
re-signed receipt (per-module crash isolation / machine sharding). Refuses
|
|
141
|
+
shards that disagree on schema, commit SHA, fingerprint, mode, or
|
|
142
|
+
environment; duplicate node IDs across shards are a hard error. Records
|
|
143
|
+
per-shard provenance under `session.shards` (additive — the verifier is
|
|
144
|
+
unchanged). `repo.dirty` is OR-ed; `gpu_info` survives CPU-only shards.
|
|
145
|
+
Docs: `docs/sharding.md`.
|
|
146
|
+
|
|
147
|
+
### Fixed
|
|
148
|
+
- Explicit CLI values equal to their built-in defaults are no longer silently
|
|
149
|
+
ignored in favor of `[tool.gpu_proof]` (value-taking options now register a
|
|
150
|
+
`None` sentinel; `--gpu-proof-fail-on-skip` ORs with the toml value since a
|
|
151
|
+
store_true flag can only turn it on).
|
|
152
|
+
|
|
153
|
+
## [0.1.0] — 2026-07-07
|
|
154
|
+
|
|
155
|
+
First public release.
|
|
156
|
+
|
|
157
|
+
### Added
|
|
158
|
+
- pytest plugin (`-p` auto-loaded via the `pytest11` entry point): captures
|
|
159
|
+
per-test outcomes and skips, git SHA, a SHA-256 source fingerprint over
|
|
160
|
+
configured paths, and self-reported GPU info; emits a signed JSON receipt at
|
|
161
|
+
session end (`--gpu-proof-enable`).
|
|
162
|
+
- Ed25519 SSH-key signing; signature covers the canonical (compact,
|
|
163
|
+
sorted-key) JSON without the signature block. `none` backend for unsigned
|
|
164
|
+
receipts.
|
|
165
|
+
- CPU-only verifier `gpu-proof verify`: signature against the signer's public
|
|
166
|
+
`github.com/<user>.keys`, fingerprint match, commit SHA, outcome + skip
|
|
167
|
+
policy, `--require-gpu`, freshness (`--max-age-days`, `0` = today only),
|
|
168
|
+
dirty policy.
|
|
169
|
+
- Skip policies: `--allow-skipped` (any) or `--expected-skips FILE` (exact-set
|
|
170
|
+
baseline — unexpected AND stale entries both fail); mutually exclusive.
|
|
171
|
+
Also `[tool.gpu_proof] expected_skips`.
|
|
172
|
+
- Signer resolution: explicit flag/config → `gh` CLI login (keyholder) →
|
|
173
|
+
origin-remote owner with a printed warning (org remotes have no SSH keys).
|
|
174
|
+
- `is_dirty` ignores untracked content inside submodules (pin moves and
|
|
175
|
+
tracked edits still count).
|
|
176
|
+
- Receipt diffing (`compare.py`), `[tool.gpu_proof]` pyproject configuration,
|
|
177
|
+
docs site (mkdocs), honest trust-model statement in
|
|
178
|
+
`docs/security_model.md`.
|
|
179
|
+
|
|
180
|
+
[0.1.0]: https://github.com/A2R-Lab/pytest-gpu-proof/releases/tag/v0.1.0
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Claude orientation
|
|
2
|
+
|
|
3
|
+
Use [AGENTS.md](AGENTS.md) as the canonical agent guide. In particular:
|
|
4
|
+
|
|
5
|
+
- a receipt is signer attestation, not proof of GPU execution;
|
|
6
|
+
- receipt, fingerprint, signature, Git, merge, and policy code fail closed;
|
|
7
|
+
- new recordings use schema 3 and bind signer metadata inside the signature;
|
|
8
|
+
- the default manifest covers the full tracked repository;
|
|
9
|
+
- tests are hermetic and maintain 100% line and branch coverage;
|
|
10
|
+
- generated `site/`, `dist/`, coverage output, real keys, and local receipts are
|
|
11
|
+
not source changes.
|
|
12
|
+
|
|
13
|
+
Before implementation work, read `docs/architecture.md`,
|
|
14
|
+
`docs/security_model.md`, `docs/policy.md`, and `CONTRIBUTING.md`.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
python -m venv .venv
|
|
7
|
+
source .venv/bin/activate
|
|
8
|
+
python -m pip install -e ".[dev]"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Required checks
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
python -m pytest tests -q
|
|
15
|
+
coverage run -m pytest tests -q
|
|
16
|
+
coverage report --fail-under=100
|
|
17
|
+
mkdocs build --strict
|
|
18
|
+
python -m build
|
|
19
|
+
python -m twine check --strict dist/*
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
CI runs the test suite on Python 3.11, 3.12, and 3.13, independently enforces
|
|
23
|
+
100% line and branch coverage, builds docs strictly, and smoke-tests the wheel.
|
|
24
|
+
|
|
25
|
+
## Change expectations
|
|
26
|
+
|
|
27
|
+
- Add adversarial tests for trust-boundary changes, not only happy paths.
|
|
28
|
+
- Keep receipt generation and verification fail-closed by default.
|
|
29
|
+
- Treat schema and policy changes as compatibility decisions; document them in
|
|
30
|
+
`CHANGELOG.md` and the relevant guide.
|
|
31
|
+
- Keep Git and network tests hermetic. Never depend on a developer's actual
|
|
32
|
+
GitHub login, SSH keys, GPU, or global Git configuration.
|
|
33
|
+
- Use separate pytest processes for shards. Receipt generation does not support
|
|
34
|
+
xdist workers.
|
|
35
|
+
- Do not commit generated `site/`, coverage files, caches, or local receipts.
|
|
36
|
+
|
|
37
|
+
## Pull requests
|
|
38
|
+
|
|
39
|
+
Describe the trust claim before and after the change, migration implications,
|
|
40
|
+
and the exact checks run. Small, reviewable commits are preferred. Security
|
|
41
|
+
reports should follow [SECURITY.md](SECURITY.md), not a public issue.
|