Neue opt-in Policy verhindert Logout durch einen einzelnen transienten
/refresh-Fehler beim Cold-Launch. Default-Verhalten unverändert.
- `RefreshFailurePolicy.immediateWipe` (Default) — wie bisher: jeder
invalidierende Server-Response → keychain.wipe() + .signedOut.
- `RefreshFailurePolicy.softFirst` — erster invalidierender Fehler
im Prozess wird nicht gewiped, Session bleibt. Wipe erst beim
zweiten Fehler oder nach einem zuvor erfolgreichen Refresh im
selben Prozess.
Plus erweiterte Diagnostik in refreshAccessToken(): jeder Attempt
loggt Token-Länge, once-succeeded, failure-count, policy, und bei
Failure HTTP-Status + Body-Excerpt (256 chars). Subsystem ev.mana.core.
Pageta-native ist erster Konsument (opt-in `.softFirst`) wegen
wiederholten TestFlight-Update-Logouts — Hypothese: transienter
Server-Glitch beim ersten Refresh nach Cold-Launch.
89/89 Tests (vorher 85/85), 4 neue für die Policy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Native-Apps werden gegen mana-auth-Downtime gehärtet und können
einen anonymen Local-First-Modus anbieten. Komplett additiv.
AuthClient.Status um `.guest(id: String)` erweitert — persistente
lokale UUID ohne Server-Account, gleichberechtigt mit `.signedIn` als
"App ist nutzbar"-Zustand.
Neue Methoden:
- enterGuestMode() throws -> String — idempotent
- currentGuestId() -> String?
- clearGuestId()
- signOut(keepGuestMode: Bool = false) — Default-Verhalten unverändert
KeychainStore.Key.guestId neu. wipe() löscht nur Session-Felder
(accessToken/refreshToken/email); Guest-ID überlebt. Für komplettes
Vergessen: neue wipeAll().
refreshAccessToken() wipt nicht mehr blind bei jedem Nicht-200.
Heuristik via AuthError.invalidatesSession:
- Wipe bei invalidCredentials/unauthorized/tokenExpired/tokenInvalid/
emailNotVerified — Session ist tatsächlich tot.
- Behalten bei serviceUnavailable/serverInternal/networkFailure/
rateLimited — Apps werden bei mana-auth-Downtime nicht mehr in
Login geworfen.
Beim Wipe fällt der Status auf .guest(id) zurück, falls eine
Guest-Identität existiert; sonst auf .signedOut.
Tests:
- Mock-Setup auf per-test-ID-Routing migriert (analog mana-swift-ui),
löst Cross-Suite-Pollution zwischen AuthClient+Account und
AuthClient Guest-Mode + Resilience.
- 15 neue Tests für Guest-Mode + Refresh-Resilience.
- 54/54 Tests grün.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>