Skip to content

Commit 62678df

Browse files
committed
docs: record pypi publish fallback
1 parent f55fe0d commit 62678df

5 files changed

Lines changed: 37 additions & 22 deletions

File tree

.github/workflows/release-pypi.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
# publishes to PyPI and creates a GitHub release.
66
# - manual dispatch publishes the same locked artifacts to TestPyPI only.
77
#
8-
# Uses PyPI Trusted Publishing (OIDC); no API tokens are stored in repository
9-
# secrets. The PyPI trusted-publisher claim is bound to this workflow path.
8+
# Intended to use PyPI Trusted Publishing (OIDC). If the PyPI
9+
# account-side trusted-publisher mapping is missing, maintainers may
10+
# publish the validated dist/ files with a scoped token and must record
11+
# that fallback in the release tracker and notes.
1012
name: Release PyPI
1113

1214
on:

CHANGELOG.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ No unreleased changes.
1616

1717
### Release Summary
1818

19-
- First Python package release target for GenoLeWM's alpha public surface.
19+
- First Python package release for GenoLeWM's alpha public surface.
2020
- Publishes the v0.2.1 serious-completion artifact chain: stronger
2121
post-v0.2 checkpoint lineage, broader benchmark-suite evidence,
2222
released-artifact planning demo, and generated paper package.
@@ -252,11 +252,15 @@ No unreleased changes.
252252
plumbing evidence only, not a Carbon-backed model result.
253253

