fix: support unsigned desktop releases (#1520)
This commit is contained in:
@@ -22,7 +22,7 @@ Kandev uses a **single SemVer** `X.Y.Z` shared across all distribution channels.
|
||||
|
||||
Entirely in CI via `.github/workflows/release.yml`, triggered by a maintainer from the GitHub Actions UI:
|
||||
|
||||
1. Maintainer clicks "Run workflow" → picks `bump` (patch/minor/major) → optional `dry_run`.
|
||||
1. Maintainer clicks "Run workflow" → picks `bump` (patch/minor/major) → optional `dry_run`, `allow_unsigned_desktop`, or `desktop_validation_only`.
|
||||
2. `prepare` job bumps version + regenerates CHANGELOG, opens release PR, squash-merges, tags `vX.Y.Z`.
|
||||
3. `build-web` + `build-cli` + `build-bundles` (5 platforms) build the release artifacts.
|
||||
4. `publish-release` creates the GitHub release with platform tarballs + sha256 + auto-generated notes.
|
||||
@@ -31,6 +31,8 @@ Entirely in CI via `.github/workflows/release.yml`, triggered by a maintainer fr
|
||||
|
||||
There is no local release script — the entire flow runs in GHA.
|
||||
|
||||
`allow_unsigned_desktop=true` only disables macOS/Windows desktop signing enforcement. It still creates and publishes the normal release outputs unless `desktop_validation_only=true` is also selected. `desktop_validation_only=true` builds artifacts from the current workflow ref for maintainer inspection and skips the release PR, tag, GitHub release, npm publish, Homebrew update, and public container tags.
|
||||
|
||||
## Runtime resolution
|
||||
|
||||
In `apps/cli/src/runtime.ts`, the CLI locates its bundled runtime via:
|
||||
|
||||
@@ -47,7 +47,11 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
allow_unsigned_desktop:
|
||||
description: "Allow unsigned macOS/Windows desktop artifacts for internal validation only"
|
||||
description: "Allow unsigned macOS/Windows desktop artifacts; still publishes unless validation-only is checked"
|
||||
type: boolean
|
||||
default: false
|
||||
desktop_validation_only:
|
||||
description: "Build desktop artifacts only (no PR, tag, publish, npm, or tap update)"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
@@ -108,7 +112,7 @@ jobs:
|
||||
id: compute
|
||||
env:
|
||||
BUMP: ${{ inputs.bump }}
|
||||
ALLOW_UNSIGNED_DESKTOP: ${{ inputs.allow_unsigned_desktop }}
|
||||
DESKTOP_VALIDATION_ONLY: ${{ inputs.desktop_validation_only }}
|
||||
CURRENT_REF: ${{ github.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -159,7 +163,7 @@ jobs:
|
||||
echo "Next tag: $TAG"
|
||||
echo "version=$NEXT" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then
|
||||
if [ "$DESKTOP_VALIDATION_ONLY" = "true" ]; then
|
||||
echo "ref=$CURRENT_REF" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "ref=$TAG" >> "$GITHUB_OUTPUT"
|
||||
@@ -176,7 +180,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Bump version + generate CHANGELOG (in working tree)
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
env:
|
||||
NEXT: ${{ steps.compute.outputs.version }}
|
||||
TAG: ${{ steps.compute.outputs.tag }}
|
||||
@@ -214,7 +218,7 @@ jobs:
|
||||
git-cliff --tag "$TAG" -o CHANGELOG.md
|
||||
|
||||
- name: Create release PR + squash-merge + tag
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NEXT: ${{ steps.compute.outputs.version }}
|
||||
@@ -269,14 +273,16 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
- name: Unsigned desktop validation summary
|
||||
if: ${{ !inputs.dry_run && inputs.allow_unsigned_desktop }}
|
||||
- name: Desktop validation summary
|
||||
if: ${{ !inputs.dry_run && inputs.desktop_validation_only }}
|
||||
env:
|
||||
NEXT: ${{ steps.compute.outputs.version }}
|
||||
TAG: ${{ steps.compute.outputs.tag }}
|
||||
REF: ${{ steps.compute.outputs.ref }}
|
||||
ALLOW_UNSIGNED_DESKTOP: ${{ inputs.allow_unsigned_desktop }}
|
||||
run: |
|
||||
echo "Unsigned desktop validation for $TAG / $NEXT."
|
||||
echo "Desktop validation for $TAG / $NEXT."
|
||||
echo "Unsigned desktop artifacts allowed: $ALLOW_UNSIGNED_DESKTOP."
|
||||
echo "No release PR, tag, GitHub release, public container tags, npm publish, or Homebrew update will be created."
|
||||
echo "Build jobs will check out $REF."
|
||||
|
||||
@@ -544,6 +550,11 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then
|
||||
echo "::notice::Unsigned desktop artifacts requested; skipping macOS signing and notarization setup."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
missing=()
|
||||
for key in APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD KEYCHAIN_PASSWORD; do
|
||||
if [ -z "${!key:-}" ]; then
|
||||
@@ -566,10 +577,6 @@ jobs:
|
||||
fi
|
||||
|
||||
if [ "${#missing[@]}" -gt 0 ]; then
|
||||
if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then
|
||||
echo "::warning::Unsigned desktop artifacts are internal validation only; missing macOS signing inputs: ${missing[*]}"
|
||||
exit 0
|
||||
fi
|
||||
echo "::error::Public macOS desktop releases require signing and notarization inputs: ${missing[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -662,6 +669,22 @@ jobs:
|
||||
WINDOWS_SIGNTOOL_PATH: ${{ secrets.WINDOWS_SIGNTOOL_PATH }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then
|
||||
unset APPLE_CERTIFICATE
|
||||
unset APPLE_CERTIFICATE_PASSWORD
|
||||
unset APPLE_ID
|
||||
unset APPLE_PASSWORD
|
||||
unset APPLE_TEAM_ID
|
||||
unset APPLE_PROVIDER_SHORT_NAME
|
||||
unset APPLE_API_KEY
|
||||
unset APPLE_API_ISSUER
|
||||
unset APPLE_API_KEY_PATH
|
||||
unset APPLE_SIGNING_IDENTITY
|
||||
unset WINDOWS_CERTIFICATE
|
||||
unset WINDOWS_CERTIFICATE_PASSWORD
|
||||
unset WINDOWS_TIMESTAMP_URL
|
||||
unset WINDOWS_SIGNTOOL_PATH
|
||||
fi
|
||||
pnpm -C apps --filter @kandev/desktop build:vite
|
||||
cd apps/desktop
|
||||
pnpm tauri build \
|
||||
@@ -670,10 +693,9 @@ jobs:
|
||||
--bundles "${{ matrix.tauri_bundles }}"
|
||||
|
||||
- name: Sign Windows desktop artifacts
|
||||
if: matrix.platform == 'windows-x64'
|
||||
if: matrix.platform == 'windows-x64' && !inputs.allow_unsigned_desktop
|
||||
shell: pwsh
|
||||
env:
|
||||
ALLOW_UNSIGNED_DESKTOP: ${{ inputs.allow_unsigned_desktop }}
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
WINDOWS_TIMESTAMP_URL: ${{ secrets.WINDOWS_TIMESTAMP_URL }}
|
||||
@@ -684,10 +706,6 @@ jobs:
|
||||
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE_PASSWORD)) { $missing += "WINDOWS_CERTIFICATE_PASSWORD" }
|
||||
|
||||
if ($missing.Count -gt 0) {
|
||||
if ($env:ALLOW_UNSIGNED_DESKTOP -eq "true") {
|
||||
Write-Warning "Unsigned desktop artifacts are internal validation only; missing Windows signing inputs: $($missing -join ', ')"
|
||||
exit 0
|
||||
}
|
||||
Write-Error "Public Windows desktop releases require signing inputs: $($missing -join ', ')"
|
||||
exit 1
|
||||
}
|
||||
@@ -803,7 +821,7 @@ jobs:
|
||||
docker-amd64:
|
||||
name: Build & push container image (amd64)
|
||||
needs: [prepare, build-bundles]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -874,7 +892,7 @@ jobs:
|
||||
docker-arm64:
|
||||
name: Build & push container image (arm64)
|
||||
needs: [prepare, build-bundles]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -933,7 +951,7 @@ jobs:
|
||||
docker-manifest:
|
||||
name: Assemble multi-arch base manifest
|
||||
needs: [prepare, docker-amd64, docker-arm64]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -987,7 +1005,7 @@ jobs:
|
||||
docker-universal-amd64:
|
||||
name: Build & push universal image (amd64)
|
||||
needs: [prepare, docker-manifest]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -1039,7 +1057,7 @@ jobs:
|
||||
docker-universal-arm64:
|
||||
name: Build & push universal image (arm64)
|
||||
needs: [prepare, docker-manifest]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -1090,7 +1108,7 @@ jobs:
|
||||
# docker-universal-manifest is included in publish-release's `needs` so
|
||||
# its size gate (and any per-arch build failure) blocks the release.
|
||||
needs: [prepare, docker-universal-amd64, docker-universal-arm64]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -1147,7 +1165,7 @@ jobs:
|
||||
publish-release:
|
||||
name: Publish GitHub release
|
||||
needs: [prepare, build-bundles, build-desktop, docker-universal-manifest]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # softprops/action-gh-release creates the release
|
||||
@@ -1166,6 +1184,20 @@ jobs:
|
||||
OUTPUT: RELEASE_NOTES.md
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Add unsigned desktop warning to release notes
|
||||
if: ${{ inputs.allow_unsigned_desktop }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tmp="$(mktemp)"
|
||||
{
|
||||
echo "> [!WARNING]"
|
||||
echo "> macOS and Windows desktop installers in this release are unsigned."
|
||||
echo "> They may require manual OS security bypasses and are not trusted downloads."
|
||||
echo
|
||||
cat RELEASE_NOTES.md
|
||||
} > "$tmp"
|
||||
mv "$tmp" RELEASE_NOTES.md
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: bundle-*
|
||||
@@ -1211,7 +1243,7 @@ jobs:
|
||||
publish-npm:
|
||||
name: Publish npm packages
|
||||
needs: [prepare, publish-release]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
@@ -1246,7 +1278,7 @@ jobs:
|
||||
update-homebrew-tap:
|
||||
name: Update Homebrew tap
|
||||
needs: [prepare, publish-release]
|
||||
if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -252,21 +252,39 @@ describe("release desktop artifacts", () => {
|
||||
tauri_bundles: deb,rpm`);
|
||||
});
|
||||
|
||||
it("fails public macOS and Windows desktop builds closed when signing secrets are absent", () => {
|
||||
it("supports unsigned desktop releases separately from validation-only builds", () => {
|
||||
const workflow = releaseWorkflow();
|
||||
const signingDocs = readRepoFile("docs/desktop-tauri-signing.md");
|
||||
const tauriConfig = readRepoFile("apps/desktop/src-tauri/tauri.conf.json");
|
||||
const windowsSignScript = readRepoFile("apps/desktop/src-tauri/windows-sign.ps1");
|
||||
|
||||
expect(workflow).toContain("allow_unsigned_desktop");
|
||||
expect(workflow).toContain("Unsigned desktop artifacts are internal validation only");
|
||||
expect(workflow).toContain("desktop_validation_only");
|
||||
expect(workflow).toContain("ref: ${{ needs.prepare.outputs.ref }}");
|
||||
expect(workflow).toContain("persist-credentials: false");
|
||||
expect(workflow).toContain("Unsigned desktop validation summary");
|
||||
expect(workflow).toContain("Desktop validation summary");
|
||||
expect(workflow).toContain("No release PR, tag, GitHub release, public container tags");
|
||||
expect(workflow).toContain("if: ${{ !inputs.dry_run && !inputs.allow_unsigned_desktop }}");
|
||||
expect(workflow).toContain("if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}");
|
||||
expect(workflow).toContain('if [ "$DESKTOP_VALIDATION_ONLY" = "true" ]; then');
|
||||
expect(workflow).toContain(
|
||||
"Allow unsigned macOS/Windows desktop artifacts; still publishes unless validation-only is checked",
|
||||
);
|
||||
expect(workflow).toContain("Add unsigned desktop warning to release notes");
|
||||
expect(workflow).toContain(
|
||||
"macOS and Windows desktop installers in this release are unsigned.",
|
||||
);
|
||||
expect(workflow).not.toMatch(
|
||||
/if \[ "\$ALLOW_UNSIGNED_DESKTOP" = "true" \]; then\r?\n\s*echo "ref=\$CURRENT_REF"/,
|
||||
);
|
||||
expect(workflow).toContain("docker-amd64:");
|
||||
expect(workflow).toContain("docker-universal-manifest:");
|
||||
expect(workflow).toContain('if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then');
|
||||
expect(workflow).toContain("unset APPLE_CERTIFICATE");
|
||||
expect(workflow).toContain("unset APPLE_ID");
|
||||
expect(workflow).toContain("unset WINDOWS_CERTIFICATE");
|
||||
expect(workflow).toContain("unset WINDOWS_CERTIFICATE_PASSWORD");
|
||||
expect(workflow).toContain("unset WINDOWS_TIMESTAMP_URL");
|
||||
expect(workflow).toContain("unset WINDOWS_SIGNTOOL_PATH");
|
||||
|
||||
for (const key of [
|
||||
"APPLE_CERTIFICATE",
|
||||
@@ -303,9 +321,12 @@ describe("release desktop artifacts", () => {
|
||||
expect(tauriConfig).toContain("windows-sign.ps1");
|
||||
expect(tauriConfig).not.toContain('"csp": null');
|
||||
expect(windowsSignScript).toContain('"https://timestamp.digicert.com"');
|
||||
expect(windowsSignScript).toContain("Skipping Windows signing for unsigned desktop artifact");
|
||||
expect(windowsSignScript).toContain("Remove-Item -LiteralPath $certificatePath");
|
||||
expect(signingDocs).toContain("Public recommended desktop releases require signing");
|
||||
expect(signingDocs).toContain("allow_unsigned_desktop");
|
||||
expect(signingDocs).toContain("desktop_validation_only");
|
||||
expect(signingDocs).toContain("publishes the normal release outputs");
|
||||
expect(signingDocs).toContain("does not publish a GitHub release");
|
||||
expect(signingDocs).toContain("public container tags");
|
||||
expect(signingDocs).toContain("Ubuntu 22.04");
|
||||
|
||||
@@ -32,4 +32,4 @@ Use `scripts/release/prepare-desktop-runtime.sh` and `scripts/release/verify-des
|
||||
|
||||
## Release
|
||||
|
||||
Desktop artifacts are built in `.github/workflows/release.yml` after the platform runtime bundles. Public macOS and Windows artifacts require signing unless `allow_unsigned_desktop=true` is explicitly selected for internal validation.
|
||||
Desktop artifacts are built in `.github/workflows/release.yml` after the platform runtime bundles. Public recommended macOS and Windows artifacts require signing unless `allow_unsigned_desktop=true` is explicitly selected. Use `desktop_validation_only=true` for artifact-only validation runs that skip the release PR, tag, publish jobs, and public container tags.
|
||||
|
||||
@@ -5,15 +5,16 @@ param(
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if ($env:ALLOW_UNSIGNED_DESKTOP -eq "true") {
|
||||
Write-Warning "Skipping Windows signing for unsigned desktop artifact."
|
||||
exit 0
|
||||
}
|
||||
|
||||
$missing = @()
|
||||
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE)) { $missing += "WINDOWS_CERTIFICATE" }
|
||||
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE_PASSWORD)) { $missing += "WINDOWS_CERTIFICATE_PASSWORD" }
|
||||
|
||||
if ($missing.Count -gt 0) {
|
||||
if ($env:ALLOW_UNSIGNED_DESKTOP -eq "true") {
|
||||
Write-Warning "Skipping Windows signing for internal unsigned desktop validation; missing: $($missing -join ', ')"
|
||||
exit 0
|
||||
}
|
||||
throw "Public Windows desktop releases require signing inputs: $($missing -join ', ')"
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Add a Tauri v2 desktop app as a thin native shell over the existing Kandev runti
|
||||
|
||||
The installed desktop app will not include a Node.js runtime. Node.js and pnpm remain build-time tooling for Vite, TypeScript, Tauri CLI invocation, tests, and release automation.
|
||||
|
||||
Desktop launches set the backend to a loopback-only bind address and an app-selected local port. Public desktop releases require macOS Developer ID signing/notarization and Windows code signing before the artifacts are presented as trusted downloads. The first desktop implementation does not include Tauri's in-app updater; updates continue through GitHub release downloads/manual reinstall until a separate updater spec is approved.
|
||||
Desktop launches set the backend to a loopback-only bind address and an app-selected local port. Public recommended desktop releases require macOS Developer ID signing/notarization and Windows code signing before the artifacts are presented as trusted downloads; unsigned desktop artifacts require an explicit release workflow override. The first desktop implementation does not include Tauri's in-app updater; updates continue through GitHub release downloads/manual reinstall until a separate updater spec is approved.
|
||||
|
||||
## Consequences
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ Supported desktop platforms:
|
||||
|
||||
Public recommended macOS artifacts must be Developer ID signed and notarized. Public recommended Windows artifacts must be code signed. Linux artifacts are checksum-gated; package-manager signatures can be added later.
|
||||
|
||||
Unsigned macOS or Windows desktop artifacts are for internal validation only. They may require manual OS security bypasses and should not be presented as trusted public downloads.
|
||||
Unsigned macOS or Windows desktop artifacts may be produced only through an explicit release workflow override. They may require manual OS security bypasses and should not be presented as trusted downloads.
|
||||
|
||||
## Runtime Requirements
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
Public recommended desktop releases require signing on macOS and Windows. The release workflow fails closed by default when those secrets are missing.
|
||||
|
||||
Use `allow_unsigned_desktop=true` only for internal validation builds. That mode may upload workflow artifacts for maintainer inspection, but it does not publish a GitHub release, npm packages, Homebrew updates, or public container tags. Unsigned desktop artifacts are internal validation only and must not be presented as trusted public downloads.
|
||||
Use `allow_unsigned_desktop=true` only when intentionally producing unsigned macOS/Windows desktop artifacts. Unless `desktop_validation_only=true` is also selected, that mode still publishes the normal release outputs: the release PR and tag, GitHub release, npm packages, Homebrew update, public container tags, and desktop artifacts. Unsigned desktop artifacts may require manual OS security bypasses and must not be presented as trusted downloads.
|
||||
|
||||
When unsigned desktop artifacts are published in a normal release, the workflow prefixes the GitHub release notes with an unsigned desktop warning.
|
||||
|
||||
Use `desktop_validation_only=true` for maintainer inspection builds. That mode uploads workflow artifacts but does not publish a GitHub release, npm packages, Homebrew updates, or public container tags.
|
||||
|
||||
## macOS
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ Add signing inputs/secrets behind conditional release steps:
|
||||
- Windows: certificate/key-vault or custom signing command wiring.
|
||||
- Linux: checksum required; GPG/AppImage signing optional.
|
||||
|
||||
Unsigned desktop builds remain allowed for dry runs and internal validation, but public recommended artifacts should require signing success on macOS and Windows.
|
||||
Unsigned desktop builds remain allowed only through explicit workflow overrides, but public recommended artifacts should require signing success on macOS and Windows.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ spec: "../../specs/desktop-tauri-app/spec.md"
|
||||
|
||||
- macOS desktop release builds support Developer ID signing and notarization through GitHub Actions secrets.
|
||||
- Windows desktop release builds support code signing through the selected signing mechanism.
|
||||
- Unsigned desktop artifacts are clearly limited to dry runs/internal validation and are not treated as trusted public artifacts.
|
||||
- Unsigned desktop artifacts require an explicit workflow override and are not treated as trusted public artifacts.
|
||||
|
||||
## Verification
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Users who prefer a desktop workflow should be able to install and open Kandev fr
|
||||
- The desktop app launches the backend with a predictable process environment for GUI launches, including common user binary locations, so configured agent CLIs can be discovered as reliably as they are from terminal-launched Kandev.
|
||||
- Opening a second desktop instance focuses the existing app window or exits without starting a second backend for the same desktop launch context.
|
||||
- GitHub releases include desktop artifacts alongside the existing runtime tarballs and checksums.
|
||||
- Unsigned desktop artifacts may be produced for development or internal validation, but public recommended desktop releases require macOS Developer ID signing/notarization and Windows code signing before they are presented as trusted user-facing downloads.
|
||||
- Unsigned desktop artifacts may be produced only through explicit development, validation, or release workflow overrides. Public recommended desktop releases require macOS Developer ID signing/notarization and Windows code signing before they are presented as trusted user-facing downloads.
|
||||
- Desktop release notes and install docs tell users which artifact to download for each operating system and call out any unsigned/pre-release limitations.
|
||||
|
||||
## Data model
|
||||
@@ -82,9 +82,9 @@ The desktop shell passes an explicit environment to the native launcher:
|
||||
|
||||
Each released version includes platform desktop artifacts with checksums. Exact file names may follow Tauri's generated naming, but the release must expose these platform groups:
|
||||
|
||||
- macOS arm64: signed/notarized `.dmg` for public release, unsigned `.dmg` allowed only for internal validation.
|
||||
- macOS x64: signed/notarized `.dmg` for public release, unsigned `.dmg` allowed only for internal validation.
|
||||
- Windows x64: signed installer (`.exe` or `.msi`) for public release, unsigned installer allowed only for internal validation.
|
||||
- macOS arm64: signed/notarized `.dmg` for recommended public release, unsigned `.dmg` allowed only through an explicit override.
|
||||
- macOS x64: signed/notarized `.dmg` for recommended public release, unsigned `.dmg` allowed only through an explicit override.
|
||||
- Windows x64: signed installer (`.exe` or `.msi`) for recommended public release, unsigned installer allowed only through an explicit override.
|
||||
- Linux x64: AppImage and/or distro package generated by Tauri, with checksum.
|
||||
- Linux arm64: AppImage and/or distro package generated by Tauri, with checksum.
|
||||
|
||||
@@ -128,7 +128,7 @@ Transitions:
|
||||
- If `/health` does not succeed before the configured timeout, the desktop app terminates the launched child process tree and shows a timeout error.
|
||||
- If the WebView runtime is unavailable or broken on the host OS, the app fails using the platform's normal Tauri/WebView error behavior; the backend process must not remain running.
|
||||
- If an agent CLI cannot be found from a GUI-launched environment, the desktop app/backend surfaces the same setup-health guidance as browser/CLI Kandev rather than failing silently.
|
||||
- If signing/notarization secrets are absent in CI, release automation may still build explicitly unsigned internal artifacts, but public trusted desktop artifacts are not marked complete.
|
||||
- If signing/notarization secrets are absent in CI, release automation may still build explicitly unsigned desktop artifacts, but trusted desktop artifacts are not marked complete.
|
||||
|
||||
## Persistence guarantees
|
||||
|
||||
@@ -147,8 +147,8 @@ Transitions:
|
||||
- **GIVEN** the user quits the desktop app, **WHEN** the app exits normally, **THEN** the launcher/backend child process tree is terminated.
|
||||
- **GIVEN** a bundled backend binary is missing, **WHEN** the user opens the desktop app, **THEN** startup fails with a visible error naming the missing binary.
|
||||
- **GIVEN** the release workflow builds desktop artifacts for a version, **WHEN** the GitHub release is published, **THEN** desktop installers and checksums are attached alongside the existing runtime tarballs.
|
||||
- **GIVEN** a public macOS desktop release, **WHEN** the user downloads and opens the `.dmg`, **THEN** the app is signed and notarized so macOS does not report the download as damaged or from an unidentified developer.
|
||||
- **GIVEN** a public Windows desktop release, **WHEN** the user runs the installer, **THEN** the installer is code signed to reduce SmartScreen trust warnings.
|
||||
- **GIVEN** a recommended public macOS desktop release, **WHEN** the user downloads and opens the `.dmg`, **THEN** the app is signed and notarized so macOS does not report the download as damaged or from an unidentified developer.
|
||||
- **GIVEN** a recommended public Windows desktop release, **WHEN** the user runs the installer, **THEN** the installer is code signed to reduce SmartScreen trust warnings.
|
||||
|
||||
## Out of scope
|
||||
|
||||
|
||||
Reference in New Issue
Block a user