feat: harden release signing and coverage gate
ForgeFlow quality gate / quality (push) Canceled after 0s

This commit is contained in:
NuklearRabbit
2026-07-29 22:54:51 +02:00
parent aa4895912a
commit 18f42621c2
13 changed files with 496 additions and 39 deletions
+9 -11
View File
@@ -1,20 +1,18 @@
# Coverage policy
ForgeFlow treats coverage as release evidence, not as a target to game. `npm run coverage`
enforces 75% statements, 75% lines, 75% functions and 60% branches globally.
enforces 75% statements, 75% lines, 75% functions and 65% branches globally.
The July 2026 hardening pass raised the measured baseline from 69.74% statements/lines,
68.82% functions and 55.38% branches to at least 78% statements/lines, 79% functions and
60% branches. The requested 65% global branch target was investigated but is not used as
the release gate yet. Node/V8 discovers additional branch counters when previously
unexecuted functions become covered; the denominator grew from 2,537 to more than 3,100
while the new tests added hundreds of asserted branches. Raising the number by excluding
command builders, platform guards or error adapters would make the result look better
without increasing deployment safety.
68.82% functions and 55.38% branches to 81.48% statements/lines, 82.07% functions and
65.59% branches. Node/V8 discovered additional branch counters when previously unexecuted
functions became covered; the denominator grew from 2,537 to 3,473 while the new tests
added hundreds of asserted decisions. No command builders, platform guards or error
adapters were excluded to improve the result cosmetically.
The 60% global gate is therefore paired with scenario-level evidence for the critical
The 65% global gate is paired with scenario-level evidence for the critical
boundaries: deploy-key rollback, deployment verification, Gitea authentication and
redirects, SSH host identity and output limits, inventory reconciliation, stale plans,
configuration recovery, release integrity and updater failure modes. New code must not
reduce the global baseline. A future increase to 65% should come from additional asserted
failure scenarios, not ignore comments or source exclusions.
reduce the global baseline. Future increases must come from additional asserted failure
scenarios, not ignore comments or source exclusions.
+2 -3
View File
@@ -45,9 +45,8 @@ console events, DOM, fixture details and test identity.
## 7. Coverage and dependencies
Coverage increased from 69.74% statements/lines, 68.82% functions and 55.38%
branches to at least 78.75%, 79.68% and 59.25%, respectively, before the last
ConfigStore tests. The enforced gates are 75/75/75/60; the rationale and 65%
follow-up are in `COVERAGE_POLICY.md`. Production dependencies have zero known
branches to 81.48%, 82.07% and 65.59%, respectively. The enforced gates are now
75/75/75/65 and are documented in `COVERAGE_POLICY.md`. Production dependencies have zero known
audit vulnerabilities. Remaining development findings belong to current upstream
ESLint/electron-builder toolchains and are assessed in `DEPENDENCY_AUDIT.md`.
+49 -1
View File
@@ -18,9 +18,57 @@ certificate through its supported CSC environment variables, then set:
```powershell
$env:FORGEFLOW_SIGNED_RELEASE = '1'
$env:FORGEFLOW_EXPECTED_PUBLISHER = 'CN=Exact Legal Publisher, O=Exact Legal Organization, C=BE'
npm run dist:win
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.
### Recommended: Azure Artifact Signing
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:
```powershell
$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:
```powershell
$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.
+3 -3
View File
@@ -5,9 +5,9 @@
The quality chain contains more than 230 Node and browser acceptance cases. The
latest Windows source run completed without failures and retains one explicitly
Bash-dependent skip. `npm run coverage` enforces 75% lines/statements/functions
and 60% branches; the measured hardening baseline is 78.75% statements/lines,
79.68% functions and 59.25% branches before the final ConfigStore additions.
See `COVERAGE_POLICY.md` for the non-gamed branch policy.
and 65% branches; the measured hardening baseline is 81.48% statements/lines,
82.07% functions and 65.59% branches. See `COVERAGE_POLICY.md` for the
non-gamed branch policy.
`npm run quality` is the local equivalent of `.gitea/workflows/quality.yml` and
runs source verification, ESLint, the complete suite and coverage on Node 22 LTS.