254254
- **PyPI release workflow hardening** (issue #100).
255-
- `.github/workflows/release-pypi.yml` is now the trusted-publisher
256-
workflow path for tagged releases.
257-
- Release artifacts build from the committed `uv.lock`, publish to
258-
PyPI via OIDC trusted publishing, and emit GitHub/Sigstore build
259-
provenance with `SHA256SUMS` attached to the GitHub release.
255+
- `.github/workflows/release-pypi.yml` is the intended
256+
trusted-publisher workflow path for tagged releases.
257+
- Release artifacts build from the committed `uv.lock`, run the
258+
package and source-distribution gates, emit GitHub/Sigstore build
259+
provenance, and attach `SHA256SUMS` to the GitHub release.
260+
- The `0.2.1` upload exposed an account-side PyPI trusted-publisher
261+
configuration gap (`invalid-publisher`), so the validated
262+
distributions were published with the maintainer token available to
263+
the release runner and the fallback was recorded in #201.
260264

261265
- **Receipt-verification tutorial notebook** (issue #99).
262266
- `examples/07_verify_receipt.ipynb` verifies a committed
@@ -499,8 +503,9 @@ No unreleased changes.
499503

500504
### Security
501505

502-
- PyPI Trusted Publishing (OIDC) on the release workflow — no
503-
long-lived API tokens are stored in repository secrets.
506+
- PyPI release workflow configured for Trusted Publishing (OIDC);
507+
`0.2.1` was published through a maintainer-token fallback after PyPI
508+
rejected the trusted-publisher claim.
504509
- CodeQL Python analysis on every PR + weekly schedule.
505510

506511
## [0.1.0-draft] — 2026-05-20

docs/release/signing-keys.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,33 @@ themselves are published here when they're issued.
66

77
## Status
88

9-
No signed binaries exist yet. The first package-release target is
10-
`0.2.1`, published through the protected PyPI workflow. This page exists
11-
so [`SECURITY`](../security.md) can reference a stable URL.
9+
No signed binaries exist yet. The first package release is `0.2.1`.
10+
The tag workflow built and validated the release distributions, but PyPI
11+
rejected the trusted-publisher exchange with `invalid-publisher`; the
12+
same validated distributions were then published with a maintainer token
13+
and recorded in the release tracker. This page exists so
14+
[`SECURITY`](../security.md) can reference a stable URL.
1215

1316
## Planned posture
1417

1518
- Maintainer key fingerprints listed here, one per row, with
1619
`[Maintainer name] — [PGP fingerprint] — [valid from] — [revoked at]`.
1720
- Release artifacts on PyPI published via PyPI trusted publishing
18-
(OIDC, no long-lived API tokens).
21+
(OIDC) once the account-side publisher mapping is configured; until
22+
then, any maintainer-token fallback must be recorded in the release
23+
tracker and public release notes.
1924
- Release artifacts on GitHub attached to a signed tag and
2025
Sigstore-backed build provenance.
2126
- Hugging Face Hub model weights signed via the `safetensors`
2227
manifest; the manifest hash is the trust anchor (RFC-0011 §3.7).
2328

2429
## Until then
2530

26-
- PyPI project releases are published from the `Release PyPI` workflow
31+
- PyPI project releases should publish from the `Release PyPI` workflow
2732
at `.github/workflows/release-pypi.yml` through trusted publishing.
2833
Verify the workflow's OIDC claim against the trusted-publisher
29-
configuration before each protected tag.
34+
configuration before each protected tag; if PyPI rejects the claim,
35+
use only a scoped maintainer-token fallback and record the exception.
3036
- The repository's tags are GPG-signed by the project lead. Verify
3137
with `git tag -v vX.Y.Z` after importing the lead's GPG key.
3238
- Release assets should also verify with the GitHub CLI

docs/spec/09-release-and-versioning.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,12 @@ trusted only after their hashes match the fetched manifest.
151151
6. Open a release PR. Require sign-off from a non-author maintainer.
152152
7. Merge to `main`. Tag `v<X>.<Y>.<Z>`.
153153
8. CI builds the PyPI artifacts from `uv.lock`, publishes them through
154-
`.github/workflows/release-pypi.yml` via trusted publishing, and
155-
emits GitHub/Sigstore build provenance. The source distribution must
156-
include the release-critical repo assets used by documented release
157-
gates: `bench/`, `configs/first_experiment/`, `tools/`, `docs/`,
154+
`.github/workflows/release-pypi.yml` via trusted publishing when the
155+
PyPI account-side publisher mapping is configured, and emits
156+
GitHub/Sigstore build provenance. If PyPI rejects the trusted
157+
publisher claim, a scoped maintainer-token fallback is allowed only
158+
when it is recorded in the release tracker and public notes. The source distribution must include the release-critical repo assets
159+
used by documented release gates: `bench/`, `configs/first_experiment/`, `tools/`, `docs/`,
158160
`rfcs/`, `examples/`, README, ROADMAP, and AGENTS.
159161
9. Publish CHANGELOG to the release notes.
160162
10. For paper/demo releases: validate the checked first-experiment
@@ -607,7 +609,7 @@ Revocation-list mechanism is an [open question](#open-questions).
607609

608610
| Channel | Status | Use |
609611
|---------|--------|-----|
610-
| PyPI | 0.2.1 release target | package wheels and sdists through trusted publishing |
612+
| PyPI | 0.2.1 published | package wheels and sdists through trusted publishing or recorded maintainer-token fallback |
611613
| HuggingFace Hub | v0.1 published | model checkpoints and dataset artifacts |
612614
| GitHub releases | v0.1 published | terminal-demo, paper, and publication-evidence assets |
613615
| Homebrew | Planned | post v1 |

tests/lint/test_docs_release_blocker_contract.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ def test_public_docs_do_not_claim_unreleased_package_distribution() -> None:
405405
else:
406406
assert "python -m pip install geno-lewm" in normalized
407407
assert "first PyPI release has not been cut yet" not in normalized
408-
assert "0.2.1 release target" in RELEASE_SPEC.read_text(encoding="utf-8")
408+
assert "0.2.1 published" in RELEASE_SPEC.read_text(encoding="utf-8")
409409

410410

411411
def test_faq_keeps_target_numbers_behind_release_evidence() -> None:

0 commit comments

Comments
 (0)