# ReBreak Magic Mac-App — Phase 2: Backend-Auth-Integration ## ✅ Implementierte Features ### 1. Auth-Stack (bereits implementiert) - ✅ `AuthService.swift` — Supabase-Login + Keychain-Persistence - ✅ `KeychainStore` — in AuthService integriert (Service: `org.rebreak.magic`) - ✅ `MagicAPIClient.swift` — Backend-API-Client für `/api/magic/*` - ✅ `MacDeviceDetector.swift` — IOPlatformUUID + hwModel via IOKit/sysctl - ✅ `MacProfileInstaller.swift` — Profile-Download + Installation via `profiles` command ### 2. Login-UI (bereits implementiert) - ✅ `LoginView.swift` — Email/Passwort-Login - ✅ Error-Handling für InvalidCredentials - ✅ Link zu "Noch kein Account? rebreak.org/signup" - ✅ Integration in `ContentView.swift` via `model.showingLogin` ### 3. Mac-Registration-Flow (NEU implementiert) - ✅ **Neuer WizardStep `.macRegistration`** (rawValue 0, vor .welcome) - ✅ **`MacRegistrationView.swift`** — UI für Mac-Device-Registrierung: - Zeigt Mac-Info (hostname, model, deviceId via IOPlatformUUID) - Button "Mac registrieren" → ruft `model.registerMac()` - Auto-Download + Installation des DNS-Filter-Profils - Limit-Reached-Handling → öffnet `ManageBindingsView` (via `model.showingManageBindings`) - Bei Erfolg: "Weiter → iPhone-Setup" button - ✅ Integration in `ContentView.swift` switch-case - ✅ `WizardModel.swift` erweitert: - Initial-Step: `.macRegistration` statt `.welcome` - `reset()` setzt auch `magicRegistration = nil` und `registrationError = nil` ### 4. Menu-Erweiterung - ✅ Neues Command-Menu "Account" mit "Abmelden" (⌘⇧L) - ✅ `handleLogout()` in WizardModel ruft `AuthService.signOut()` + reset ### 5. Workflow-Integration **Neuer Flow:** 1. App startet → `authState` aus Keychain laden 2. Wenn kein Auth → `LoginView` 3. Nach Login → `.macRegistration` (Mac registrieren + Profil installieren) 4. Nach Mac-Setup → `.welcome` (iPhone-Detection wie bisher) 5. Rest unverändert: preflight → supervise → enroll → configure → done ## 📂 Neue Files - ✅ `Sources/Views/MacRegistrationView.swift` (218 Zeilen) ## 📝 Geänderte Files 1. **`Sources/Models/WizardStep.swift`** - Neuer Case `.macRegistration = 0` - `.welcome` wurde von rawValue 0 → 1 (alle anderen +1) - Titel: "Mac registrieren" 2. **`Sources/Models/WizardModel.swift`** - Initial-Step: `var step: WizardStep = .macRegistration` - `reset()` erweitert: setzt `magicRegistration = nil`, `registrationError = nil` - Syntax-Fix: entfernte orphaned code-fragments 3. **`Sources/Views/ContentView.swift`** - Switch-Case erweitert: `case .macRegistration: MacRegistrationView()` 4. **`Sources/Views/LoginView.swift`** - macOS-Kompatibilität: `.textInputAutocapitalization(.never)` entfernt (iOS-only) 5. **`Sources/RebreakMagicApp.swift`** - Neues Command-Menu "Account" mit "Abmelden" ## ⚙️ Config-Anforderungen User muss `~/.config/rebreak-magic/config.json` erstellen (siehe `config.example.json`): ```json { "supabaseUrl": "https://your-project.supabase.co", "supabaseAnonKey": "your-supabase-anon-key", "backendBaseUrl": "https://staging.rebreak.org", "mdmServer": "https://mdm.rebreak.org", "mdmUser": "admin", "mdmApiKey": "your-nanomdm-api-key" } ``` **Benötigte Werte:** - `supabaseUrl` + `supabaseAnonKey` — von Supabase-Dashboard - `backendBaseUrl` — staging: `https://staging.rebreak.org`, prod: `https://api.rebreak.org` - `mdmServer`, `mdmUser`, `mdmApiKey` — für iPhone-MDM-Commands (nur wenn iPhone-Setup durchgeführt wird) ## 🏗 Build-Status ✅ **BUILD SUCCEEDED** ```bash cd apps/rebreak-magic-mac xcodegen generate xcodebuild -project RebreakMagic.xcodeproj -scheme RebreakMagic -configuration Debug build ``` **Warnings (harmlos):** - `no 'async' operations occur within 'await' expression` bei `MainActor.run` (expected, korrekt) ## 📋 Login-Flow-Ablauf 1. **App-Start** - `WizardModel.init()` lädt `authSession = AuthService.shared.currentSession()` - Falls `authSession == nil` → `showingLogin = true` 2. **LoginView** - User gibt Email + Passwort ein - `AuthService.signIn()` → Supabase `/auth/v1/token` - Bei Erfolg: Session in Keychain speichern - `model.handleLogin(session)` setzt `showingLogin = false` 3. **MacRegistrationView** (neuer Step) - Liest Mac-Info via `MacDeviceDetector.detect()` - Button "Mac registrieren" → `model.registerMac()` - API: `POST /api/magic/register` mit `{ deviceId, hostname, model, osVersion }` - Response: `{ dnsToken, profileUrl, existing }` - Auto-Download: `MagicAPIClient.downloadProfile(token)` → tmp-File - Auto-Install: `MacProfileInstaller.downloadAndInstall()` → `profiles install -path ` - Bei Limit-Reached (409): öffnet `ManageBindingsView` (Sheet) - Bei Erfolg: "Weiter → iPhone-Setup" → `model.advance()` zu `.welcome` 4. **Rest des Wizards** (unverändert) - `.welcome` — iPhone-Detection - etc. ## 🔒 Security-Hinweise - **Keychain-Service**: `org.rebreak.magic` (Account: User-Email) - **JWT-Tokens**: Access + Refresh-Token in Keychain - **Token-Refresh**: Auto-Refresh bei Expiry via `AuthService.refreshSessionIfNeeded()` - **Config-File**: chmod 600 auf `~/.config/rebreak-magic/config.json` empfohlen ## 🚧 Bekannte Limitations / TODOs 1. **Profile-Installation benötigt User-Interaktion** - `profiles install` auf macOS öffnet evtl. System-Settings-Dialog - User muss Profil manuell bestätigen (macOS-Security-Policy) - TODO: Anleitung in UI zeigen falls Installation fehlschlägt 2. **Keine Profile-Signierung** - Unsigned Profiles triggern macOS-Warnung - TODO: Apple-Developer-Cert für Profil-Signierung (Phase 3) 3. **Device-ID-Persistence** - IOPlatformUUID ist Hardware-UUID, bleibt stabil - Bei Mac-Hardware-Reset ändert sich UUID → neues Device im Backend - Akzeptabel für jetzt 4. **Keine Tests** - Unit-Tests für AuthService, MagicAPIClient kommen in Phase 3 5. **Offline-Handling** - Bei Netzwerkfehler: Error-Message, aber kein Retry-Button - User muss App neu starten oder "Erneut registrieren" clicken ## 📊 Code-Statistik - **Neue Files**: 1 (`MacRegistrationView.swift`, 218 LOC) - **Geänderte Files**: 5 (WizardStep, WizardModel, ContentView, LoginView, RebreakMagicApp) - **Bestehende Services** (nicht geändert): AuthService, MagicAPIClient, MacDeviceDetector, MacProfileInstaller, ManageBindingsView ## 🎯 Nächste Schritte (optional für User) 1. **Config erstellen**: `cp config.example.json ~/.config/rebreak-magic/config.json` + Werte eintragen 2. **Supabase-Projekt**: URL + Anon-Key aus Supabase-Dashboard 3. **Test-Account**: User in Supabase anlegen (via Supabase-Dashboard oder Backend-Signup) 4. **App starten**: Xcode → Run, Login-Flow testen 5. **Mac-Registrierung testen**: Device-Limit-Check (max 3 Devices) 6. **Profil prüfen**: `profiles show -type configuration` → sollte `org.rebreak.protection.profile.*` enthalten ## ✨ Bonus-Feature (bereits implementiert) - ✅ **ManageBindingsView** — zeigt eigene Magic-Bindings + Release-Button - ✅ Erreichbar via Sheet wenn Limit-Reached - ✅ 24h-Cooldown-Handling für Release-Requests