From 2023d787db2f43b00e83c3d55e97402c992c13e5 Mon Sep 17 00:00:00 2001 From: Filipe Moreira Date: Fri, 25 Sep 2026 16:44:38 -0300 Subject: [PATCH] chore: prepare SignPath code signing (policy page, gated release steps) Co-Authored-By: Claude Opus 5.5 --- .github/workflows/release.yml | 38 +++++++++++++++++++++++++++++++++ README.md | 2 +- README.pt-BR.md | 2 +- docs/CODE_SIGNING.md | 40 +++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 docs/CODE_SIGNING.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 619b1dc..b51d748 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,6 +91,44 @@ jobs: shell: pwsh run: .\build\Publish-ConsoleMode.ps1 -Runtime x64 -Target All -Version "${{ steps.version.outputs.version }}" + # Code signing (docs/CODE_SIGNING.md). Off until the SignPath repository variables exist: + # SIGNPATH_ORGANIZATION_ID, SIGNPATH_PROJECT_SLUG, SIGNPATH_POLICY_SLUG, plus the + # SIGNPATH_API_TOKEN secret. Only tag pushes are signed; each request waits for manual approval. + - name: Upload unsigned build for signing + id: unsigned + if: github.event_name == 'push' && vars.SIGNPATH_ORGANIZATION_ID != '' + uses: actions/upload-artifact@v4 + with: + name: unsigned-${{ steps.version.outputs.version }} + path: | + dist/ConsoleMode-Setup-x64.exe + dist/ConsoleMode-Portable-x64.exe + if-no-files-found: error + + - name: Sign with SignPath + if: github.event_name == 'push' && vars.SIGNPATH_ORGANIZATION_ID != '' + uses: signpath/github-action-submit-signing-request@v2 + with: + api-token: ${{ secrets.SIGNPATH_API_TOKEN }} + organization-id: ${{ vars.SIGNPATH_ORGANIZATION_ID }} + project-slug: ${{ vars.SIGNPATH_PROJECT_SLUG }} + signing-policy-slug: ${{ vars.SIGNPATH_POLICY_SLUG }} + github-artifact-id: ${{ steps.unsigned.outputs.artifact-id }} + wait-for-completion: true + wait-for-completion-timeout-in-seconds: 3600 + output-artifact-directory: dist-signed + + - name: Use the signed files + if: github.event_name == 'push' && vars.SIGNPATH_ORGANIZATION_ID != '' + shell: pwsh + run: | + foreach ($name in "ConsoleMode-Setup-x64.exe", "ConsoleMode-Portable-x64.exe") { + $signed = Join-Path "dist-signed" $name + if (-not (Test-Path -LiteralPath $signed)) { throw "SignPath did not return $name" } + if ((Get-AuthenticodeSignature -LiteralPath $signed).Status -ne "Valid") { throw "$name is not validly signed" } + Copy-Item -LiteralPath $signed -Destination (Join-Path "dist" $name) -Force + } + - name: Upload artifacts uses: actions/upload-artifact@v4 with: diff --git a/README.md b/README.md index bb45968..062231d 100644 --- a/README.md +++ b/README.md @@ -65,4 +65,4 @@ All the details in the [release notes](https://github.com/lippdev/consolemode/re - **Feedback:** the button next to Settings in the app, or [this form](https://github.com/lippdev/consolemode/issues/new?template=feedback.yml). A ⭐ helps other couch gamers find the project. - Antivirus may flag the bundled helper tools; the source is all here. -MIT License · [Third-party notices](THIRD_PARTY_NOTICES.md) +MIT License · [Third-party notices](THIRD_PARTY_NOTICES.md) · [Code signing policy](docs/CODE_SIGNING.md) diff --git a/README.pt-BR.md b/README.pt-BR.md index 7c17fac..cee90d9 100644 --- a/README.pt-BR.md +++ b/README.pt-BR.md @@ -65,4 +65,4 @@ Todos os detalhes nas [notas da versão](https://github.com/lippdev/consolemode/ - **Feedback:** o botão ao lado de Ajustes no app, ou [este formulário](https://github.com/lippdev/consolemode/issues/new?template=feedback.yml). Uma ⭐ ajuda outros jogadores de sofá a encontrar o projeto. - Alguns antivírus podem acusar as ferramentas auxiliares incluídas; o código está todo aqui. -Licença MIT · [Avisos de terceiros](THIRD_PARTY_NOTICES.md) +Licença MIT · [Avisos de terceiros](THIRD_PARTY_NOTICES.md) · [Política de assinatura de código](docs/CODE_SIGNING.md) diff --git a/docs/CODE_SIGNING.md b/docs/CODE_SIGNING.md new file mode 100644 index 0000000..44b508c --- /dev/null +++ b/docs/CODE_SIGNING.md @@ -0,0 +1,40 @@ +# Code signing policy + +> **Status:** application to the SignPath Foundation open source program is pending. +> Until it is approved, releases are not signed and this policy describes how they will be. + +Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/). + +## What gets signed + +Only binaries built from this repository's source by the [Release workflow](../.github/workflows/release.yml) +on GitHub Actions, from a `v*` tag: + +- `ConsoleMode-Setup-x64.exe` (installer) +- `ConsoleMode-Portable-x64.exe` (portable) + +Nothing built on a developer machine is signed. + +## Team roles + +| Role | Members | +|------|---------| +| Committers and reviewers | [Filipe Moreira (@lippdev)](https://github.com/lippdev) | +| Approvers | [Filipe Moreira (@lippdev)](https://github.com/lippdev) | + +Pull requests from people outside this list, and from automated agents, are reviewed by a committer +before merge, and every pull request must pass the CI build. Each signing request is approved +manually by an approver. All members use multi-factor authentication on GitHub and SignPath. + +## Privacy + +Console Mode does not collect or send telemetry. It connects to the internet only to: + +- check for new versions through the public GitHub Releases API (`api.github.com`), without + sending any personal data, and download an update when the user accepts it; +- open pages in the user's browser when the user asks for it (the feedback form on GitHub, + the releases page, links to other apps). + +Settings, the display backup and the log stay on the user's PC, in `%LOCALAPPDATA%\ConsoleMode` +(installer) or `ConsoleMode_Data` next to the executable (portable). The installer version can be +removed from Windows Settings → Apps; the portable version by deleting its file and folder.