Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ updates:
# pyproject.toml + uv.lock and REGENERATES uv.lock IN its PRs (version updates GA 2025-03,
# security updates GA 2025-12) — the old "pip" ecosystem updated requirements/pyproject but NOT
# uv.lock. It still does not re-derive the EXPORTED locks (requirements.lock + docker/locks/* +
# constraints.lock + ci/locks/* — SIX artifacts), which the DEP-1 gate in security.yml byte-diffs;
# constraints.lock + ci/locks/* — SEVEN artifacts, since a9354808e added ci/locks/release-tools.lock),
# which the DEP-1 gate in security.yml byte-diffs;
# .github/workflows/dependabot-lock-resync.yml re-exports those on the Dependabot branch so the
# gate stays green.
#
Expand Down Expand Up @@ -56,11 +57,40 @@ updates:
# `versioning-strategy: lockfile-only`. Both would freeze the hash-pinned CI toolchain, which ADR
# 0034 §3 wants moving THROUGH this machinery — a pinned toolchain outside it rots into
# "pinned, stale, unpatched — worse posture than floating".
#
# ONE CARVE-OUT, and it is the `sigstore` entry below (BACKLOG #332). The rule above is about
# versions NOBODY HAS DECIDED: it keeps the toolchain moving because leaving a pin unattended is
# how it rots. `sigstore`'s version is not unattended — it is an OWNER RULING, given 2026-08-22
# and re-affirmed 2026-09-03, pinning 4.4.0 and naming 4.5.0 as the version not to take. So the
# policy's own reason does not reach it, and the failure mode inverts: a routine weekly PR here
# does not keep a neglected pin fresh, it re-proposes a version the owner has twice declined,
# and merging it silently reverses a decision. That is not hypothetical -- it already happened
# once, in a9354808e, which shipped 4.5.0 two days AFTER its own author had retracted the
# argument for it (PR 531, comment of 2026-08-27T02:45:36Z). Lift this entry when the owner
# rules differently in writing, and not before.
#
# THE STALENESS HALF OF THE RULE STILL BINDS, and is honoured by a different mechanism rather
# than waived. The trade-off note above applies unchanged (an `ignore` suppresses the SECURITY
# track for the named range too), so this entry is only acceptable while something else can see
# an advisory in the pinned closure. Until this commit NOTHING could: security.yml's audit step
# covered `requirements.lock`, `ci-scanners.lock` and `ci-quality.lock` but NOT
# `ci/locks/release-tools.lock`, which a9354808e added to the export and byte-diff set without
# adding to the audit set. That gap is closed in the same commit as this entry, so the
# annotated-types / ruff bargain — detection untouched, a withheld fix reds a required gate
# within ~24h, a human lifts the entry — now holds here too. If that audit line is ever removed,
# REMOVE THIS ENTRY WITH IT.
#
# SCOPED TO `>=4.5.0`, NOT TO THE PACKAGE. sigstore 4.x has shipped zero patch releases (4.0.0,
# 4.1.0, 4.2.0, 4.3.0, 4.4.0, 4.5.0; measured against PyPI 2026-09-03), but the 3.x series did
# ship them (3.5.1, 3.6.7), so a 4.4.1 is possible. This range leaves the 4.4.x patch track open
# and blocks only the minor bump the ruling declined.
ignore:
- dependency-name: "annotated-types"
versions: [">=0.8.0"]
- dependency-name: "ruff"
versions: [">=0.16.0"]
- dependency-name: "sigstore"
versions: [">=4.5.0"]
groups:
# Version-update grouping (applies-to defaults to version-updates).
python-deps:
Expand Down
24 changes: 14 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -375,19 +375,23 @@ jobs:
# resolved at signing time.
# 2. NO Dependabot ecosystem parses an inline `pip install X==Y` inside a workflow `run:`
# block (.github/dependabot.yml registers uv, github-actions, npm). So the pin had no
# updater, no trigger and no owner its own comment said "re-evaluate once it has aged
# past the window" and nothing would ever have prompted that. It was 19 days overdue when
# this landed. tests/test_ci_venv_pinning.py words the class: "a stale pin rots invisibly
# and a DELETED pin is invisible twice over."
# updater, no trigger and no owner: its own comment said "re-evaluate once it has aged
# past the window" and nothing would ever have prompted that.
# tests/test_ci_venv_pinning.py words the class: "a stale pin rots invisibly and a
# DELETED pin is invisible twice over."
# Routing it through `uv.lock` fixes both: the transitives are hash-pinned, and the group is
# under the `uv` ecosystem Dependabot already watches.
#
# ON THE VERSION: the lock resolves sigstore 4.5.0, which the old inline pin deliberately
# avoided. That choice was CORRECT when made — dependabot.yml sets a 5-day supply-chain
# cooldown and 4.5.0 was then <48h old, so pinning the SIGNING toolchain to a fresher artifact
# than the repo's own update policy allows would have inverted that policy at its
# highest-privilege point. MEASURED: 4.5.0 published 2026-07-28T07:34:00Z, so the window
# closed 2026-08-02. The objection is SPENT, not overridden.
# ON THE VERSION: the lock pins sigstore 4.4.0 BY OWNER RULING -- given 2026-08-22, and
# re-affirmed 2026-09-03 with the full history in hand. "NOT 4.5.0." The rationale lives
# ONCE, at the `release-tools` group in pyproject.toml; BACKLOG #332 carries the record.
# The one thing worth repeating HERE, because this is where the thought occurs to a reader
# standing at the install: DO NOT RE-DERIVE THE COOLDOWN ARGUMENT. dependabot.yml's 5-day
# window closed 2026-08-02 and BOTH rulings postdate it, so "the objection is spent" is not
# news to this pin -- it is what the rulings were made in spite of. That argument has been
# published and RETRACTED BY ITS OWN AUTHOR once already (PR 531, 2026-08-27), and shipped
# anyway two days later in a9354808e before being corrected back. dependabot.yml now
# carries a matching `ignore` entry so a bot cannot repeat it.
python -m pip install --require-hashes -r ci/locks/release-tools.lock
# Sign the wheel + sdist AND the SBOM + VEX, so an operator can verify the provenance of the
# bill-of-materials and the exploitability assessment too — not just the code artifacts (ADR 0149).
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@ jobs:
# the advisory half not block, move the ci-quality line alone to its own step.
pip-audit -r ci/locks/ci-scanners.lock --desc
pip-audit -r ci/locks/ci-quality.lock --desc
# THE SIGNING TOOLCHAIN, and it is the one that most needs this (BACKLOG #332). a9354808e
# added ci/locks/release-tools.lock to the export set and the byte-diff gate above but NOT
# here, so from 2026-08-29 until this line landed the release signing closure was the only
# committed lock nothing audited -- hash-pinned, therefore sticky, therefore exactly the
# "pinned, stale, unpatched is worse than floating" case the two lines above exist to stop.
# It is also load-bearing for .github/dependabot.yml's `sigstore` ignore entry: that entry
# suppresses the security track for >=4.5.0, and is only acceptable while this audit can
# still see an advisory in the pinned closure. REMOVE THIS LINE AND YOU MUST REMOVE THAT
# ENTRY -- the comment there says so from the other side.
#
# Same REQUIRED-context consequence as the two above, and a better-earned one: a CVE in
# sigstore's closure reds the merge gate. That closure signs the wheel, the sdist, the SBOM
# and the VEX with the job's OIDC identity, so blocking is the wanted behaviour, not a cost
# reluctantly accepted for an advisory tool. `--ignore-vuln <ID>` remains the escape hatch.
pip-audit -r ci/locks/release-tools.lock --desc
# ANTI-SLOPSQUAT. Deliberately a STEP in this already-REQUIRED job rather than a new context: it
# blocks today with no branch-protection change, the same reasoning as the ledger-gate backstop
# in ci.yml. (A hard-failing job that is NOT a required context does not stop auto-merge — it
Expand Down
6 changes: 3 additions & 3 deletions ci/locks/release-tools.lock
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,9 @@ securesystemslib==1.4.0 \
--hash=sha256:a0743a3d978cf26e98a70a57e3fbd5a18e0a74c20cabe615f6a55b02ef0272b3 \
--hash=sha256:faea87be0f9c4b4277a5fa1b54bf9bfd807be9a94ab11be6c557dc8b75c43285
# via tuf
sigstore==4.5.0 \
--hash=sha256:020d3e07f622b2916bf453e66ff6ff0711e1fdc5ab69e8bd8902f71d9fcb316f \
--hash=sha256:f045b207f2e12605cf775ec38e89c5eda625d71ffa7830477db65e47ec2bc8b2
sigstore==4.4.0 \
--hash=sha256:20ffe791c1fa33ce62148c0291b46280d29c1910964d9afac419e9b1a8afc56b \
--hash=sha256:80c36d08b02479e2a282d0bea93de68fe0d43a93b0d58e4d9ac6bb9f8425957c
sigstore-models==0.0.6 \
--hash=sha256:5201a68f4d7d0f8bec1e2f4378eb646b084c52609a4e31db8c385095fff68b2e \
--hash=sha256:c766c09470c2a7e8a4a333c893f07e2001c56a3ff1757b1a246119f53169a849
Expand Down
Loading
Loading