Contributing to proofbundle
September 20, 2026 · View on GitHub
Thanks for your interest. This project deliberately stays small, dependency-light and correct. Contributions that keep it that way are very welcome.
Principles
- The trusted verification core stays minimal and easy to audit.
- No custom cryptography. Signature math comes from
cryptography; Merkle hashing follows RFC 6962 exactly. - Every behaviour is covered by a test. Correctness beats features.
Development
git clone https://github.com/b7n0de/proofbundle
cd proofbundle
python -m pip install -e ".[dev]"
# run the tests (pytest is REQUIRED — see the note below)
pytest -q
# regenerate the example bundle
python examples/make_example.py
# lint
ruff check .
Why pytest is required, measured 02.09.2026. This used to say "no pytest required, standard library works too". That is not true of this suite and had not been true for a long time: 104 of 337 test modules import
pytestat module level, and 108 modules hold 991 test functions written as plaindef test_*(), whichunittest discovercannot see at all.Those four figures were re-measured on 2026-09-20 with
astovertests/**/test_*.py; the sentence had said 35 / 217 / 30 / 345 since 02.09.2026 and every one of them was low by a factor between 1.6 and 3.6. The argument did not depend on the exact numbers, which is precisely why they were never checked again — and a figure nobody rechecks is the defect class this repository keeps finding. They are carried with their derivation and their date rather than bound by a gate, because they move with every added test file. A stdlib-only run therefore does not fail loudly — it silently runs several hundred tests fewer and still reportsOK. A promise a test suite cannot keep is worse than no promise: it sends the reader down a path that looks green and is not.The repo-context rule (tests that assert repo/CI/Rust/docs layout declare themselves N/A outside a git checkout) lives in
tests/conftest.py. It is bound to pytest — and that is correct because pytest is the only runner that can run this suite. A rule bound to one runner is a defect only when a second, documented runner exists.
Branch base (fork from main, never from a release tag)
Fork every feature/fix branch from the current main HEAD:
git switch -c <type>/<scope>/<slug> main # e.g. fix/verify/kb-jwt
For a stable patch to an older line, fork from the corresponding release/v1.9.x
branch instead, then merge that branch back into main.
Never branch from a release tag (vX.Y.Z). A tag-based branch predates the
## [Unreleased] section that every later release adds to CHANGELOG.md, so it
re-conflicts on CHANGELOG.md on every single PR. CHANGELOG.md is structured
newest-first: ## [Unreleased] at the top, then released versions in descending
order — a branch cut from an old tag always collides there.
A non-blocking CI check (scripts/branch_base_check.py) warns if a PR branch was
forked from a release tag; it is advisory only and never fails the build. To fix a
branch that was cut from a tag:
git rebase --onto origin/main <tag-it-was-cut-from> <your-branch>
Good first issues
- Add a
proofbundle consistencyCLI subcommand aroundverify_consistency. - Add SHA-384 and SHA-512 Merkle variants behind an explicit
hash_alg. - Add Key Binding JWT verification to the SD-JWT path.
- Add more external RFC 6962 / SD-JWT reference vectors under
tests/fixtures/.
Open an issue before large changes so we can agree on scope. By contributing you agree that your contributions are licensed under the MIT License.