rebreak-monorepo/docs/superpowers/specs/2026-06-16-magic-dashboard-ios-section-design.md

7.8 KiB
Raw Blame History

Magic Dashboard iOS-Section Redesign

Ziel

Das Magic-Dashboard soll klar zwischen zwei eigenen Bausteinen trennen:

  1. Desktop-Schutz (Mac/Windows) das Gerät, auf dem Magic läuft.
  2. iOS-Verwaltung (eigene iPhone/iPad-Geräte) registrierte iOS-Geräte des Users mit Status, Sternen und passenden Aktionen.

„Andere Geräte“ bleiben als sekundäre Information erhalten, sollen aber nicht den Fokus stehlen. Magic ist kein offenes Verwaltungstool für fremde Geräte.


Annahmen (aus dem Abstimmungsgespräch)

  • Backend-iOS-Geräte werden immer gelistet.
  • Wenn ein iPhone/iPad per USB verbunden ist, werden Live-Daten (Supervision, Enrollment, Sideload, App) mit dem passenden Backend-Eintrag synchronisiert.
  • Ein per USB verbundenes, aber im Backend unbekanntes iOS-Gerät wird als „Nicht erkennbar“ markiert. Der Hinweis verweist auf: ReBreak-App installieren → anmelden → Gerät registrieren. Erst danach ist es verwaltbar.
  • Supervise / Enroll / Sideload / App-Install bleiben im bestehenden Wizard (/detect, /supervise, /enroll, /sideload). Das Dashboard bietet nur den passenden Einstieg.

Seitenstruktur

status.vue
├── Header (Profil, Logout)
├── Section: Aktives Gerät (Desktop-Hero)
│   └── DeviceHeroCard für currentBackendDevice (mac/windows)
├── Section: Meine iOS-Geräte
│   ├── UnknownIosDeviceCard (falls USB-Device nicht im Backend)
│   └── IosDeviceCard[] für jedes Backend-iOS-Gerät
│       (Sterne + Status + Action-Button)
├── Section: Weitere Geräte
│   └── DeviceListItem[] für sonstige Backend-Geräte
└── DeviceDetailSheet (weiterhin für Details/Cooldown)

Neue Komponenten

IosDeviceSection.vue

  • Props:
    • devices: ComputedDevice[] alle Backend-iOS-Geräte des Users
    • iphone: IphoneDeviceState | null aktuell per USB erkanntes Gerät
    • loading: boolean
  • Zeigt den Section-Header und rendert die Liste von IosDeviceCards.
  • Wenn iphone verbunden, aber kein passendes Backend-Gerät gefunden wird, wird UnknownIosDeviceCard angezeigt.
  • Wenn noch keine Backend-iOS-Geräte geladen wurden: Hinweis „Keine iOS-Geräte geladen“ + Aktualisieren-Button.
  • Wenn geladen und leer: Hinweis „Keine iOS-Geräte registriert. ReBreak-App installieren und Gerät hinzufügen.“

IosDeviceCard.vue

  • Props:
    • device: ComputedDevice
    • iphone: IphoneDeviceState | null falls dieses Gerät per USB verbunden ist
    • isConnected: boolean
  • Zeigt:
    • Name/Modell
    • Status-Badge (active, pending, unprotected etc.)
    • Letzte Sichtung
    • IosStarRating + detaillierte Sternen-Liste, wenn isConnected
    • Sonst Hinweis: „Zum Live-Status iPhone per USB verbinden“
  • Action-Button (ableitet sich aus dem gemergten Zustand):
    • Nicht supervised → „Supervisen" → /supervise
    • Supervised, aber Enrollment fehlt → „Enrollen" → /enroll
    • Enrollment vorhanden, aber Sideload-Profil fehlt → „Sideload installieren" → /sideload
    • Sideload vorhanden, aber App fehlt → „App installieren" (MDM-Befehl oder Link)
    • Alles okay → „Synchronisieren" (prüft Enrollment-, Sideload- und Supervision-Status; bei Abweichungen werden fehlende Profile/MDM-Kommandos gepusht; falls die lokale MDM-Version hinter der aktuellen ReBreak-MDM-Version zurückfällt, wird ein Update gepusht und der User informiert)
    • Während der 3-Tage-Kündigungs-Grace-Period → „ReBreak entfernen" (löst Offboarding aus: MDM-Profile entfernen, Gerät unsupervised setzen, Eintrag bereinigen)

UnknownIosDeviceCard.vue

  • Props:
    • iphone: IphoneDeviceState
  • Zeigt:
    • Warn-Icon + „Dieses iPhone ist nicht erkennbar"
    • Modell, iOS-Version, UDID (nur zur Info)
    • Hinweis: „Mit keinem ReBreak-Konto verbunden. Um es zu verwalten: ReBreak-App installieren, anmelden und Gerät registrieren."
    • Keine Supervise-/Enroll-Aktionen.

