- Umgebungen (Name, API-URL, Keycloak-Issuer) kommen aus
assets/hl_server_config.json statt hartcodiertem BackendConfig.prod;
Testumgebung 192.168.1.9:3001 ist dort hinterlegt
- AppBloc laedt die Config, aktiviert die gespeicherte Wahl (Fallback
Default) und registriert das Networking; Wechsel persistiert per
SharedPreferences und registriert neu
- Bloc-Baum ist pro Umgebung gekeyt: beim Wechsel entstehen alle Blocs
mit dem neuen API-Client neu
- Login-Screen: Zahnrad oben rechts oeffnet Einstellungen mit Umgebungs-
Cards (Name + IP:Port); Hinweis auf aktive Umgebung unter dem Button
- Fahrzeugauswahl pro Umgebung getrennt (eigene DB = eigene Car-IDs)
- Tests fuer Config-Parsing, Auswahl-Fallback, Card-Wechsel, Re-Registrierung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Haengt der interaktive Login (Browser-Tab/Token-Exchange) bei Verbindungsabbruch/Issuer-Hang, bricht er nach 10s ab; LoginPage zeigt 'Einloggen nicht moeglich. Spaeter erneut versuchen.' (Unauthenticated.loginTimedOut).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
App-Code:
- KeycloakOidcTokenProvider: PKCE-Login via flutter_appauth, Refresh via
Refresh-Token aus flutter_secure_storage, Session-Restore beim
App-Start, Logout.
- AuthSessionEvent als Provider→Bloc-Brücke (LoggedIn/LoggedOut/
SessionExpired) auf einem Broadcast-Stream.
- AuthBloc komplett umgebaut: nimmt jetzt den KeycloakOidcTokenProvider
statt UserInfoService, mappt eingehende Provider-Events auf eigene
Zustände. Authenticated.fromClaims() liest personalnummer + Name aus
dem ID-Token-Payload.
- LoginPage: kein Browser+Deep-Link mehr — Button feuert
LoginRequested, der Provider übernimmt den restlichen Flow.
- network_locator: produktiver KeycloakOidcTokenProvider, doppelt
registriert (KeycloakOidcTokenProvider für AuthBloc,
AuthTokenProvider für Interceptor).
- Auth-State trägt zusätzlich personalnummer/displayName/email; das
Legacy-User-Objekt + sessionId bleiben temporär drin, damit die
alten ERPframe-Services (Phase D) noch kompilieren.
Plattform-Setup:
- Android: appAuthRedirectScheme=holzleitner in build.gradle.kts,
NetworkSecurityConfig erlaubt HTTP zu localhost/10.0.2.2/127.0.0.1.
- iOS: holzleitner als URL-Scheme im Info.plist, ATS-Ausnahme für
localhost (HTTP-Keycloak im Dev-Setup).
Out of scope:
- Keine echte App-Run-Smoke — kommt mit dem User-Test.
- iOS-pod-install läuft beim ersten 'flutter run ios' automatisch.
- Old ERPframe-Services bleiben aktiv und werfen ab jetzt 401 (kein
Cookie-Session-Token mehr) — wird in Phase D entfernt.