Skip to content

Phase 4: Integrate SignPath signing into release pipeline (gated on SignPath OSS approval) #17

@geevensingh

Description

@geevensingh

Context

This issue captures the final phase of the in-app auto-update plan (master plan was Phases 0–5). Phases 0–3 and 5 shipped in v1.5.0 / v1.6.0; Phase 4 (code signing) was deliberately deferred because it depends on external approval from the SignPath Foundation.

The full auto-update infrastructure is operating today, but every release artifact (DiffViewer-Setup.exe, DiffViewer-portable.exe, the Velopack *.nupkg files) ships unsigned. Users see a Windows SmartScreen warning on first install and have to click More infoRun anyway. The vpk pack step in release.yml logs warnings like:

[WRN] No signing parameters provided, 254 file(s) will not be signed.
[WRN] No signing parameters provided, 1 file(s) will not be signed.

These warnings are the intentional "Phase 4 will fix this" placeholders.

Status of SignPath application

Submitted on 2026-05-30 by @geevensingh. SignPath OSS reviews typically take weeks-to-months; no fixed timeline. Approval may also be rejected, in which case the fallback options (buying a commercial OV/EV cert, staying unsigned) need a separate decision.

The application draft (with project description, build pipeline details, reputation section, etc.) lives in agent session state at ~/.copilot/session-state/4519f6b6-393a-4476-8efa-410e5396c3a9/files/signpath-application.md for context — that's local-only and not committed.

Repository-level prep work that is committed:

  • CODE_SIGNING_POLICY.md — the per-project policy SignPath reviewers expect (commit a3f7f75)
  • PRIVACY.md — referenced by the application form (commit bff5f67)

What to do once approval lands

  1. Provision SignPath credentials (handled by the SignPath dashboard once approved):
    • Create a SignPath project for DiffViewer
    • Define a signing policy covering DiffViewer-Setup.exe, DiffViewer-portable.exe, and the Velopack *.nupkg files
    • Get the signing-request token from the SignPath UI
  2. Add the token as a GitHub Actions secret (SIGNPATH_API_TOKEN or similar — match whatever the SignPath docs recommend at the time)
  3. Wire signing into .github/workflows/release.yml using SignPath's official GitHub Action (signpath/github-action-submit-signing-request). Two integration points to think through:
    • Sign the Velopack-produced files (DiffViewer-Setup.exe + *.nupkg) — these come out of vpk pack. SignPath''s action takes the unsigned artifacts and returns the signed versions.
    • Sign the portable DiffViewer-portable.exe — separately, after the Portable lane''s dotnet publish and rename step.
    • Both signed sets get uploaded by the existing softprops/action-gh-release step (no change to upload logic).
  4. Remove the "unsigned binary" SmartScreen note from:
    • README.md (Install section)
    • CODE_SIGNING_POLICY.md (the status note at the top)
  5. Verify in CI by cutting a vX.Y.Z-rc1 prerelease tag against a feature branch; confirm SignPath signs both artifacts and the resulting .exes are recognized as signed by Windows.
  6. Add a CHANGELOG [Unreleased] entry noting that releases are now Authenticode-signed (this is a real user-visible change — SmartScreen warning goes away on first install).

Open questions for the future session

  • Does the SignPath signing action need a separate signing-request step per artifact, or can it batch? The current Velopack output has 1 .exe + 1 or 2 .nupkg files; portable adds another .exe. Batching = fewer SignPath round-trips = faster CI.
  • What does the per-artifact "purpose" look like in a SignPath policy? Setup installer vs portable exe vs .nupkg may need different signing rules.
  • Should we sign the per-release-asset Velopack metadata .json files (assets.win.json, releases.win.json)? Probably not — they''re not executables. But worth confirming with SignPath docs.
  • What''s our fallback if signing fails mid-CI? Today an unsigned release is acceptable. Once Phase 4 ships, do we fail the release if signing fails, or fall back to unsigned + a warning? The latter is probably right (don''t block a release because of a transient SignPath outage) but worth deciding explicitly.

Definition of done

  • Both DiffViewer-Setup.exe and DiffViewer-portable.exe in the next tagged release are signed (verifiable via signtool verify or right-click → Properties → Digital Signatures)
  • No SmartScreen warning on first install for the signed Setup.exe
  • vpk pack warnings about missing signing parameters are gone
  • README and CODE_SIGNING_POLICY.md reflect the signed-release status

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority: mediumWorth doing; not blockingscope: mediumMulti-day, spans a couple subsystems

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions