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:
test_direct_dependencies_are_exact_and_scoped-tests/unit/test_dependency_policy.py::test_direct_dependencies_are_exact_and_scopedtest_rejects_dependency_versions_in_project_metadata-tests/unit/test_dependency_snapshot.py::test_rejects_dependency_versions_in_project_metadatatest_rejects_included_files_and_options_in_independent_inputs-tests/unit/test_dependency_snapshot.py::test_rejects_included_files_and_options_in_independent_inputs
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:
test_all_committed_locks_are_pip_compile_hash_locks-tests/unit/test_dependency_policy.py::test_all_committed_locks_are_pip_compile_hash_lockstest_rejects_hashless_lock_entry-tests/unit/test_dependency_snapshot.py::test_rejects_hashless_lock_entry
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:
test_make_installs_locks_with_hashes_and_checks_drift-tests/unit/test_dependency_policy.py::test_make_installs_locks_with_hashes_and_checks_drift
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:
test_ci_preserves_project_specific_quality_and_platform_gates-tests/unit/test_ci_policy.py::test_ci_preserves_project_specific_quality_and_platform_gatestest_direct_dependencies_are_exact_and_scoped-tests/unit/test_dependency_policy.py::test_direct_dependencies_are_exact_and_scoped
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:
test_make_installs_locks_with_hashes_and_checks_drift-tests/unit/test_dependency_policy.py::test_make_installs_locks_with_hashes_and_checks_drift
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:
test_make_installs_locks_with_hashes_and_checks_drift-tests/unit/test_dependency_policy.py::test_make_installs_locks_with_hashes_and_checks_drifttest_ci_preserves_project_specific_quality_and_platform_gates-tests/unit/test_ci_policy.py::test_ci_preserves_project_specific_quality_and_platform_gates
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:
test_builds_all_exact_lock_manifests-tests/unit/test_dependency_snapshot.py::test_builds_all_exact_lock_manifeststest_snapshot_is_deterministic-tests/unit/test_dependency_snapshot.py::test_snapshot_is_deterministictest_rejects_direct_dependency_missing_from_lock-tests/unit/test_dependency_snapshot.py::test_rejects_direct_dependency_missing_from_locktest_rejects_direct_version_drift-tests/unit/test_dependency_snapshot.py::test_rejects_direct_version_drifttest_rejects_hashless_lock_entry-tests/unit/test_dependency_snapshot.py::test_rejects_hashless_lock_entrytest_rejects_unpinned_direct_dependency-tests/unit/test_dependency_snapshot.py::test_rejects_unpinned_direct_dependency
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:
test_dependabot_updates_python_and_actions_as_groups-tests/unit/test_dependency_policy.py::test_dependabot_updates_python_and_actions_as_groupstest_all_committed_locks_are_pip_compile_hash_locks-tests/unit/test_dependency_policy.py::test_all_committed_locks_are_pip_compile_hash_lockstest_make_installs_locks_with_hashes_and_checks_drift-tests/unit/test_dependency_policy.py::test_make_installs_locks_with_hashes_and_checks_drift
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:
test_environment_key_is_stable_private_and_scoped-tests/unit/test_venv_root.py::test_environment_key_is_stable_private_and_scopedtest_invalid_linux_identity_has_no_shared_fallback-tests/unit/test_venv_root.py::test_invalid_linux_identity_has_no_shared_fallbacktest_windows_machine_guid_is_validated_case_insensitively-tests/unit/test_venv_root.py::test_windows_machine_guid_is_validated_case_insensitivelytest_reads_the_windows_machine_guid-tests/unit/test_venv_root.py::test_reads_the_windows_machine_guidtest_user_identity_uses_uid_or_casefolded_windows_user-tests/unit/test_venv_root.py::test_user_identity_uses_uid_or_casefolded_windows_usertest_selector_reports_failure_without_identity_or_path_leaks-tests/unit/test_venv_root.py::test_selector_reports_failure_without_identity_or_path_leakstest_make_selects_only_this_host_environments_and_fails_closed-tests/unit/test_venv_root.py::test_make_selects_only_this_host_environments_and_fails_closedtest_make_clean_preserves_other_host_and_legacy_environments-tests/unit/test_venv_root.py::test_make_clean_preserves_other_host_and_legacy_environments