Skip to the content.

Code-signing policy

This document describes how LegendCTL release binaries are built and signed. It is also a prerequisite for LegendCTL’s application to the SignPath Foundation free code-signing program for open-source software.

Summary

Build & release process

  1. Source of truth. All code lives in this public repository. Releases are cut from a specific tagged commit on the default branch.
  2. Build from source. There are two build lanes:
    • Official release assets (v2.5.0 and later) are built by GitHub Actions CI (.github/workflows/release-build.yml) when the release tag is pushed: the workflow runs the full unit suite and a dependency CVE audit first, then packages the app with PyInstaller (plus the Inno Setup installer) and generates a build-provenance attestation for each distributed binary.
    • Source builds (and releases before v2.5.0) use the project’s own local build script:
      .\tools\build_release.ps1
      

      This packages the app with PyInstaller into dist/…/ZD Ultimate Legend.exe plus a distributable ZIP (and an installer .exe when Inno Setup is present).

  3. Sign (future — once SignPath signing is live). The built executable and installer inputs are submitted to SignPath for signing before the final distributables are packaged, because AuthentiCode signing changes a binary’s bytes (and a signed inner executable changes the ZIP/installer bytes). The signed-release flow is: build → sign → package the final distributables → smoke-test the final artifacts → hash + attest the final bytes → publish. Only artifacts produced by step 2 from the tagged commit are submitted. Until signing is live this step is skipped, and the flow is: build → smoke-test → hash + attest → publish.
  4. Verify the build. The release smoke test (.\tools\smoke_release.ps1) and the unit suite are run against the final artifacts before a build is considered releasable.
  5. Publish hashes. Each release publishes SHA256SUMS.txt computed over the final published bytes (after signing, once signing is live), so users can verify integrity independently of the signature — hashes and attestations always describe exactly what users download.

Signing scope

We sign only:

We do not sign:

Team & roles

LegendCTL is currently a solo-maintainer project. For SignPath’s role model, the single maintainer (copyright holder EvilHumphrey) holds all three roles:

Role Responsibility Holder
Author Requests the signed build solo maintainer
Reviewer Reviews the change being signed solo maintainer
Approver Approves the signing request solo maintainer

If additional maintainers join, these roles will be separated (a different person approving the signing than authoring it) and this document updated.

Account security

How users verify a signed release

Once signing is live, you can confirm a downloaded build is the signed release:

  1. Right-click ZD Ultimate Legend.exeProperties → Digital Signatures and confirm the signer is the LegendCTL project certificate.
  2. Independently, check the downloaded artifact’s hash against the published SHA256SUMS.txt:
    Get-FileHash ".\ZDUltimateLegend-v<version>-windows.zip" -Algorithm SHA256
    

Until signing is in place, releases are unsigned — but from v2.5.0 they are not unverifiable: each release’s binaries carry CI build-provenance attestations you can check with the GitHub CLI:

gh attestation verify .\ZDUltimateLegend-v<version>-Setup.exe --repo EvilHumphrey/LegendCTL
gh attestation verify .\ZDUltimateLegend-v<version>-windows.zip --repo EvilHumphrey/LegendCTL

See install-windows-and-smartscreen.md for the full verification guide (including offline verification), and the README’s “Distribution safety” section for what to expect from SmartScreen and antivirus in the meantime.