Skip to content

CLAUDE.md: retain the PyPI break-glass token; bar agents from deleting credentials - #76

Merged
binlecode merged 1 commit into
mainfrom
docs-pypi-token-break-glass
Aug 23, 2026
Merged

binlecode merged 1 commit into
mainfrom
docs-pypi-token-break-glass

Conversation

@binlecode

Copy link
Copy Markdown
Owner

Docs only — no code, CLI, or test change. Lands under CHANGELOG.md [Unreleased]; per When to cut a release this is repo-internal churn and ships with the next user-visible release, not as a release of its own.

Why

The PyPI hygiene note said to delete the project-scoped token once OIDC Trusted Publishing was confirmed on a release. Two problems:

  1. It contradicted the failure playbook two paragraphs above it, which names the token-driven Flow B as the recovery path when publish-pypi fails on an OIDC / trusted-publisher error. Obeying the hygiene rule removed the fallback exactly when a broken release would need it.
  2. It failed silently. ~/.zshrc builds TWINE_PASSWORD with $(cat … 2>/dev/null), so deleting the file yields an empty password — a confusing PyPI auth error rather than an obvious missing-file one.

This is not hypothetical: immediately after the v1.9.11 release published cleanly over OIDC, an agent (me) read that note as an action item and proposed deleting the live break-glass token. The maintainer declined. The note is the root cause, so it is retired.

Changes

  • Hygiene note reversed — retain the token, refresh on expiry, revoke only on leak/replacement. Also warns that ~/.zshrc names pypi-org-api-token-binlecode literally, not by glob, so adding a dated -exp-<month>-<year> suffix requires editing the .zshrc path in the same commit or the export breaks silently.
  • Break-glass documented as env-sourced — TWINE_USERNAME / TWINE_PASSWORD are pre-exported, so twine upload needs no flags and nobody hunts for a token file. Presence is checked with env | grep -c TWINE_PASSWORD, never by printing the value.
  • New hard rule under Security & Configuration Tips: never delete, revoke, or rotate a credential, or propose it as cleanup — credential lifecycle is the maintainer's call. Plus secret-handling rules (never print a value; assert on presence, not content; filenames and env-var names are not secrets, their values are).
  • Drive-by dedupe of the two near-identical "avoid persistent privileged processes" bullets in that section.

Validation

.venv/bin/ruff check .          # All checks passed
.venv/bin/ruff format --check . # 60 files already formatted

Diff leak-checked for token material (pypi-Ag… / AgEIcHlwaS5vcmc): 0 matches. The doc references the credential's filename and env-var names only — never a value.

🤖 Generated with Claude Code

…g credentials

The PyPI hygiene note told the reader to delete the project-scoped token
once OIDC Trusted Publishing was confirmed on a release. That contradicted
the failure playbook two paragraphs above it, which names the token-driven
Flow B as the recovery path when publish-pypi fails on an OIDC /
trusted-publisher error -- so obeying the hygiene rule removed the fallback
exactly when a broken release would need it, and forced a pypi.org
round-trip at the worst possible moment.

It was also a silent failure. ~/.zshrc builds TWINE_PASSWORD with
$(cat ... 2>/dev/null), so deleting the file yields an empty password and a
confusing PyPI auth error rather than an obvious missing-file one.

Three changes:

- Reverse the hygiene note: retain the token, refresh it on expiry, revoke
  only on leak or replacement. Warn that ~/.zshrc names the file literally
  (not by glob), so a rename must edit the .zshrc path in the same commit.
- Document that the break-glass credential comes from the system
  environment (TWINE_USERNAME / TWINE_PASSWORD, pre-exported), so twine
  needs no flags and nobody hunts for a token file.
- Add a hard rule under Security & Configuration Tips against deleting,
  revoking, or rotating any credential, or proposing it as cleanup, plus
  secret-handling rules: never print a value, assert on presence rather
  than content, and treat filenames/env-var names as non-secret.

Also dedupe the two near-identical "avoid persistent privileged processes"
bullets in that section.

Docs only -- no code, CLI, or test change. Lands under [Unreleased].

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@binlecode
binlecode merged commit 33f56dc into main Aug 23, 2026
5 checks passed
@binlecode
binlecode deleted the docs-pypi-token-break-glass branch August 23, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant