Skip to content

ci: PyPI release workflow (Trusted Publishing) - #2

Merged
MrPredic merged 1 commit into
mainfrom
ci/pypi-trusted-publishing
Aug 5, 2026
Merged

MrPredic merged 1 commit into
mainfrom
ci/pypi-trusted-publishing

Conversation

@MrPredic

@MrPredic MrPredic commented Aug 5, 2026 •

Copy link
Copy Markdown
Owner

Package builds clean and passes twine check, but the name is unclaimed on PyPI and there was no release job. Adds a tag-triggered publish over OIDC — no API token stored anywhere.

Needs one manual step before the first tag: add the pending publisher on PyPI (project name, owner MrPredic, workflow release.yml, environment pypi).

The package builds and passes `twine check`, but nothing ever pushed it: the
name is unclaimed on PyPI and the README had to send readers to a git URL.
This adds the tag-triggered release job. It uses OIDC rather than an API
token, so there is no publishing secret in the repo to leak.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VWTgH2xDR5xafCX83YvQQV
@MrPredic
MrPredic merged commit 482741d into main Aug 5, 2026
@MrPredic
MrPredic deleted the ci/pypi-trusted-publishing branch August 5, 2026 14:56
MrPredic added a commit that referenced this pull request Aug 5, 2026
…ttest

Two post-review hardening fixes that close the gap between the marketed
USP and what the code delivered.

#1 Signature tamper-evidence (was cryptographically hollow)
- _sign() no longer writes a companion .pub next to the .sig. A pub that
  travels with the signature is no trust anchor: an attacker edits the
  fingerprint, re-signs with their own key, ships their own pub, verify
  passed. Tamper-evidence was effectively 0.
- verify() now checks the signature against a PINNED public key
  (indelible.pub, committed) or one supplied out-of-band via --pubkey.
  A signature with no pinned key is a hard error, never a silent pass.
- init now emits indelible.pub (and re-derives it for pre-existing keys).
- Documented the honest trust model in SECURITY.md / README / llms.txt:
  authenticates origin+integrity relative to a pinned key, not attester
  honesty; cross-party verification must pin the key out-of-band.

#2 Determinism (baseline was maximally noisy)
- New IndelibleConfig.temperature, default 0.0, threaded through all three
  providers (Anthropic/OpenAI-compat temperature, Ollama options.temperature).
  Attestation ran at provider-default temp (~1.0), injecting sampling noise
  into every signal and manufacturing false breaches.
- temperature is part of the canonical config hash (different temp =
  different behavioral baseline).

Also: softened over-reaching EU AI Act claim to "supporting evidence";
documented latency as network-influenced/informational; hand-tuned
tolerances flagged as uncalibrated.

TDD: 17 new tests (tamper-resign attack, wrong-key, missing-anchor,
temperature threading + canonical hash). Full suite 164 passed, ruff +
mypy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MrPredic added a commit that referenced this pull request Aug 5, 2026
The package builds and passes `twine check`, but nothing ever pushed it: the
name is unclaimed on PyPI and the README had to send readers to a git URL.
This adds the tag-triggered release job. It uses OIDC rather than an API
token, so there is no publishing secret in the repo to leak.


Claude-Session: https://claude.ai/code/session_01VWTgH2xDR5xafCX83YvQQV

Co-authored-by: MrPredic <269417388+MrPredic@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
MrPredic added a commit that referenced this pull request Aug 7, 2026
…ttest

Two post-review hardening fixes that close the gap between the marketed
USP and what the code delivered.

#1 Signature tamper-evidence (was cryptographically hollow)
- _sign() no longer writes a companion .pub next to the .sig. A pub that
  travels with the signature is no trust anchor: an attacker edits the
  fingerprint, re-signs with their own key, ships their own pub, verify
  passed. Tamper-evidence was effectively 0.
- verify() now checks the signature against a PINNED public key
  (indelible.pub, committed) or one supplied out-of-band via --pubkey.
  A signature with no pinned key is a hard error, never a silent pass.
- init now emits indelible.pub (and re-derives it for pre-existing keys).
- Documented the honest trust model in SECURITY.md / README / llms.txt:
  authenticates origin+integrity relative to a pinned key, not attester
  honesty; cross-party verification must pin the key out-of-band.

#2 Determinism (baseline was maximally noisy)
- New IndelibleConfig.temperature, default 0.0, threaded through all three
  providers (Anthropic/OpenAI-compat temperature, Ollama options.temperature).
  Attestation ran at provider-default temp (~1.0), injecting sampling noise
  into every signal and manufacturing false breaches.
- temperature is part of the canonical config hash (different temp =
  different behavioral baseline).

Also: softened over-reaching EU AI Act claim to "supporting evidence";
documented latency as network-influenced/informational; hand-tuned
tolerances flagged as uncalibrated.

TDD: 17 new tests (tamper-resign attack, wrong-key, missing-anchor,
temperature threading + canonical hash). Full suite 164 passed, ruff +
mypy clean.
MrPredic added a commit that referenced this pull request Aug 7, 2026
The package builds and passes `twine check`, but nothing ever pushed it: the
name is unclaimed on PyPI and the README had to send readers to a git URL.
This adds the tag-triggered release job. It uses OIDC rather than an API
token, so there is no publishing secret in the repo to leak.
Co-authored-by: MrPredic <269417388+MrPredic@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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