# Code Signing Setup This document explains how to configure code signing for Local Transcription so that Windows and macOS installers are trusted by the operating system. ## Overview Without code signing: - **Windows**: SmartScreen shows "Windows protected your PC" warnings - **macOS**: Gatekeeper blocks the app — "app can't be opened because it is from an unidentified developer" The CI/CD workflows are configured to sign automatically when the required secrets are present. Without secrets, builds still work — they just produce unsigned installers. --- ## Windows — Azure Artifact Signing **Cost**: ~$9.99/month (up to 5,000 signatures) ### 1. Create an Azure Account Sign up at https://azure.microsoft.com if you don't already have one. ### 2. Set Up Artifact Signing 1. In the Azure Portal, search for **Artifact Signing** 2. Create a new **Artifact Signing Account** - Choose a region (e.g., West US 2) — note this for the endpoint URL - The endpoint will be like `https://wus2.codesigning.azure.net/` 3. Complete **Identity Verification** (required before you can create certificate profiles) 4. Create a **Certificate Profile** with type "Public Trust" for code signing ### 3. Create an App Registration (Service Principal) This allows CI to authenticate to Azure: 1. Go to **Azure Active Directory** > **App registrations** > **New registration** 2. Name it (e.g., `local-transcription-signing`) 3. After creation, note the **Application (client) ID** and **Directory (tenant) ID** 4. Go to **Certificates & secrets** > **New client secret** — note the secret value 5. Grant the app registration the **Artifact Signing Certificate Profile Signer** role on your Artifact Signing Account ### 4. Add Gitea Secrets In your Gitea repository, go to **Settings** > **Actions** > **Secrets** and add: | Secret Name | Value | |-------------|-------| | `AZURE_CLIENT_ID` | App registration Application (client) ID | | `AZURE_CLIENT_SECRET` | App registration client secret value | | `AZURE_TENANT_ID` | Directory (tenant) ID | | `AZURE_SIGNING_ENDPOINT` | Artifact Signing endpoint URL (e.g., `https://wus2.codesigning.azure.net/`) | | `AZURE_SIGNING_ACCOUNT` | Artifact Signing account name | | `AZURE_CERT_PROFILE` | Certificate profile name | --- ## macOS — Apple Developer Code Signing + Notarization **Cost**: $99/year (Apple Developer Program) ### 1. Enroll in the Apple Developer Program Sign up at https://developer.apple.com/programs/ ### 2. Create a Developer ID Certificate 1. Open **Xcode** > **Settings** > **Accounts** > select your team > **Manage Certificates** 2. Click **+** > **Developer ID Application** 3. Or create via the Apple Developer portal: **Certificates, Identifiers & Profiles** > **Certificates** > **+** > **Developer ID Application** ### 3. Export the Certificate as .p12 1. Open **Keychain Access** 2. Find your **Developer ID Application** certificate 3. Right-click > **Export** > save as `.p12` with a password 4. Base64-encode it: ```bash base64 -i certificate.p12 | tr -d '\n' ``` ### 4. Create an App Store Connect API Key This is used for notarization (submitting the app to Apple for verification): 1. Go to https://appstoreconnect.apple.com/access/integrations/api 2. Click **Generate API Key** 3. Give it a name and **Developer** role (minimum) 4. Download the `.p8` private key file (you can only download it once) 5. Note the **Key ID** and **Issuer ID** shown on the page ### 5. Find Your Signing Identity Your signing identity looks like: ``` Developer ID Application: Your Name (TEAMID) ``` You can find it by running: ```bash security find-identity -v -p codesigning ``` ### 6. Add Gitea Secrets | Secret Name | Value | |-------------|-------| | `APPLE_CERTIFICATE` | Base64-encoded .p12 certificate (from step 3) | | `APPLE_CERTIFICATE_PASSWORD` | Password used when exporting the .p12 | | `APPLE_SIGNING_IDENTITY` | Full identity string (e.g., `Developer ID Application: Your Name (TEAMID)`) | | `APPLE_API_KEY` | App Store Connect API Key ID | | `APPLE_API_ISSUER` | API issuer UUID | | `APPLE_API_KEY_CONTENT` | Full contents of the `.p8` private key file | --- ## Verifying Signing Works ### Trigger a Build Both build workflows use `workflow_dispatch`, so you can trigger them manually in Gitea: 1. Go to **Actions** > select the workflow > **Run workflow** 2. Enter the release tag (e.g., `v2.0.15`) ### Check macOS After installing the `.dmg`, the app should open without any Gatekeeper warnings. You can also verify from the command line: ```bash codesign -dv --verbose=4 /Applications/Local\ Transcription.app spctl --assess --type execute /Applications/Local\ Transcription.app ``` ### Check Windows After running the `.msi` or `-setup.exe`, there should be no SmartScreen warning. The installer properties should show your organization name as the publisher.