Skip to content

Dependency Contract

The six requirements*.in files own every exact direct Python dependency. Each is paired with a same-stem requirements*.txt lock generated by pip-compile with hashes; locks must never be edited manually. Every tool input includes requirements.in exactly once, so all runtime-derived environments resolve the same published runtime pin.

Audience Direct input Generated lock Purpose
runtime requirements.in requirements.txt published ssh-wrapper runtime
quality requirements-quality.in requirements-quality.txt Ruff, mypy, Bandit, audit, licenses
test requirements-test.in requirements-test.txt pytest and coverage
package requirements-package.in requirements-package.txt wheel/sdist construction
standalone requirements-standalone.in requirements-standalone.txt native PyInstaller build
docs requirements-docs.in requirements-docs.txt strict MkDocs rendering

pyproject.toml declares runtime dependencies as dynamic setuptools metadata read from requirements.in. It contains no second copy of those versions and no internal quality, test, package, standalone, or documentation extras. Its build-system setuptools range expresses a backend capability; the exact setuptools used by project commands is pinned in requirements-package.in.

ssh-wrapper==0.1.0 is the sole runtime dependency. Every audience that needs it resolves the reviewed PyPI wheel through generated hashes. This repository does not vendor it, build it from another checkout, or add an import path to an uninstalled source tree.

Run make lock only after an intentional direct dependency change in a requirements*.in file and make refresh-dependencies for a reviewed whole-graph upgrade. Both use the online resolver container. Never edit a lock manually. Environment targets install with --require-hashes, binary-only policy, and pip check.

make freeze-check is an explicit online gate that recompiles every audience against its current constraints. make lock-validate checks exact ownership, pins, hashes, and wrapper provenance. make dependency-snapshot produces the six GitHub dependency manifests deterministically.

Dependabot treats every .in file as a native pip-compile manifest, updates its matching .txt lock, and groups all ordinary Python changes into one pull request. pyproject.toml is excluded from its pip manifests so a plain requirements updater cannot take ownership of generated locks. The coordinated ssh-wrapper runtime contract remains excluded from automatic version changes. Both local resolver stages pin the pip==26.1.1 and pip-tools==7.5.3 pair used by Dependabot when this contract was established; a future resolver migration must update both stages together and reproduce all six locks. GitHub Actions updates remain grouped into one other pull request, so one scheduled run opens at most one update per ecosystem.

make audit checks every lock and accepts only exact findings in dependency-audit-exceptions.json; an unused exception fails as stale. make licenses inventories the complete standalone build environment, a conservative superset of bundled Python packages; make outdated is an explicit online review aid. Maintainer locks are not a public installation interface: users install the published distribution normally.