Skip to content

v1.0.0 — signed releases, and a pipeline that refuses to publish anything else

Choose a tag to compare

@spilloid spilloid released this 19 Sep 23:41
· 59 commits to main since this release
261a109

The Windows binaries are Authenticode-signed. spoolsmith.exe and
spoolsmith-gui.exe are signed with Azure Artifact Signing,
so Windows shows a named publisher rather than an unknown one on a tool that
asks for Administrator rights and writes to the driver store. That gap was the
uncomfortable one: SpoolSmith's own trust model already requires an Authenticode
check on the vendor driver payloads it stages, and until now it held its own
executables to a lower standard than it held its inputs.

The release pipeline fails closed. Signing is not a step that can silently
be skipped. The release workflow aborts before building if signing is
unconfigured, and fails the release if a binary comes back unsigned,
untimestamped, or signed by an unexpected certificate profile. There is no path
through it that publishes an unsigned artifact.

You can check what you downloaded without installing anything.
scripts/verify-signature.ps1 deliberately uses Get-AuthenticodeSignature
rather than signtool verify — SignTool ships with the Windows SDK and is not
present on a stock Windows 11 machine, which this project documented as a
problem with its own verification guidance and then fixed here:

Get-AuthenticodeSignature .\spoolsmith.exe | Format-List Status, SignerCertificate

The ZIP is still published with its SHA-256 sidecar, and that hash now covers
the signed archive — the binaries are signed before packaging, not after, so
the signature is inside the artifact the hash describes.

Signing does not depend on the pipeline. scripts/build-release.ps1 -Sign
performs the same signing on a Windows machine by hand, keeping this project's
rule that a release must be reproducible without trusting CI.

One detail worth knowing, because it fails quietly if you get it wrong: Artifact
Signing certificates are valid for three days. The RFC 3161 countersignature is
what keeps a release verifiable afterwards, so an untimestamped build looks
perfect on release day and starts failing on users' machines about three days
later. Both the workflow and the local script timestamp explicitly, and
verification treats a missing timestamp as a hard failure rather than a warning.

Setup, troubleshooting and the full runbook are in
docs/code-signing.md.

SpoolSmith has an icon. Both executables now carry the product icon — an
anvil coming down on a printer — so Explorer, the taskbar, Alt+Tab and every
window title bar show it instead of a generic application icon, and the
product site has a favicon for the first time. It is embedded in the
executables, so it cannot be separated from them when a release is copied or
renamed.

Why 1.0.0

No commands, options or behavior changed since v0.7.4; the icon is the only
change a user can see in the app. This release is about distribution:
continuously delivered, signed builds that a Windows admin can verify before
running them with Administrator rights. For a tool whose entire argument is
"review before you change anything," being unverifiable itself was the last
thing standing between v0.x and calling it 1.0.

Verified: go vet and the full go test ./... suite clean. The signing
pipeline signed both executables in GitHub Actions before this release, and the
signed files were downloaded and checked on a separate Windows machine: valid
signature issued to Joseph Spillers, with a timestamp countersignature.
The pipeline was also confirmed to refuse unsigned binaries. The published
assets are re-verified after upload, since CI checks what it built and users get
what was uploaded.