import 'package:matrix/matrix.dart'; import 'package:pyramid/core/auth_log.dart'; /// Wendet einen Soft-Logout durch Token-Refresh ab, ohne JE in einen /// destruktiven Logout zu eskalieren. /// /// Hintergrund: Ohne gesetztes `Client.onSoftLogout` behandelt das matrix-SDK /// einen fehlgeschlagenen Refresh so: catch → `logout()` → `finally clear()` — /// die lokale Session inkl. Krypto-Schlüssel wird also selbst dann zerstört, /// wenn der Refresh nur an einem transienten Netzwerkfehler scheiterte /// (Gerät offline im Moment des Token-Ablaufs) oder am Rotations-Race mit dem /// Push-Hintergrund-Isolate (beide teilen sich die DB; refreshAccessToken() /// liest den Refresh-Token bei jedem Versuch frisch aus der DB, deshalb heilt /// ein Retry dieses Race). Wirft dieser Handler nicht, ruft das SDK auch kein /// `logout()` auf (Client._handleSoftLogout, matrix 6.2.0). /// /// Regel aus CLAUDE.md: Fehlerpfade dürfen NIE in einem stillen Logout enden. /// Schlägt der Refresh dauerhaft fehl, bleibt der Client im Zustand /// soft-logged-out; der nächste Sync/API-Aufruf stößt den Refresh erneut an. Future guardedSoftLogoutRefresh(Client client) async { for (var attempt = 1; attempt <= 3; attempt++) { try { await client.refreshAccessToken(); await AuthLog.write( 'Soft-Logout durch Token-Refresh abgewendet (Versuch $attempt)', ); return; } catch (e) { await AuthLog.write( 'Soft-Logout: Token-Refresh fehlgeschlagen (Versuch $attempt/3): $e', ); if (attempt < 3) { await Future.delayed(Duration(seconds: 2 * attempt)); } } } await AuthLog.write( 'Soft-Logout: Refresh dauerhaft fehlgeschlagen – Session wird NICHT ' 'zerstört, nächster Sync/API-Aufruf versucht es erneut.', ); }