Datenfluss

  1. User klickt in status.vue auf Aktualisieren.
  2. protection.refresh() wird aufgerufen:
    • detectIphoneState() lädt das per USB verbundene iOS-Gerät.
    • getMagicDevices() lädt alle Backend-Geräte in den shared useMagicDevices-State.
  3. useDeviceStatus liefert weiterhin:
    • currentBackendDevice (Desktop)
    • otherDevices (alles außer current)
  4. IosDeviceSection erhält die Liste aller otherDevices, filtert intern auf platform === 'ios' und versucht, das verbundene iphone per Modell + Name zuzuordnen.
  5. Action-Buttons leiten den User basierend auf dem gemergten Live-Status in den passenden Wizard-Schritt weiter.

iOS-Matching

Da Backend-deviceId (Capacitor-UUID) nicht mit USB-UDID übereinstimmt, erfolgt das Matching über:

  • device.model (Backend) ↔ iphone.productType (USB)
  • device.name (Backend) ↔ iphone.name (USB) als Fallback / Verfeinerung

Sind mehrere Geräte mit identischem Modell vorhanden, wird das erste passende (name match) als verbunden markiert; bei Unklarheit wird das iphone nicht zugeordnet und erscheint als UnknownIosDeviceCard.


Bestehende Komponenten Anpassungen

DeviceHeroCard.vue

  • Keine iOS-Sterne mehr anzeigen (showIosStars bleibt aber für zukünftige Flexibilität).
  • Aktionen bleiben auf Desktop-Schutz beschränkt.

DeviceListItem.vue

  • Wird für „Weitere Geräte“ (andere Desktops) weiterverwendet.
  • iOS-Geräte verschwinden aus dieser Liste und werden in der neuen iOS-Section angezeigt.

DeviceDetailSheet.vue

  • iOS-Sterne-Anzeige gilt für jedes iOS-Gerät, das gerade per USB verbunden ist (nicht nur isCurrent, da iOS-Geräte nie „current" sind).
  • Cooldown-Steuerung bleibt nur für isCurrent-Desktop-Geräte.

useDeviceStatus.ts

  • Entfernt den Debug-watchEffect (bereits erledigt).
  • Fügt optional iosDevices und desktopDevices als getrennte Derived Lists hinzu, damit status.vue weniger Filter-Logik enthält.

On-Demand-Verhalten bleibt erhalten

  • Kein automatisches Polling mehr.
  • Sterne/Status werden nur beim manuellen Refresh aktualisiert.
  • Das verhindert erneut Log-Spam durch wiederholte detect_iphone_state-Aufrufe.

Fehlerbehandlung

  • Wenn detectIphoneState fehlschlägt: Fehler nur in protection.lastError; iOS-Section zeigt Backend-Liste weiterhin an.
  • Wenn getMagicDevices fehlschägt: error-Banner in status.vue.
  • Wenn Matching mehrdeutig: UnknownIosDeviceCard statt falscher Zuordnung.

Kündigungs-Grace-Period & Offboarding

  • Solange das Gerät enrolled ist und das Abo aktiv ist, wird nichts deinstalliert.
  • Nach einer Kündigung bleibt das iOS-Gerät für 3 Tage in der Liste sichtbar.
  • Der Button „ReBreak entfernen" ist unsichtbar oder disabled, solange die Grace-Period noch nicht begonnen hat.
  • Sobald die Grace-Period läuft, erscheint der Button ohne zusätzliche Sicherheitsabfrage.
  • Ein Klick darauf startet das Offboarding:
    1. MDM-Enrollment-Profil und Sideload-Profil vom Gerät entfernen.
    2. Gerät aus dem Supervised-Modus zurücksetzen.
    3. Backend-Eintrag für das iOS-Gerät bereinigen.
  • Backend-Abhängigkeit: Es braucht ein Feld/Endpoint, der die Kündigung + verbleibende Grace-Period erkennbar macht (z. B. subscriptionCancelledAt im Profil oder dedizierter /api/magic/subscription-status). Das Offboarding selbst braucht einen neuen API-Endpoint oder Tauri-Command, der MDM-Remove + Unsupervise orchestriert.

Offene Punkte / Nächste Schritte

  1. Existiert bereits ein Backend-Feld/Endpoint für Kündigung + Grace-Period, oder muss der gebaut werden?
  2. Wie wird die „aktuelle ReBreak-MDM-Version" bestimmt ist sie im Profil hinterlegt, im Backend konfiguriert oder über eine Tauri-Funktion verfügbar?
  3. Soll die App-Installation via MDM direkt aus dem Dashboard auslösbar sein, oder reicht ein Verweis auf /sideload?