Skip to content

Dependency Contract

Assertions

DEP-001 - Requirements inputs own every direct Python dependency

Contract: The four root requirements-*.in files MUST be the only direct Python dependency manifests; the exact build-backend requirement in the pyproject.toml [build-system] table is the sole build-time exception. Root pyproject.toml MUST declare no optional dependency groups, and its runtime dependencies MUST remain empty unless an ADR introduces a reviewed runtime-lock policy. Each input MUST be independent and contain only exact direct pins. Quality, test, package, and documentation tools MUST be exact direct pins to their latest stable releases compatible with their supported job audience. Tool pins MUST remain disjoint. A platform compatibility package MAY be shared only by the audiences that require it. A temporary older pin MUST carry an inline reason and changelog entry.

Evidence:

DEP-002 - Exactly four non-empty generated hash locks exist

Contract: requirements-dev.txt, requirements-test.txt, requirements-package.txt, and requirements-docs.txt MUST be the only Python locks, each generated by pip-compile from its same-stem .in input. Every entry MUST be an exact pin with one or more SHA-256 hashes. The empty runtime dependency set MUST NOT have a placeholder requirements.in or requirements.txt. Generated locks MUST NOT be hand-edited.

Evidence:

DEP-003 - Lock installation is hash-verified and wheel-only

Contract: Supported Make environments MUST install their exact lock with --require-hashes --only-binary=:all: and run pip check. The isolated resolver bootstrap MAY use one exact inline wheel-only install set; no workflow MAY introduce an independent Python tool list.

Evidence:

DEP-004 - Platform jobs install only their supported audience

Contract: Linux quality MAY install the dev lock containing Ruff, mypy, Bandit, and pip-audit. Compatibility jobs on Windows and Linux MUST install only the test lock; distribution jobs MUST install only the package lock; Pages MUST install only the docs lock. A tool's missing wheel on an unrelated platform MUST be handled by this audience split, not by a repository-wide downgrade. Because pip-compile evaluates environment markers on its resolver host, the test and package inputs MUST directly pin their shared Windows console dependency.

Evidence:

DEP-005 - Lock generation is reproducible and drift is blocking

Contract: make lock MUST regenerate all four locks from their requirements inputs with the exact resolver bootstrap, which MUST pin exact pip and pip-tools versions. make refresh-dependencies MUST re-resolve after a reviewed direct-pin update. make freeze-check MUST recompile every input constrained by its committed lock, so upstream releases never count as drift, and fail on any semantic difference between an input and its lock. make lock-platform-check MUST additionally prove that the test and package locks can resolve exclusively from Windows wheels for every supported CPython version, and the complete Linux CI contract MUST run that check.

Evidence:

DEP-006 - Every non-empty lock is audited

Contract: The Linux CI contract MUST run strict vulnerability audit against each of the four exact lock files. A known vulnerability MUST fail unless a future exception mechanism is itself exact, reviewed, tested, and documented.

Evidence:

DEP-007 - Dependency submission derives every lock offline

Contract: The snapshot generator MUST parse exactly the four hash locks, cross-check them against the direct pins of their same-stem requirements inputs, reject empty, hashless, missing, or version-drifted content, and emit deterministic direct/transitive relationships without network access or credentials.

Evidence:

DEP-008 - Dependabot updates native pip-compile inputs

Contract: Dependabot MUST treat the requirements inputs as its pip manifests and update each matching generated lock, with pyproject.toml excluded from its pip manifests. Python and GitHub Actions updates MUST remain grouped per ecosystem. A Dependabot update MUST pass the same drift, platform, audit, and snapshot gates as a manual update.

Evidence:

DEP-009 - Checkout environments are private to one host and user

Contract: Every Make environment MUST live under .venvs/<key>/, where the key is an application-specific HMAC of the validated OS machine identity and the local user: /etc/machine-id and the UID on Linux, the registry MachineGuid and the user name on Windows. The raw machine identity MUST NOT be printed. A missing or invalid identity MUST stop Make without a shared fallback. make clean MUST remove only the current host's environments and MUST leave other hosts' and legacy root-level environments untouched.

Evidence: