/// Endpoint-Konfiguration für das Rust-Backend. /// /// Diese Übergangs-Konfiguration für die Backend-Migration wird in /// Phase D durch eine umfassendere Konfigurations-Ablösung verfeinert /// (Build-Time-Flavor pro Stage etc.). /// /// **Werte für lokale Entwicklung:** /// * iOS-Simulator + macOS-Host: `http://localhost:...` /// * Android-Emulator: `http://10.0.2.2:...` /// * Echtes Gerät im LAN: `http://:...` /// /// Default ist iOS-Simulator-tauglich; für Android-Build vor dem /// Compile umstellen oder per Build-Flag injizieren. class BackendConfig { const BackendConfig({ required this.apiBaseUrl, required this.keycloakIssuerUrl, required this.keycloakClientId, required this.keycloakRedirectUrl, }); /// Basis-URL der Rust-API (kein abschließender Slash). final String apiBaseUrl; /// Realm-Issuer ohne `/.well-known/...`-Suffix — /// `flutter_appauth` hängt das selbst an für die Discovery. /// Beispiel: `http://localhost:8080/realms/holzleitner`. /// /// **Achtung:** Keycloak prägt das `iss`-Claim aus dem Hostnamen /// dieser URL. Das Backend erwartet exakt diesen String als /// `KEYCLOAK_ISSUER_URL`. Mismatch → 401 mit `invalid issuer`. final String keycloakIssuerUrl; /// Token-Endpoint des Realms — abgeleitet aus dem Issuer. String get keycloakTokenEndpoint => '$keycloakIssuerUrl/protocol/openid-connect/token'; /// Public-Client-Id (entspricht der `aud` im Backend-Token). final String keycloakClientId; /// Custom-Scheme-Redirect, das in Keycloak als /// `holzleitner://oauth2redirect` whitelisted ist. Muss mit dem /// `appAuthRedirectScheme` in `android/app/build.gradle.kts` und /// dem `CFBundleURLSchemes`-Eintrag in `ios/Runner/Info.plist` /// matchen. final String keycloakRedirectUrl; /// Default-Konfiguration für lokale Entwicklung gegen das /// Docker-Compose-Setup (Postgres + Keycloak + Backend). static const BackendConfig localDev = BackendConfig( apiBaseUrl: 'http://192.168.0.138:3000', keycloakIssuerUrl: 'http://192.168.0.138:8080/realms/holzleitner', keycloakClientId: 'holzleitner-app', keycloakRedirectUrl: 'holzleitner://oauth2redirect', ); /// Konfiguration für USB-Tunnel via `adb reverse` — gedacht für Tests in /// fremden Netzwerken, in denen das Gerät den Mac nicht über eine LAN-IP /// erreicht. Alles zeigt auf `localhost`; der Traffic wird über den /// USB-Bus zum Host getunnelt. /// /// **Setup vor dem Start (Gerät per USB angesteckt):** /// ``` /// adb reverse tcp:3000 tcp:3000 # Rust-API /// adb reverse tcp:8080 tcp:8080 # Keycloak /// ``` /// /// **Backend-Voraussetzungen**, damit das OIDC-Login funktioniert: /// * Backend-Env `KEYCLOAK_ISSUER_URL=http://localhost:8080/realms/holzleitner` /// (muss exakt mit [keycloakIssuerUrl] matchen, sonst 401 `invalid issuer`). /// * Keycloak muss den Issuer als `localhost` ausgeben — z. B. via /// `KC_HOSTNAME_URL=http://localhost:8080` (oder Frontend-URL im Realm), /// sonst prägt es den Container-Hostnamen ins `iss`-Claim. /// * Der `holzleitner://oauth2redirect`-Redirect bleibt unverändert (das /// Custom-Scheme ist netzwerk-unabhängig). /// /// Aktivieren ohne Code-Edit: /// ``` /// flutter run --dart-define=HL_BACKEND=usb /// ``` static const BackendConfig usbReverse = BackendConfig( apiBaseUrl: 'http://localhost:3000', keycloakIssuerUrl: 'http://localhost:8080/realms/holzleitner', keycloakClientId: 'holzleitner-app', keycloakRedirectUrl: 'holzleitner://oauth2redirect', ); /// Wählt die Config anhand des Compile-Time-Flags `HL_BACKEND`: /// * `usb` → [usbReverse] (adb-reverse-Tunnel über localhost) /// * sonst → [localDev] (LAN-IP, Default) /// /// So muss für einen Netzwerkwechsel nur das Build-Flag gesetzt werden, /// nicht der Quellcode angefasst. static const BackendConfig fromEnvironment = String.fromEnvironment('HL_BACKEND') == 'usb' ? usbReverse : localDev; }