ci: fail-closed guard against left-over mutation mutants #345
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: demo-reproducible | |
| # Block C of the pre-outreach checklist (2026-07-07): prove, continuously, that a STRANGER's | |
| # 60-second try works — fresh venv, install from PyPI (not this checkout), run the demo, | |
| # verify the committed receipt, and hold the orthogonal failure matrix: | |
| # tampered payload -> verify FAILED (exit 1) | |
| # foreign/attacker key -> verify FAILED (exit 1) | |
| # no network -> verify still OK (offline-by-design, proven via unshare -rn) | |
| # Every fixture below was proven against the real verifier before this workflow landed | |
| # (tamper_rc=1, foreign_rc=1, offline_rc=0). Honest scope: this exercises the RELEASED | |
| # package (what a reader installs today), while ci.yml covers the checkout. A red run here | |
| # means the public 60-second try is broken right now. | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| schedule: | |
| - cron: "23 5 * * *" | |
| permissions: | |
| contents: read | |
| jobs: | |
| pypi-sixty-second-try: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: "3.12" | |
| - name: Fresh venv, install from PyPI (the stranger's path — NOT this checkout) | |
| run: | | |
| python -m venv /tmp/fresh | |
| /tmp/fresh/bin/pip install --quiet "proofbundle[eval]" | |
| /tmp/fresh/bin/proofbundle --help >/dev/null | |
| - name: 60-second try — demo must exit 0 (honest OK, six tampers caught, sample swap caught) | |
| run: /tmp/fresh/bin/proofbundle demo | |
| - name: Committed receipt verifies from the released package | |
| run: /tmp/fresh/bin/proofbundle verify examples/example_bundle.json | |
| - name: Build the tamper fixtures (payload bit-flip + attacker key swap) | |
| run: | | |
| python - <<'PY' | |
| import json, base64 | |
| b = json.load(open("examples/example_bundle.json")) | |
| raw = base64.b64decode(b["payload_b64"]) | |
| b["payload_b64"] = base64.b64encode(raw[:-1] + bytes([raw[-1] ^ 0x01])).decode() | |
| json.dump(b, open("/tmp/tampered.json", "w")) | |
| b2 = json.load(open("examples/example_bundle.json")) | |
| assert "public_key_b64" in b2["signature"], "receipt layout changed — update this matrix" | |
| b2["signature"]["public_key_b64"] = "A" * 43 + "=" | |
| json.dump(b2, open("/tmp/foreignkey.json", "w")) | |
| PY | |
| - name: Orthogonal matrix — tampered payload MUST fail | |
| run: | | |
| if /tmp/fresh/bin/proofbundle verify /tmp/tampered.json; then | |
| echo "::error::tampered receipt verified OK — the public package is broken" | |
| exit 1 | |
| fi | |
| echo "tampered receipt correctly FAILED" | |
| - name: Orthogonal matrix — foreign key MUST fail | |
| run: | | |
| if /tmp/fresh/bin/proofbundle verify /tmp/foreignkey.json; then | |
| echo "::error::foreign-key receipt verified OK — the public package is broken" | |
| exit 1 | |
| fi | |
| echo "foreign-key receipt correctly FAILED" | |
| - name: Orthogonal matrix — verify with the network namespace REMOVED (offline-by-design) | |
| run: | | |
| # GH runners forbid unprivileged userns (uid_map EPERM); sudo is passwordless there. | |
| sudo unshare -n /tmp/fresh/bin/proofbundle verify examples/example_bundle.json | |
| echo "offline verify OK (no network namespace)" |