diff --git a/apps/browser/.gitignore b/apps/browser/.gitignore index 077bd14..46a4faa 100644 --- a/apps/browser/.gitignore +++ b/apps/browser/.gitignore @@ -10,3 +10,7 @@ release # Compiled scripts (TypeScript sources in scripts-src/) scripts/*.js + +# Environment variables (contains sensitive data) +.env.local +.env.*.local diff --git a/apps/browser/CODESIGN_SETUP.md b/apps/browser/CODESIGN_SETUP.md new file mode 100644 index 0000000..772bf08 --- /dev/null +++ b/apps/browser/CODESIGN_SETUP.md @@ -0,0 +1,212 @@ +# Code Signing and Notarization Setup Guide + +This document explains how to set up code signing and notarization for distributing aka-browser on macOS. + +## 1. Create Developer ID Application Certificate + +### 1-1. Generate CSR (Certificate Signing Request) + +1. Open **Keychain Access** app +2. Menu: **Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority...** +3. Enter the following information: + - User Email Address: Your Apple Developer account email + - Common Name: Your name + - CA Email Address: Leave empty + - Select **"Saved to disk"** + - Check **"Let me specify key pair information"** +4. Choose save location (e.g., `~/Desktop/CertificateSigningRequest.certSigningRequest`) +5. Key Size: **2048 bits**, Algorithm: **RSA** +6. Click **Continue** + +### 1-2. Issue Certificate from Apple Developer Website + +1. Visit https://developer.apple.com/account/resources/certificates/list +2. Click **"+"** button +3. Select **"Developer ID Application"** (for distribution outside Mac App Store) +4. Click **Continue** +5. Upload the CSR file created above +6. Click **Continue** +7. Download certificate (`.cer` file) +8. **Double-click** the downloaded file to install it in Keychain + +### 1-3. Verify Certificate + +Verify the certificate is installed by running this command in Terminal: + +```bash +security find-identity -v -p codesigning +``` + +You should see output like: +``` +1) XXXXXX "Developer ID Application: Your Name (TEAM_ID)" +``` + +## 2. Generate App-Specific Password + +An App-Specific Password is required for notarization. + +1. Visit https://appleid.apple.com/account/manage +2. **Sign in** (Two-factor authentication required) +3. Click **App-Specific Passwords** in the **Security** section +4. Click **"+"** button +5. Enter a name (e.g., "aka-browser notarization") +6. Copy the generated password (e.g., `abcd-efgh-ijkl-mnop`) +7. **Save it securely** (you won't be able to see it again) + +## 3. Find Your Team ID + +1. Visit https://developer.apple.com/account +2. Find your **Team ID** in the **Membership Details** section (e.g., `AB12CD34EF`) + +## 4. Set Environment Variables + +### 4-1. Method 1: .env File (Recommended) + +Create a `.env.local` file in the project root: + +```bash +# /Users/hm/Documents/GitHub/aka-browser/apps/browser/.env.local +APPLE_ID=your-apple-id@example.com +APPLE_APP_SPECIFIC_PASSWORD=abcd-efgh-ijkl-mnop +APPLE_TEAM_ID=AB12CD34EF +``` + +**Warning**: Add `.env.local` to `.gitignore` to prevent committing it to Git! + +### 4-2. Method 2: System Environment Variables + +Add to `~/.zshrc` or `~/.bash_profile`: + +```bash +export APPLE_ID="your-apple-id@example.com" +export APPLE_APP_SPECIFIC_PASSWORD="abcd-efgh-ijkl-mnop" +export APPLE_TEAM_ID="AB12CD34EF" +``` + +After saving: +```bash +source ~/.zshrc +``` + +### 4-3. Method 3: Specify During Build + +```bash +APPLE_ID="your@email.com" \ +APPLE_APP_SPECIFIC_PASSWORD="abcd-efgh-ijkl-mnop" \ +APPLE_TEAM_ID="AB12CD34EF" \ +pnpm run package +``` + +## 5. Build and Notarize + +### 5-1. Install Dependencies + +```bash +cd /Users/hm/Documents/GitHub/aka-browser/apps/browser +pnpm install +``` + +### 5-2. Compile Build Scripts + +```bash +pnpm run build:scripts +``` + +### 5-3. Build and Notarize App + +```bash +pnpm run package +``` + +Build process: +1. ✅ Build app +2. ✅ EVS signing (Widevine CDM) +3. ✅ Code signing (Developer ID Application) +4. ✅ Notarization (upload to Apple servers) +5. ✅ DMG creation + +### 5-4. Verify Notarization + +After the build completes, verify notarization status with: + +```bash +spctl -a -vv -t install release/mac-arm64/aka-browser.app +``` + +Successful output: +``` +release/mac-arm64/aka-browser.app: accepted +source=Notarized Developer ID +``` + +## 6. Troubleshooting + +### Cannot Find Certificate + +``` +Error: Cannot find identity matching "Developer ID Application" +``` + +**Solution**: +1. Verify the certificate is installed in Keychain +2. Check if the certificate has expired +3. Run `security find-identity -v -p codesigning` to verify + +### Notarization Failed + +``` +Error: Notarization failed +``` + +**Solution**: +1. Verify Apple ID, App-Specific Password, and Team ID are correct +2. Ensure two-factor authentication is enabled +3. Check if App-Specific Password is valid (it may have expired) + +### Check Notarization Logs + +```bash +xcrun notarytool log --apple-id "your@email.com" \ + --password "abcd-efgh-ijkl-mnop" \ + --team-id "AB12CD34EF" \ + +``` + +## 7. Distribution + +Notarized DMG files are created in the `release/` directory: + +- `release/aka-browser-0.1.0-arm64.dmg` (Apple Silicon) +- `release/aka-browser-0.1.0-x64.dmg` (Intel) +- `release/aka-browser-0.1.0-universal.dmg` (Universal) + +You can upload these files to the internet for distribution. Users won't see the "damaged" message when downloading and installing. + +## 8. Security Precautions + +- ❌ **NEVER commit to Git**: + - App-Specific Password + - `.env.local` file + - Certificate files (`.p12`, `.cer`) + +- ✅ **Store securely**: + - Use password managers like 1Password or Bitwarden + - Use encrypted channels when sharing with team members + +## 9. CI/CD Setup (GitHub Actions) + +Add the following variables to GitHub Secrets: + +- `APPLE_ID` +- `APPLE_APP_SPECIFIC_PASSWORD` +- `APPLE_TEAM_ID` +- `CSC_LINK` (certificate `.p12` file encoded in base64) +- `CSC_KEY_PASSWORD` (certificate password) + +For detailed setup, refer to the electron-builder documentation: +https://www.electron.build/code-signing + +--- + +**Questions**: Please create an issue if you encounter any problems. diff --git a/apps/browser/CODESIGN_START.md b/apps/browser/CODESIGN_START.md new file mode 100644 index 0000000..48eae34 --- /dev/null +++ b/apps/browser/CODESIGN_START.md @@ -0,0 +1,106 @@ +# Quick Start Guide + +## 🚀 Get Started Now + +### 1. Issue Developer ID Application Certificate + +**Takes 5 minutes** + +1. https://developer.apple.com/account/resources/certificates/list +2. Click "+" button → Select "Developer ID Application" +3. Upload CSR file (generate using method below) +4. Download and double-click to install + +**How to generate CSR:** +``` +Keychain Access app → Menu → Keychain Access → Certificate Assistant → Request a Certificate from a Certificate Authority... +→ Enter email → Select "Saved to disk" → Save +``` + +### 2. Generate App-Specific Password + +**Takes 2 minutes** + +1. https://appleid.apple.com/account/manage +2. Security → App-Specific Passwords → "+" button +3. Enter name (e.g., "aka-browser") → Generate +4. **Copy password** (you won't be able to see it again!) + +### 3. Find Your Team ID + +**Takes 1 minute** + +1. https://developer.apple.com/account +2. Membership Details → Copy Team ID (e.g., `AB12CD34EF`) + +### 4. Set Environment Variables + +Create a `.env.local` file in the project root: + +```bash +# /Users/hm/Documents/GitHub/aka-browser/apps/browser/.env.local +APPLE_ID=your-apple-id@example.com +APPLE_APP_SPECIFIC_PASSWORD=abcd-efgh-ijkl-mnop +APPLE_TEAM_ID=AB12CD34EF +``` + +**Or** run directly in terminal: + +```bash +export APPLE_ID="your-apple-id@example.com" +export APPLE_APP_SPECIFIC_PASSWORD="abcd-efgh-ijkl-mnop" +export APPLE_TEAM_ID="AB12CD34EF" +``` + +### 5. Build and Notarize + +```bash +cd /Users/hm/Documents/GitHub/aka-browser/apps/browser +pnpm run package +``` + +**Build process (approx. 5-10 minutes):** +1. ✅ Build app +2. ✅ EVS signing (Widevine) +3. ✅ Code signing +4. ✅ Notarization (upload to Apple servers) +5. ✅ DMG creation + +### 6. Done! + +Generated file: `release/aka-browser-0.1.0-arm64.dmg` + +You can now upload this file to the internet for distribution. +Users won't see the **"damaged"** message when downloading! ✨ + +--- + +## 🔍 Verify Notarization + +```bash +spctl -a -vv -t install release/mac-arm64/aka-browser.app +``` + +On success: +``` +accepted +source=Notarized Developer ID +``` + +--- + +## ❓ Troubleshooting + +### Cannot Find Certificate +```bash +security find-identity -v -p codesigning +``` +→ Check if "Developer ID Application" certificate exists + +### Notarization Failed +- Verify Apple ID, Password, and Team ID are correct +- Ensure two-factor authentication is enabled + +--- + +**For detailed instructions**: See `CODESIGN_SETUP.md` diff --git a/apps/browser/package.json b/apps/browser/package.json index 9ca6384..2179953 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -32,6 +32,7 @@ "author": "hmmhmmhm", "license": "MIT", "devDependencies": { + "@electron/notarize": "^2.5.0", "@tailwindcss/vite": "^4.1.14", "@types/node": "^20.11.0", "@types/react": "^19.2.2", @@ -39,6 +40,7 @@ "@vitejs/plugin-react": "^5.0.4", "concurrently": "^8.2.2", "cross-env": "^10.1.0", + "dotenv": "^17.2.3", "electron": "github:castlabs/electron-releases#v38.0.0+wvcus", "electron-builder": "^26.0.12", "tailwindcss": "^4.1.14", @@ -66,11 +68,15 @@ "!node_modules/**/*" ], "afterPack": "scripts/evs-sign.js", + "afterSign": "scripts/notarize.js", "mac": { "target": [ { "target": "dmg", - "arch": ["x64", "arm64"] + "arch": [ + "x64", + "arm64" + ] } ], "category": "public.app-category.developer-tools", @@ -78,8 +84,7 @@ "hardenedRuntime": true, "gatekeeperAssess": false, "entitlements": "build/entitlements.mac.plist", - "entitlementsInherit": "build/entitlements.mac.plist", - "identity": null + "entitlementsInherit": "build/entitlements.mac.plist" }, "win": { "target": "nsis", diff --git a/apps/browser/scripts-src/notarize.ts b/apps/browser/scripts-src/notarize.ts new file mode 100644 index 0000000..eaa5fa9 --- /dev/null +++ b/apps/browser/scripts-src/notarize.ts @@ -0,0 +1,44 @@ +import { notarize } from '@electron/notarize'; +import * as path from 'path'; +import * as dotenv from 'dotenv'; + +// Load .env.local file +dotenv.config({ path: path.join(__dirname, '..', '.env.local') }); + +export default async function notarizing(context: any) { + const { electronPlatformName, appOutDir } = context; + + // Only notarize on macOS + if (electronPlatformName !== 'darwin') { + return; + } + + // Check environment variables + const appleId = process.env.APPLE_ID; + const appleIdPassword = process.env.APPLE_APP_SPECIFIC_PASSWORD; + const teamId = process.env.APPLE_TEAM_ID; + + if (!appleId || !appleIdPassword || !teamId) { + console.warn('⚠️ Skipping notarization. Please set environment variables:'); + console.warn(' APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID'); + return; + } + + const appName = context.packager.appInfo.productFilename; + const appPath = path.join(appOutDir, `${appName}.app`); + + console.log(`🔐 Starting notarization: ${appPath}`); + + try { + await notarize({ + appPath, + appleId, + appleIdPassword, + teamId, + }); + console.log('✅ Notarization completed!'); + } catch (error) { + console.error('❌ Notarization failed:', error); + throw error; + } +} diff --git a/apps/browser/scripts/notarize.d.ts b/apps/browser/scripts/notarize.d.ts new file mode 100644 index 0000000..c04f366 --- /dev/null +++ b/apps/browser/scripts/notarize.d.ts @@ -0,0 +1 @@ +export default function notarizing(context: any): Promise; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55d8485..cb27c4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,9 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) devDependencies: + '@electron/notarize': + specifier: ^2.5.0 + version: 2.5.0 '@tailwindcss/vite': specifier: ^4.1.14 version: 4.1.14(vite@7.1.11(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)) @@ -51,6 +54,9 @@ importers: cross-env: specifier: ^10.1.0 version: 10.1.0 + dotenv: + specifier: ^17.2.3 + version: 17.2.3 electron: specifier: github:castlabs/electron-releases#v38.0.0+wvcus version: https://codeload.github.com/castlabs/electron-releases/tar.gz/678b5c7761825c5af936f5c67a9101f3fc6ab750 @@ -1095,6 +1101,10 @@ packages: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} + dotenv@17.2.3: + resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} + engines: {node: '>=12'} + dotenv@9.0.2: resolution: {integrity: sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==} engines: {node: '>=10'} @@ -2455,7 +2465,7 @@ snapshots: '@babel/parser': 7.28.4 '@babel/template': 7.27.2 '@babel/types': 7.28.4 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -3513,6 +3523,8 @@ snapshots: dotenv@16.6.1: {} + dotenv@17.2.3: {} + dotenv@9.0.2: {} dunder-proto@1.0.1: