Files
ForgeFlow/docs/RELEASING.md
T
NuklearRabbit 18f42621c2
ForgeFlow quality gate / quality (push) Canceled after 0s
feat: harden release signing and coverage gate
2026-07-29 22:54:51 +02:00

4.0 KiB

Releasing ForgeFlow

ForgeFlow releases are built only from a clean, reviewed commit on Node 22 LTS.

Quality gate

npm ci
npm run quality
npm audit --omit=dev --audit-level=high

Signed Windows build

Production signing is fail-closed. Configure electron-builder's Authenticode certificate through its supported CSC environment variables, then set:

$env:FORGEFLOW_SIGNED_RELEASE = '1'
$env:FORGEFLOW_EXPECTED_PUBLISHER = 'CN=Exact Legal Publisher, O=Exact Legal Organization, C=BE'
npm run dist:win:signed

The signed command requires signed-release mode, an exact publisher subject and either a classic WIN_CSC_LINK certificate configuration or complete Azure credentials. It enables electron-builder's forceCodeSigning gate, so missing signing material cannot silently produce a production candidate.

  1. Create an Azure Artifact Signing account and identity-validation certificate profile for the legal ForgeFlow publisher.
  2. Create an Entra app registration and give its service principal the Artifact Signing Certificate Profile Signer role on that account.
  3. Store the following as protected CI variables—never in Git:
$env:AZURE_TENANT_ID = '<tenant id>'
$env:AZURE_CLIENT_ID = '<application/client id>'
$env:AZURE_CLIENT_SECRET = '<secret value>'
$env:FORGEFLOW_AZURE_SIGNING_ENDPOINT = 'https://<region>.codesigning.azure.net/'
$env:FORGEFLOW_AZURE_SIGNING_ACCOUNT = '<artifact signing account>'
$env:FORGEFLOW_AZURE_CERTIFICATE_PROFILE = '<certificate profile>'
$env:FORGEFLOW_SIGNED_RELEASE = '1'
$env:FORGEFLOW_EXPECTED_PUBLISHER = 'CN=<exact subject from Get-AuthenticodeSignature>'
npm run dist:win:signed

The generated configuration uses SHA-256 and Microsoft's RFC 3161 timestamp service. FORGEFLOW_EXPECTED_PUBLISHER must still contain the complete subject reported by the resulting certificate, even though Azure's builder option uses its CN component.

Alternative: classic CA certificate

When a CA supplies a CI-compatible PFX or hardware/cloud connector supported by electron-builder, configure its protected values and use the same command:

$env:WIN_CSC_LINK = 'C:\secure\forgeflow-signing.pfx'
$env:WIN_CSC_KEY_PASSWORD = '<secret password>'
$env:FORGEFLOW_SIGNED_RELEASE = '1'
$env:FORGEFLOW_EXPECTED_PUBLISHER = 'CN=<exact legal subject>, O=<organization>, C=BE'
npm run dist:win:signed

Do not purchase a certificate before the CA or cloud service confirms the exact legal subject and that its key-storage method works with the intended Windows CI runner. An ordinary OV certificate can still accumulate SmartScreen reputation; EV or Azure Artifact Signing provides immediate publisher trust.

Both installer and portable executable must have a valid Authenticode signature, the expected publisher and a timestamp. The build also creates SHA-256 files, a CycloneDX SBOM and a provenance document containing commit and build ID.

Without FORGEFLOW_SIGNED_RELEASE=1, local builds may be unsigned for development testing but must never be published as production releases.

Atomic publication

npm run release:binary keeps the Gitea release in draft state while uploading the installer, portable executable, two checksums, provenance and SBOM. It only publishes after all six assets are present. A failed upload leaves a draft rather than exposing an incomplete updater target.

The publisher check is an exact subject match, not a substring match. Before a production certificate is available, validate the complete local chain with:

npm run test:signing

This disposable fixture signs installer, portable, update-helper and uninstaller stand-ins, requires an RFC 3161 timestamp, and proves rejection of a missing timestamp, wrong publisher and a modified binary. Its certificate is removed from the current-user certificate store after the test.

The production Authenticode certificate and exact legal publisher identity are PENDING_HUMAN_INPUT; all surrounding build and verification code is complete.