wharfy 0.22.0 — what you ship carries provenance
Everything you ship is attested
release and publish running in GitHub Actions now attach build provenance to the sha256
of each thing that reaches a user — not only build artifacts. That includes install.sh,
the script users pipe into their shell, and latest.json, the file their update check
follows.
| What is attested | How a user checks it |
|---|---|
| archives / packages / bundles | gh attestation verify <file> --repo acme/demo |
install.sh / install.ps1 / latest.json |
same command — provenance is bound to the shipped bytes |
| the container image | gh attestation verify oci://ghcr.io/acme/demo:1.2.0 --repo acme/demo |
The host does not matter
Provenance is looked up by digest, not by where the file came from. If a tap, a scoop bucket, the AUR or your apt/rpm repo serves the same file, a user who got it there verifies it with the same command.
The image is attested during publish
An image can only be named by its manifest digest, and that digest does not exist until the
registry has accepted the push. So the image is attested in publish, not in release.
No signing key, only permissions
Nothing to generate, store or rotate. The workflow needs these:
permissions:
contents: write
packages: write
id-token: write # signs the provenance (the identity Actions hands the workflow)
attestations: write # the attestation is stored on the repository
Nothing is attested from a laptop, and status says so instead of leaving you to find out
later.
$ wharfy status
demo
attest: no OIDC token available — provenance is signed with the identity GitHub Actions hands the workflow, so nothing is attested from a laptop (in CI: permissions: id-token: write)
verify checks the provenance as a consumer
Attaching provenance is not proof that it works. A wrong signature format, an entry missing
from the transparency log, or only some artifacts being covered all look fine from the
publisher’s side. verify looks it up again the way a user would, and fails if it does not
verify.
$ wharfy verify --version 1.2.0
✓ verified releases, script, attest
attest: all 13 shipped artifacts on v1.2.0 carry verifiable provenance from this repository's workflow (signed, logged in rekor, and bound to the bytes users receive)
$ wharfy verify --version 1.2.0
✗ failed attest
! attest_unverified: attest: none of the 13 shipped artifacts on v1.2.0 carry build provenance — nothing proves they came from this repository's workflow; release attaches it when it runs in github actions with permissions: id-token: write / attestations: write
Asset contents are checked without downloading them
The default verify only checked that an asset with that name exists — contents were
checked only with --install. A truncated upload, or an asset swapped after the fact,
slipped through because the name was there. GitHub reports a digest per asset, so it is
compared against what the checksums manifest declares, on every verify.
Before
$ wharfy verify --version 1.2.0
✓ verified releases
releases 1.2.0: 13 assets present; the assets were not downloaded, so their contents are unchecked
After
$ wharfy verify --version 1.2.0
✓ verified releases
releases 1.2.0: 13 assets present, and all 13 of them hash to what the checksums manifest says (compared against the digests github reports, without downloading them)
--install still downloads for real — it looks at the bytes a user actually receives. A
release with nothing to compare against, a BYO path with no checksums manifest, still
stops at probe.
Fixed
- The managed block in AGENTS.md / CLAUDE.md could be stale while
statusstayed green — wharfy can change the block’s text, but copies already written into a repo do not follow.statusnow compares the content and reportsinit_stale;wharfy init --yesrefreshes it in place. wharfy agent’s per-command notes only appeared in--json— notes are the premises you break things by not knowing, and anyone reading the plain-text output never saw them. They are in the human output now.
Getting it
brew upgrade wharfy / scoop update wharfy / go install github.com/ShiroDoromoto/wharfy/cmd/wharfy@latest. On Linux, from the apt / yum repo.