0041: Windows signing with Artifact Signing
On this page
Status: accepted
Context
The Windows installer was unsigned, so SmartScreen showed Windows protected your PC and people had to choose More info, then Run anyway. A signature from a certificate that chains to Microsoft's trusted roots, issued to a verified publisher, is what lets Windows show the publisher's name and build reputation.
The usual ways to get one are an EV or OV code signing certificate on a hardware token or in a cloud HSM, or Azure Artifact Signing (called Trusted Signing until 2025). A token can't be used from a hosted CI runner, and a certificate exported to a file would be a long-lived secret in the repository's settings. Artifact Signing issues a certificate valid for three days, signs on Microsoft's side, and gives the publisher's identity only after Microsoft verifies the organization (Frank The Programmer LLC, validated in October 2026).
Decision
- The release workflow signs with Azure Artifact Signing: an account in East US and a Public Trust certificate profile on it, bound to the validated organization. The workflow reads their names from the GitHub variables
AZURE_SIGNING_ACCOUNTandAZURE_SIGNING_PROFILE. - Tauri runs
apps/desktop/scripts/sign-windows.ps1as itssignCommandfor the installer and Short Leash's executables. The workflow writes that setting into a config file for the run (apps/desktop/scripts/windows-sign-config.ps1), so local, CI and pull request builds stay unsigned. Tauri signs first and makes the updater signature after, so the update signature covers the signed installer. - The script runs
signtoolfrom the Windows SDK with Microsoft's Artifact Signing client library (a NuGet package) and a timestamp fromtimestamp.acs.microsoft.com, so signatures keep validating after the three-day certificate expires. We don't use a third-party signing CLI. - The client library is pinned to a version and SHA-512 that nuget.org publishes, and its DLL is used only with a valid Authenticode signature from Microsoft, the same rule as the Visual C++ Redistributable (ADR 0032, invariant 7 in
CLAUDE.md). - The workflow signs in as a service principal that holds only the Artifact Signing Certificate Profile Signer role on that account. Its tenant ID, client ID and client secret are the repository secrets
AZURE_TENANT_ID,AZURE_CLIENT_IDandAZURE_CLIENT_SECRET. The secret expires, so signing stops until it's replaced; the release skill says when and how. - After the build,
apps/desktop/scripts/check-windows-signature.ps1fails the release unless the installer, the app and the two programs it carries (leashdandleash) each have a valid, timestamped signature issued to Frank The Programmer LLC. - The Preview build workflow has a
sign_windowsoption that does the same signing for a hand-run build from any branch, to try changes to signing before a release.
Consequences
- No certificate or private key is stored anywhere, and a leaked signing credential can only sign as Short Leash until its role assignment or secret is removed.
- Windows shows Short Leash's publisher name. The SmartScreen warning should fade as the signed installer builds reputation, but that isn't immediate, so the docs keep the Run anyway step until a signed release has been tried on a clean PC.
- Releases now depend on the Artifact Signing service. If it's down or the secret has expired, the Windows job fails before anything is published.
- The Mac build is unchanged (Developer ID and notarization).