Verifying release signatures¶
Every Fathom release artifact from 0.5.0 onward is signed with minisign (detached Ed25519) and attached to its GitHub Release. This how-to shows you how to install minisign, verify a downloaded wheel or sdist, and understand the custody, rotation, and revocation policy for the signing key.
Releases before 0.5.0 are unsigned. Signing was introduced with the 0.4.0
tree, which reached PyPI as 0.5.0. The five earlier PyPI releases — 0.1.0,
0.2.0, 0.3.0, 0.3.1 and 0.3.2 — have no .minisig, and the GitHub releases for
0.3.0, 0.3.1, 0.3.3 and 0.4.0 carry no assets at all. There is nothing to
verify for those versions, and no signature will be published retroactively:
back-signing an old artifact today would assert a custody chain that did not
exist when it was built. Use 0.5.0 or later if you need a verifiable artifact.
What is signed, and how¶
- Artifacts: every
fathom_rules-*.whlandfathom_rules-*.tar.gzfrom 0.5.0 onward.pypi-publish.ymlfails the release if any artifact indist/reaches the publish step without a sibling.minisig. - Algorithm: Ed25519 via minisign's standard
.minisigformat — detached signature, one file per artifact, binary-safe. - Where signatures appear:
- Alongside each wheel / sdist as
<artifact>.minisigon the GitHub Release page. - In the
dist/directory produced byscripts/sign_release.shduring thepypi-publishworkflow. - Pubkey: published at
docs/reference/release-signing-pubkey.minisigand embedded in the Fathom wheel atfathom/_data/release_pubkey.minisignso thatfathom verify-artifactworks offline.
A .minisig file is a small text blob containing an Ed25519 signature
plus a trusted comment. It is not a bundle — the artifact and its
.minisig travel together but remain separate files.
Installing minisign¶
Pick the instruction that matches your platform. All of them give you a
minisign binary on your PATH.
- macOS (Homebrew):
- Linux (Debian, Ubuntu):
On Fedora / RHEL: sudo dnf install minisign. On Arch: sudo pacman
-S minisign.
- Windows: download a pre-built binary from the upstream release
page at
https://github.com/jedisct1/minisign/releasesand place it somewhere onPATH. Alternatively, use WSL and follow the Linux instructions above.
Confirm the install:
Verifying a downloaded artifact¶
You have two equivalent paths. Use the first if you already have Fathom
installed; use the second if you only have minisign and the public
key file.
Option A — fathom verify-artifact (embedded pubkey)¶
The CLI carries the release pubkey inside the wheel, so once you have any recent Fathom version installed you can verify later downloads offline:
If <artifact>.minisig lives next to the artifact, the CLI picks it up
automatically. Override either side with --sig <path> or --pubkey
<path> when auditing a specific file. Exit code 0 means the
signature verified; non-zero means the verification failed or the
inputs were malformed — re-download the artifact before trusting it.
Option B — raw minisign¶
No Fathom install needed. Download the artifact, its .minisig, and
the pubkey file from
docs/reference/release-signing-pubkey.minisig,
then:
minisign looks for <artifact>.minisig by default. Pass -x <path>
to point at a signature that lives elsewhere. A Signature and comment
signature verified line means the artifact is authentic.
The pubkey's first line is also pasted into every GitHub Release body, so you can cross-check the key you fetched from the repository against the one on the release page.
M-of-N custody policy¶
The release private key is never held in a single place. Two named custodians each hold one half of the operational state, and both must agree out-of-band before a release tag is pushed.
MINISIGN_KEY_PRIMARY— GitHub Actions secret, held by custodian A. Loaded intoscripts/sign_release.shduring thepypi-publishworkflow.MINISIGN_KEY_SECONDARY— offline backup of the same keypair, held by custodian B. Used only for rotation, recovery, and the custody handshake described below.- Both custodians confirm the target tag, commit SHA, and intended version via a signed email or Signal message before custodian A authorises the tag push that triggers signing. No single custodian can ship a release on their own, because the handshake is the authorisation step — not merely a courtesy.
The policy exists so that a compromise of a single machine, inbox, or GitHub token cannot produce a valid Fathom release.
Rotation cadence¶
- Scheduled: rotate the keypair annually. Track the next rotation date in the repository's release runbook.
- On compromise: rotate immediately if either custodian suspects
their copy of the key has been exposed, if a custodian's workstation
is lost or stolen, or if
MINISIGN_KEY_PRIMARYis ever printed to logs.
Rotation procedure¶
- Both custodians meet out-of-band and generate a new keypair with
minisign -G. - Update
docs/reference/release-signing-pubkey.minisigandsrc/fathom/_data/release_pubkey.minisignwith the new public key, in a single commit. - Distribute the new private key: update the
MINISIGN_KEY_PRIMARYGitHub Actions secret; custodian B stores the new offline backup. - Publish a dedicated release note flagging the rotation, including the new key ID and the date from which signatures use it.
- Retire the previous private-key material (securely erase offline copies, delete the old GitHub secret).
Revocation¶
minisign has no CRL or OCSP equivalent — trust in a key is defined by the key file you hold. To revoke a compromised key:
- Follow the rotation procedure above, treating it as an emergency.
- Issue a release note that explicitly invalidates every artifact signed by the previous key and lists which published versions are affected.
- Recommend that users re-fetch and re-verify any still-in-use artifacts against the new pubkey before continuing to rely on them.
Users who pin the pubkey (for example by vendoring
release-signing-pubkey.minisig) should update their pinned copy from
the new release. The embedded pubkey in fathom/_data/ updates
automatically once users install a release signed under the new key.