ADR-0009 — PyPI advisory lookup for local dependency versions

Status: proposed

Date: 2026-08-26

Owners: ZeroProofML maintainers

Supersedes / superseded by: none

Context

The release environment installs PyTorch's CPU wheel, whose PEP 440 version contains a local build suffix such as 2.13.0+cpu. The PyPI JSON advisory API has a record for the public release 2.13.0, but not for the local wheel identifier. Consequently, pip-audit --strict stops dependency collection and does not emit its JSON report. Disabling strict mode would silently skip that dependency and weaken the release gate.

Decision

Release auditing records every installed distribution in a machine-readable inventory. The qualified ZeroProofML wheel is bound separately by filename, version, and SHA-256 digest; every other installed distribution becomes a pinned pip-audit input. An installed PEP 440 local version is retained in the inventory while its advisory lookup uses Version.public, which removes only the local build label. The validator requires the audit report to contain the exact projected inventory and records every projection in policy provenance.

The audit continues to use --strict and the live PyPI Advisory Database. A skipped dependency, missing report entry, version mismatch, malformed report, or failed advisory lookup remains a release failure.

Consequences

CPU or platform-specific local wheel labels no longer make the audit unexecutable. Findings apply to the corresponding public source release and are evaluated through the existing time-bounded exception policy. The inventory makes the distinction between installed and queried versions explicit, but it does not establish that a downstream local build is bitwise identical to PyPI's distribution.

Alternatives considered

  • Removing --strict would permit silent omissions and was rejected.
  • Ignoring PyTorch would leave a deployment-critical dependency unaudited.
  • Switching only this job to OSV would change the release advisory authority and make its evidence inconsistent with the documented PyPI policy.
  • Querying 2.13.0+cpu directly cannot work because PyPI has no distribution record for that identifier.

Verification and rollout

Regression tests cover local-to-public projection, exact project-wheel identity, duplicate distributions, the current pip-audit JSON envelope, and report/inventory completeness. The tag-only security job publishes the pinned requirements, installed inventory, raw audit report, and validated policy record as qualification artifacts.