React/TypeScript-SPA fuer novaris-policy-core-modern - Umsetzung der zuvor nur als
Ziel benannten novaris-policy-web-modern-spa-Luecke (siehe
docs/70-migration/02-component-mapping.md, Zeile zum JSF-Portal). Kein Legacy-Gegenstueck
1:1 (das Legacy-JSF-Portal ist server-seitig gerendert, hier: reines REST-Client-SPA) -
fachlich aber derselbe Anwendungsfall wie novaris-policy-web-legacy-jsf.
react-router-dom fuer Client-Routing.oidc-client-ts fuer OIDC Authorization-Code-Flow + PKCE gegen Keycloak - siehe
docs/70-migration/11-oidc-keycloak.md. Kein eigener Redux/Zustand-Store - der
Auth-Zustand lebt in einem schlanken React-Context (src/auth/AuthContext.tsx), die
fachlichen Daten werden pro Seite direkt per fetch geholt (keine globale Client-Cache-
Bibliothek wie React Query - fuer den Funktionsumfang dieser Lernanwendung bewusst nicht
noetig).Der Password-Grant (grant_type=password), den dieses Projekt an anderer Stelle fuer
automatisierte Tests/curl-Verifikation nutzt (siehe 11-oidc-keycloak.md), ist fuer eine
echte Browser-Anwendung ungeeignet - er wuerde bedeuten, dass die SPA selbst
Benutzername/Passwort entgegennimmt und an Keycloak weiterreicht, statt dass die
Authentifizierung komplett bei Keycloak stattfindet (Redirect zur Keycloak-Login-Seite).
PKCE (code_challenge/code_verifier) ersetzt dabei den sonst fuer den Authorization-Code-
Flow noetigen Client-Secret - ein Browser-Client kann kein Geheimnis verstecken (der
komplette Quellcode liegt offen), PKCE macht den abgefangenen Code allein wertlos ohne den
nur clientseitig gehaltenen Verifier.
CreatePolicyPage.tsx haelt die drei gueltigen Produktcodes
(KFZ-HAFTPFLICHT/KFZ-KASKO/LEBEN) als schmale, bewusst redundante Konstante -
PremiumCalculationService.buildRateTable im Backend exponiert diese nicht ueber einen
eigenen Endpunkt. Fuer drei feste, seltenaenderliche Werte war ein eigener
GET /api/products-Endpunkt nur fuer diesen einen Zweck nicht gerechtfertigt.
novaris-policy-core-moderns SecurityConfig.corsConfigurationSource() erlaubt bewusst nur
http://localhost:5173 (Vite-Dev-Server-Standardport) - kein Wildcard-Origin, siehe dessen
Javadoc.
# aus novaris-modern-parent/novaris-policy-web-modern-spa/:
npm install
cp .env.example .env.local # ggf. Ports anpassen
npm run dev # http://localhost:5173
npm run build # tsc -b && vite build, Produktions-Bundle nach dist/
npm run lint # oxlint
npm test # Vitest: Routing-/Auth-Schutztests
Voraussetzung fuer einen echten Login: novaris-policy-core-modern (Port 8080) und ein
Keycloak mit importiertem novaris-realm.json (Port 8081, siehe
novaris-policy-core-modern/README.md) muessen erreichbar sein.
Ohne Browser-Automatisierungswerkzeug in dieser Umgebung wurde die UI nicht durch echtes Klicken getestet - stattdessen wurde der komplette Protokoll-/Integrationspfad, den die SPA zur Laufzeit durchlaeuft, per Skript nachgebildet und gegen echte, laufende Instanzen verifiziert (kein Mock):
npm test, npm run build und npm run lint laufen fehlerfrei durch.OPTIONS) gegen das echte Backend: http://localhost:5173 wird erlaubt
(Access-Control-Allow-Origin korrekt gesetzt), ein fremder Origin wird mit 403
abgelehnt (kein Wildcard-Leck).VITE_OIDC_REDIRECT_URI (http://localhost:5173/callback), Code-Tausch am
Token-Endpunkt mit dem passenden Code-Verifier liefert ein echtes JWT - derselbe Ablauf,
den oidc-client-tss signinRedirect()/signinRedirectCallback() intern durchfuehren.Origin-Header wie bei einem Browser-fetch()): echte
Police ueber POST /api/policies angelegt (wie CreatePolicyPage.tsx), und die
Rollenpruefung real bestaetigt - ein underwriter-Token bekommt bei cancelPolicy
(nur PolicyAdmin) korrekt 403, deckungsgleich mit canCancelPolicy(roles) in
src/auth/roles.ts, das denselben Button in der UI ausblendet.Kein Klick-Test in einem echten Browser (kein Playwright/Selenium in dieser Umgebung verfuegbar) - die oben beschriebene Protokoll-Verifikation deckt die Backend-Integration vollstaendig ab, nicht aber tatsaechliches Rendering/Interaktionsverhalten der React-Komponenten selbst.
⌂ Cockpit