# Signed auto-update and code-signing certificates

Phase 3 alpha requires signed desktop updates (Windows + macOS). This document
is the procurement and wiring checklist. **No certificate is invented here.**
Until the secrets below exist in CI, Tauri produces unsigned artefacts and
the updater check no-ops if the endpoint has no matching signature.

## Two different signatures

| What | Why | Who issues it |
|---|---|---|
| **OS code signature** | SmartScreen (Windows) / Gatekeeper + notarisation (macOS) | Authenticode certificate; Apple Developer ID Application |
| **Tauri updater signature** | `tauri-plugin-updater` verifies the downloaded bundle before apply | Minisign keypair generated with `tauri signer generate` |

An Authenticode/Apple signature does **not** replace the updater pubkey in
`tauri.conf.json`. Both are required for a trustworthy auto-update.

## Tauri updater (wired in this repo)

- Plugin: `tauri-plugin-updater` + `tauri-plugin-process` (relaunch)
- Config: `apps/desktop/src-tauri/tauri.conf.json` → `plugins.updater`
- Capability: `updater:default` on the main window
- Frontend: `checkDesktopUpdates()` in `apps/web/src/platform/adapter.ts`
- Artefacts: `bundle.createUpdaterArtifacts: true`

Replace `plugins.updater.pubkey` with the **public** half of the minisign
keypair (`tauri signer generate`). The value currently in `tauri.conf.json` is
an all-zero placeholder so the schema validates; it cannot verify a real
update. Store the private key as CI secret `TAURI_SIGNING_PRIVATE_KEY`
(and password `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` if encrypted). Never
commit the private key.

Endpoint shape (placeholder until a releases bucket exists):

```
https://api-new.windshieldhub.com/updates/{{target}}/{{arch}}/{{current_version}}
```

The endpoint must serve Tauri's updater JSON (`version`, `platforms.*.url`,
`platforms.*.signature`).

## Windows Authenticode

1. Obtain an OV or EV code-signing certificate (DigiCert, Sectigo, SSL.com).
   EV reduces SmartScreen reputation time; OV works but users see warnings
   until the app builds reputation.
2. Store the PFX and password in a hardware token or CI secret
   (`WINDOWS_CERTIFICATE`, `WINDOWS_CERTIFICATE_PASSWORD`) — not in git.
3. Wire `tauri build` / `signtool` once the file is available. CI currently
   notes unsigned builds until then (`.github/workflows/ci.yml`).

Procurement lead time is often **days to weeks**. Start now (§10 step 3).

## macOS Developer ID + notarisation

1. Apple Developer Program membership (organisation, not personal, for a
   company-named app).
2. Developer ID Application certificate in the Mac build machine's keychain
   or as `APPLE_CERTIFICATE` / `APPLE_CERTIFICATE_PASSWORD` in CI.
3. App-specific password + Team ID for `notarytool`
   (`APPLE_ID`, `APPLE_PASSWORD`, `APPLE_TEAM_ID`).
4. Hardened runtime is already Tauri's default for macOS bundles.

OD-3 (WKWebView `getDisplayMedia`) is a separate hardware spike; signing does
not unblock it.

## Until certs land

- CI builds Windows MSI/NSIS and macOS app/dmg **unsigned**.
- Updater pubkey in config is a generated placeholder; production must
  rotate it before any signed channel is advertised.
- Do not ship an updater endpoint that serves unsigned bundles to clients
  that have a pubkey configured — verification will fail closed, which is
  correct.
