chahinebrini 77edd67cbe fix(magic): explicit imports + staging defaults + sheet height
- backend/api/magic/register: explicit import of MAGIC_DEVICE_LIMIT
  and createAdGuardClient (Nitro auto-import was missing them
  → ReferenceError → HTTP 500 on /api/magic/register)
- mac-app: default backendBaseUrl falls back to staging.rebreak.org
  (app.rebreak.org serves wrong TLS cert)
- native MagicSheet: fallback download/dmg URLs point to staging
- native settings: Magic sheet capped at detents=[0.85] so AppHeader
  stays visible
- bundles all in-flight Magic feature work (pair create/redeem,
  device endpoints, schema, adguard utils, mac-app, locales)
2026-06-03 08:25:02 +02:00

185 lines
7.1 KiB
Markdown

# 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 <url>`
- 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