Bis jetzt haben die mana-Apps `keychainAccessGroup: nil` gesetzt;
Apple legt das Item dann im default-bucket (`$(AppIdentifierPrefix).
$(BundleId)`) ab. Beim Wechsel auf eine explizite `accessGroup`
(Apps werden mit v1.5.1 nachgezogen) hätten User sonst beim ersten
Start einen Logout gesehen — Apple's Read-mit-Group liefert das
alte Item nicht immer.
KeychainStore.getString(for:) liest jetzt bei einem Miss einmalig
ohne `kSecAttrAccessGroup` nach. Findet sich der alte Eintrag im
default-bucket, wird er in den expliziten Bucket migriert und der
alte gelöscht. Transparent für alle Caller. Greift nur wenn
accessGroup != nil — Apps die nicht migrieren, sind unaffected.
70/70 ManaCore-Tests grün.
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>