Contributing
Contributing
Contributing
The project welcomes contributions. This document gives the working agreement. It covers: how the project proposes, reviews and merges changes; what the continuous-integration gates enforce.
Ground rules
- Never commit to
main. All work happens on a branch, one change per branch, merged via pull request. Branch names follow<type>/<short-description>kebab-case — e.g.feat/group-ladder,fix/resolver-ewma,docs/spec-scoring. - Conventional Commits. Every commit subject follows the specification:
type(scope): subject.- Types:
feat,fix,docs,refactor,test,build,ci,chore,perf,revert. scopeis a component:probe(probe plans, deadline ladder),quic(QUIC plane),classify(registry tables, taxonomy, scoring),resolver(DNS/PTR),target(grammar, dedupe, shard),out(encoders, WAL),legacy(optional legacy module),cli,docs,ci,release.- Subject: imperative, lowercase, no trailing period. Body (optional): what changed and why; wrap at 72 columns.
- PR titles follow the same form; roadmap slices carry the task id in the subject —
type(scope): PQ-XXn — subject. Squash merges use the PR title as the commit subject, so the PR title is the commit record. A CI gate checks the form on every PR; bot/dependency PRs (renovate, pre-commit.ci autoupdate) keep their canonical titles.
- Types:
- Sign everything. Commits carry a GPG or SSH signature (
git config commit.gpgsign true); releases carry signed tags. An unsigned commit or tag blocks the merge and the publish. This repository signs with the OWASP identity: OpenPGP key9CB1781DC2BB28D37A0155DCAAF8226F3F4C1712, emailshain.singh@owasp.org. Theprotect-defaultruleset enforcesrequired_signatures. Verify withgit log --show-signature/git tag -v. - One logical change per PR. Small, reviewable diffs merge faster.
- Pre-commit runs locally. Install the hooks once per clone:
pre-commit install && pre-commit install --hook-type pre-push. Then everygit commitandgit pushruns the same hook set CI runs. Bypass with--no-verifyfor the rare legitimate exception.
Security-sensitive changes
Extra care applies to the probe-affecting defaults, the classifier registry tables, and the output schema (SECURITY.md carries the full posture):
- Vulnerabilities do not go into public issues. Follow
SECURITY.md— never open a public issue for an unreported vulnerability. - Etiquette defaults (rate caps, per-subnet concurrency, breaker thresholds, deadline ladder) are the published safety posture: a change that loosens them implicitly is rejected in review and needs its own ADR.
- Registry integrity: IANA-derived files regenerate from the registry; hand edits never happen; a review rejects inline codepoints in engines or prose.
- Output schema: field removals or semantic changes break the contract — the change needs a schema bump and a migration note.
The acceptance suite
gofmt -l . && go vet ./... # formatting + static analysis
go test ./... # the fixture matrix + unit suite
pre-commit run --all-files # the hook set CI runs
The repo is stdlib-first: new dependencies need the justification in the PR body. The hook set (trailing whitespace, YAML/JSON validity, large-file guards, detect-private-key, shellcheck on shell scripts) runs on every PR.
CI on every pull request
| Check | What it does |
|---|---|
PR title — Conventional Commits + PQ id |
PR title checked against the Conventional Commits form |
| Dependency Review | flags vulnerable or licence-incompatible dependency changes |
required_signatures |
ruleset-enforced: unsigned commits block the PR |
Required status checks grow as CI surfaces arrive (the build/test legs arrived first).
Commits and pull requests
- Push the branch and open a PR against
main; describe the what and the why. - The PR body links the
PQ-XXnissue the change implements and thedocs/spec.mdsections it exercises (GitHub heading anchors). - The maintainer reviews and merges every PR; do not enable auto-merge on the maintainer’s behalf.
- Releases are signed tags; the release sequence is defined in
docs/spec.md.
Reporting bugs
Open a GitHub issue. The report carries: the version or commit, the mode and the probe surface hit, the host OS, the relevant output excerpt. Security issues never go here — SECURITY.md instead.
The matrix-cell duty: fix a bug, add the cell
Every bug fix and every feature that touches a flag combination adds the reproducing combination as a new matrix cell in the same PR. The cell takes one shape: an array case, a battery vector class, a refusal row, or a chain cell. The row goes in tests/matrix/LEDGER.md (origin, the landing date, the invariant it pins); the checkbox goes in issue #150’s body registry. An unverified checkbox is the standing drift signal; the next build clears it. Bug reports name the cell through the required Matrix cell field of the bug report template; new there means the fixer derives the row and adds the cell.
Licence
The project carries the MIT licence — see LICENSE. Contributions come in under the project’s MIT terms.
Engineering standard: hypothesis-first, check-first
Every feature, fix and refactor follows hypothesis → failing test → minimal implementation → refactor:
- State the hypothesis in the issue: the expected behaviour, the assumed mechanism, the falsifying observation.
- Commit the failing test first on the feature branch; paste the RED run’s failure line into the PR.
- Implement the minimum that passes; run the suite; refactor with the tests green.
- Cover the edge and error paths (timeouts, malformed targets, failure modes) before close.
Live-network behaviour sits outside the unit tests’ reach. The issue’s acceptance criterion then acts as the test: record the expected-versus-observed run before the change; re-run after.
Harness before capability. The check that gates a behaviour goes in the same PR as the behaviour; nothing merges ahead of the check that catches its regression, and a new gate’s negative case gets its proof in CI, not in prose.
Exceptions need the maintainer’s explicit go-ahead in the issue before work starts.