mana-swift-event-sync/Sources/ManaEventSync/Engine/SyncConsent.swift
Till JS e574bc55d6 Cloud-Sync-Opt-in-Gate (Art. 25) — Parität zur Web-App
Native synct bisher per Default beim Login, Web ist Opt-in. Neues
EventSyncConfig.requireSyncConsent (Default false → abwärtskompatibel):
ist es gesetzt, läuft die Engine ohne explizite Einwilligung lokal-only
(authMode() → anonymous trotz JWT, kein Egress, Outbox staut). Einwilligung
beim start() aus mana-auth /api/v1/settings (gleiche Quelle wie Web),
setSyncConsent(_:) als Konto-Toggle (true claimt+startet wie signIn, false
stoppt Server-Sync; lokale Daten bleiben). + syncConsentRequired/hasSyncConsent.

Tests: SyncConsentTests (6) grün, volle Suite ohne Regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:09:25 +02:00

27 lines
1 KiB
Swift

import Foundation
/// Liest die Cloud-Sync-Einwilligung aus einer mana-auth
/// `GET /api/v1/settings`-Antwort. Reihenfolge identisch zur Web-App
/// (`sync.svelte.ts`): **App-Override vor globaler Präferenz**, fehlend =
/// nicht eingewilligt (Opt-in, DSGVO Art. 25).
///
/// Erwartetes Shape (Teilmenge):
/// ```json
/// {
/// "globalSettings": { "sync": { "enabled": true } },
/// "appOverrides": { "pageta": { "sync": { "enabled": false } } }
/// }
/// ```
///
/// Pure Funktion (kein I/O) — direkt testbar.
func parseSyncConsent(fromSettingsJSON data: Data, appId: String) -> Bool {
guard let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
return false
}
func enabled(in container: [String: Any]?) -> Bool? {
(container?["sync"] as? [String: Any])?["enabled"] as? Bool
}
let appOverride = enabled(in: (root["appOverrides"] as? [String: Any])?[appId] as? [String: Any])
let global = enabled(in: root["globalSettings"] as? [String: Any])
return appOverride ?? global ?? false
}