Skip to content

Report the version, and attest the release binary - #9

Merged
edgecasehuman merged 2 commits into
mainfrom
report-the-version-and-attest-the-release
Aug 25, 2026
Merged

edgecasehuman merged 2 commits into
mainfrom
report-the-version-and-attest-the-release

Conversation

@edgecasehuman

Copy link
Copy Markdown
Owner

What this changes

ProcDrift can now say which build it is. CARGO_PKG_VERSION appeared
nowhere in the source — the version existed only in the Windows file properties
winresource stamps — and every argument except the internal
--replace-instance fell through to the unknown-argument branch, so
ProcDrift --version answered "unknown internal argument: --version" in an
error dialog. For a tool whose release notes ask you to match a SHA-256 before
trusting the binary, that is the wrong end of the bargain.

--version, -v, --help, -h and /? are now answered, and the window
title carries the version so a screenshot identifies the build too. The answers
arrive as a dialog because this is a windows-subsystem binary: it is never
attached to the console that launched it, so anything printed would go nowhere.

Parsing stays strict — --replace-instance makes this process wait on a PID
another process named, so an argument list that is not exactly understood is
refused rather than guessed at. --version extra is still an error, and so is
a trailing argument after the PID, which no test previously covered.

Also: the release binary carries a provenance attestation, and release
notes come from a new CHANGELOG.md. v1.0.1's notes were written by hand
afterwards with gh release edit, because the workflow produced only the hash
and the unsigned-binary warning — the reason to upgrade was the whole point of
that page and the one part the release could not produce. A tag whose version
has no changelog section now fails the run rather than publishing an empty page.

The bug template asked for "1.0.0, or the commit SHA", a placeholder that goes
stale every release; it now asks for what --version reports. The README
documents installing from crates.io, including what differs about a locally
compiled binary: no mark-of-the-web, so no SmartScreen notice, but it embeds
your own build paths and should not be redistributed.

Scope

  • Adds no network access, background persistence, or periodic file write
  • Adds no dependency
  • Keeps blocking work off the UI thread — both answers return before the
    window is created, and neither reaches the message loop
  • Phrases anything user-visible as an observation, not a verdict

The attestation step adds id-token: write and attestations: write to the
release job. Both are short-lived OIDC tokens minted per run, not stored
secrets.

Checks

  • cargo fmt --all -- --check
  • cargo clippy --locked --all-targets -- -D warnings
  • cargo test --locked — 37 passing, up from 34
  • A test fails without this change, or the change is genuinely untestable

The three new tests cover every accepted spelling, that the reported version is
the compiled-in one, that no argument still opens the window, and that strict
parsing survived. Separately, the release workflow's own note-extraction script
was executed — read out of the YAML rather than retyped — against the real
changelog, for both released versions and for a version that does not exist,
which must fail the run.

Unproven: the attestation step only runs on a tag, so it has never executed.

Unsafe code

None added.

CARGO_PKG_VERSION appeared nowhere in the source. The version existed only
in the Windows file properties winresource stamps into the executable, so
the running program could not say which build it was -- not in the window,
not on the command line, nowhere a person could see it.

Worse, asking produced an error. Every argument except the internal
--replace-instance fell through to the unknown-argument branch, so
`ProcDrift --version` answered "unknown internal argument: --version" in an
error dialog. For a tool whose release notes ask you to match a SHA-256
before trusting the binary, being unable to state its own version is the
wrong end of that bargain.

--version, -v, --help, -h and /? are now answered. In a dialog, because
this is a windows-subsystem binary: it is never attached to the console
that launched it, so anything printed would go nowhere, and a dialog is the
only channel that reaches the person who typed the argument. The window
title carries the version as well, so a screenshot identifies the build as
precisely as the command line does.

Parsing stays strict, because --replace-instance makes this process wait on
a PID another process named, and an argument list that is not exactly
understood should be refused rather than guessed at. `--version extra` is
still an error, and so is a trailing argument after the --replace-instance
PID -- which the previous test did not cover.

Two documentation consequences. The bug report template asked for "1.0.0,
or the commit SHA if built from source", a placeholder that goes stale at
every release; it now asks for the line --version reports. And the README
documents installing from crates.io, where this crate has been since 1.0.1,
including what differs about a binary compiled locally: no mark-of-the-web,
so no SmartScreen notice, but it embeds your own build paths and should not
be redistributed.

34 tests to 37.
ProcDrift ships one unsigned executable that SmartScreen will warn on, and
its only integrity check is a SHA-256 written into the release notes by the
same workflow that built it. That hash says the file has not changed since
it was hashed. It cannot say what produced it, because the thing publishing
the hash is the thing being vouched for.

attest-build-provenance binds the binary to this workflow, this commit, and
this repository, in a store the release page cannot rewrite, checkable with
`gh attestation verify ProcDrift.exe --repo edgecasehuman/procdrift`. It
matters more here than it would elsewhere: the binary is unsigned, so a
downloader has nothing else to go on. It runs before the release exists, so
a failure leaves the tag re-runnable rather than leaving an unattested
asset published.

v1.0.1's notes were written by hand afterwards with `gh release edit`,
splicing the generated hash line through byte for byte, because the
workflow produced only that hash and the unsigned-binary warning. The
reason to upgrade was the whole point of that page and it was the one part
the release could not produce. Notes now come from a CHANGELOG section
matching the tag, with the hash and the verification command appended. A
tag whose version has no section fails the run rather than publishing an
empty page.

The changelog is reconstructed from the tags and the commits rather than
from memory: 1.0.0 as released, 1.0.1's baseline-adoption fix as the reason
that release existed, and the post-tag CodeQL and approval-gate work under
Unreleased.

Verified by executing the workflow's own run: script -- read out of the
YAML rather than retyped -- against the real changelog, for both released
versions and for a version that does not exist, which must fail the run.
@edgecasehuman
edgecasehuman merged commit bdfe36a into main Aug 25, 2026
5 checks passed
@edgecasehuman
edgecasehuman deleted the report-the-version-and-attest-the-release branch August 25, 2026 00:02
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