/// Endpoint-Konfiguration für das Rust-Backend. /// /// Produktiv-Setup: Backend und Keycloak laufen auf dem Host `192.168.1.9`. /// Es gibt bewusst KEINE Dev-/localhost-/Tunnel-Profile und keine /// `HL_BACKEND`-Umschaltung mehr — die App zeigt immer auf Prod. So kann kein /// Build versehentlich auf `localhost` oder eine Dev-IP zeigen. 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://192.168.1.9:8080/realms/holzleitner`. /// /// **Achtung:** Keycloak prägt das `iss`-Claim aus dem Hostnamen /// dieser URL. Das Backend erwartet exakt diesen String als /// `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; /// Produktiv-Konfiguration — einzige Quelle der Wahrheit. static const BackendConfig prod = BackendConfig( apiBaseUrl: 'http://192.168.1.9:3000', keycloakIssuerUrl: 'http://192.168.1.9:8080/realms/holzleitner', keycloakClientId: 'holzleitner-app', keycloakRedirectUrl: 'holzleitner://oauth2redirect', ); /// Aktive Konfiguration. Früher per `--dart-define=HL_BACKEND` zwischen /// Dev-Profilen (usb-Tunnel / LAN-IP) umschaltbar — entfernt. Das Flag wird /// jetzt ignoriert; es zählt immer [prod]. static const BackendConfig fromEnvironment = prod; }