Skip to content

feat(packaging): wire Windows Authenticode signing, activated by repo secrets (#36, #37) - #480

Open
lmanchu wants to merge 1 commit into
andrewyng:mainfrom
lmanchu:feat/windows-authenticode-pipeline
Open

feat(packaging): wire Windows Authenticode signing, activated by repo secrets (#36, #37)#480
lmanchu wants to merge 1 commit into
andrewyng:mainfrom
lmanchu:feat/windows-authenticode-pipeline

Conversation

@lmanchu

@lmanchu lmanchu commented Aug 9, 2026

Copy link
Copy Markdown

Summary

Towards #36 / #37 (Windows builds are unsigned). Per the maintainer note in #36 there is no signing account yet — so this PR does not require one. It makes the release pipeline signing-ready: when a signing credential lands as a repo secret, the next release comes out fully signed; until then (and on forks / scratch runs) every build is byte-for-byte the current unsigned behavior. The included doc is the procurement decision guide for when that account gets opened.

This deliberately mirrors the two patterns the repo already uses: the macOS APPLE_* block in release.yml (secrets present → signed; absent → degrade gracefully) and the existing TAURI_SIGNING_PRIVATE_KEY overlay mechanism in build_windows.ps1.

What changed

packaging/build_windows.ps1 — resolves credentials from the environment, first match wins, all-absent = no-op:

  1. WINDOWS_SIGN_COMMAND — custom command template (%1 = file), the escape hatch that fits any cloud signing CLI (Azure Trusted Signing, KeyLocker, eSigner, …)
  2. WINDOWS_CERTIFICATE_THUMBPRINTsigntool against a cert already in the store (hardware token / pre-provisioned runner)
  3. WINDOWS_CERTIFICATE (+ _PASSWORD) — base64 PFX, imported for the build and then signed by thumbprint, so the password never reaches a command line or config file

It signs the PyInstaller sidecar explicitly before tauri build: the sidecar ships via resources, which the bundler copies verbatim — and Smart App Control evaluates every PE at run time, so a signed installer with an unsigned sidecar installs fine and then dies at first backend start (a failure mode that presents exactly like #382). After the build, every produced .exe/.msi is verified to carry a valid signature and the build fails otherwise — a sign step that silently no-ops is worse than an unsigned build.

.github/workflows/release.yml — passes the new secrets through (unset secrets arrive as empty strings and count as absent) and documents them in the header, mirroring the APPLE_* block.

docs/windows-signing.md — procurement decision matrix (Trusted Signing ~$10/mo with immediate SmartScreen reputation, vs OV cloud-HSM, vs EV token and why tokens don't fit CI), the runbook, verification commands, and field notes from shipping a Tauri + PyInstaller-sidecar app through OEM QA on SAC-enabled machines.

README.md — the Windows download caption now points at the doc.

Deliberately NOT in tauri.conf.json: a hardcoded certificateThumbprint makes tauri build fail on every machine that doesn't hold that cert. Signing config travels through a generated --config overlay only; dev builds stay green with zero setup.

Validation

Ran this branch's full Release workflow on a fork (no secrets configured → exercises the no-credentials path end-to-end on real runners): all three build jobs green, Windows included — https://github.com/lmanchu/openworker/actions/runs/31314011128

The Windows job log shows the degradation behaving as documented:

==> [3/4] Authenticode signing (sidecar)
    note: no signing credentials in env - installers will be UNSIGNED (SmartScreen warns; Smart App Control blocks). See docs/windows-signing.md.
==> [4/4] tauri build (--bundles nsis,msi)

Also: release.yml YAML validated; repo CI (pytest / gui-unit / gui-e2e) green on the branch. The signed path needs a run by whoever holds real credentials — happy to iterate if anything surfaces there.

Not closing #36/#37 with this PR: those should stay open until a credential is procured and a signed release actually ships.

🤖 Generated with Claude Code

Windows installers ship unsigned today (andrewyng#36, andrewyng#37): SmartScreen trains
users to click through, and Smart App Control machines block the app
outright with no override. The maintainer position is that no signing
account exists yet - so this change makes signing a repo-secret away
without requiring one now.

build_windows.ps1 resolves credentials from the environment (custom
sign-command template > cert-store thumbprint > base64 PFX import),
signs the PyInstaller sidecar explicitly - Tauri's bundler only signs
its own outputs, and SAC evaluates every PE at run time, so an
unsigned sidecar fails on SAC machines even inside a signed installer -
then hands Tauri the signing config through the existing --config
overlay mechanism. Every produced artifact is verified signed, and the
build fails if one is not. With no credentials in the environment the
build is byte-for-byte the current unsigned behavior.

release.yml passes the new secrets through (empty = absent), and
docs/windows-signing.md is the procurement decision guide (Trusted
Signing vs OV cloud-HSM vs EV token), the runbook, and the field notes
from shipping a Tauri + PyInstaller-sidecar app through OEM QA.

Deliberately NOT in tauri.conf.json: a hardcoded certificateThumbprint
breaks tauri build on every machine without that cert.

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
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