140 lines
6.2 KiB
Markdown
140 lines
6.2 KiB
Markdown
# JARVIS Web Frontend (Phase 3b) - Design
|
|
|
|
**Datum:** 2026-09-12
|
|
**Status:** Approved, bereit fuer Implementierungsplan
|
|
|
|
## Kontext
|
|
|
|
Phase 2 (Claude-Chat) und Phase 3a (Knowledge Base via pgvector) sind live auf
|
|
`https://jarvis.mbo-tech-it.de` (API) mit Traefik-Routing ueber den bereits
|
|
vorhandenen, geteilten Reverse-Proxy des VPS. `JARVIS_HANDOFF.md` listet
|
|
Phase 3 "Frontend" mit vier Punkten (React/Vue Web UI, Authentication UI,
|
|
Chat Interface, Dashboard) - das wurde bewusst aufgeteilt: eine
|
|
"Authentication UI" braucht ein Auth-System, das serverseitig nicht
|
|
existiert (kein Login/JWT-Flow). Diese Spec deckt Chat + Dashboard als eine
|
|
gemeinsame Web-App ab; ein vollwertiges Auth-System bleibt ein separates
|
|
Follow-up.
|
|
|
|
## Sicherheitsproblem, das diese Phase mitloest
|
|
|
|
`/api/v1/chat` hat aktuell keinerlei Zugriffsschutz und CORS steht auf `*`.
|
|
Eine oeffentlich erreichbare Chat-UI unter einer bekannten Domain waere ohne
|
|
Schutz von jedem nutzbar, der die Domain findet, und wuerde Claude-API-
|
|
Guthaben verbrauchen. Diese Spec fuehrt deshalb einen einfachen
|
|
Shared-Secret-Schutz ein (kein vollwertiges User-System - das ist bewusst
|
|
YAGNI fuer den aktuellen Umfang, siehe Out of Scope).
|
|
|
|
## Domain-Aufteilung
|
|
|
|
- `jarvis.mbo-tech-it.de` -> Web-Frontend (neu, dieser Service)
|
|
- `api.jarvis.mbo-tech-it.de` -> JARVIS-API (Umzug von der Hauptdomain)
|
|
|
|
Kein neuer DNS-Eintrag noetig: der Wildcard-Record `*.jarvis.mbo-tech-it.de`
|
|
(siehe Traefik-Integration in `JARVIS_HANDOFF.md`) deckt `api.jarvis...`
|
|
bereits ab.
|
|
|
|
## Zugriffsschutz: Shared Secret statt vollwertiges Auth-System
|
|
|
|
Wiederverwendung des bereits in `.env` vorhandenen `API_KEY_ADMIN` (kein
|
|
neues Secret noetig). Ablauf:
|
|
|
|
1. Neue FastAPI-Dependency `require_admin_key` prueft den Header
|
|
`X-Admin-Key` gegen `API_KEY_ADMIN`. Fehlt der Header oder stimmt der Wert
|
|
nicht -> `401 Unauthorized`.
|
|
2. Angewendet auf: `POST /api/v1/chat`, `GET /api/v1/conversations/{id}`,
|
|
`POST/GET /api/v1/documents`, `POST/GET /api/v1/tasks`,
|
|
`POST /api/v1/workflows/trigger`, `GET /api/v1/admin/stats`,
|
|
`GET /api/v1/admin/health/detailed`.
|
|
3. **Nicht** geschuetzt: `GET /health` (wird fuer einfaches Monitoring/
|
|
Uptime-Checks offen gehalten - liefert ohnehin keine sensiblen Daten).
|
|
4. CORS wird von `allow_origins=["*"]` auf
|
|
`allow_origins=["https://jarvis.mbo-tech-it.de"]` eingeschraenkt, da wir
|
|
an dieser Stelle ohnehin an der Zugriffskontrolle arbeiten.
|
|
|
|
Im Frontend: Login-Screen mit einem Passwort-Feld. Eingabe wird nicht
|
|
client-seitig validiert, sondern per Testaufruf gegen
|
|
`GET /api/v1/admin/stats` mit dem eingegebenen Wert als `X-Admin-Key`
|
|
geprueft. Bei `200` wird der Wert in `localStorage` (Key
|
|
`jarvis_admin_key`) gespeichert und die Hauptansicht angezeigt. Bei `401`
|
|
Fehlermeldung im Login-Screen. Jeder weitere API-Call haengt den
|
|
gespeicherten Wert als `X-Admin-Key`-Header an; ein `401` auf irgendeinem
|
|
Call loescht den `localStorage`-Eintrag und zeigt wieder den Login-Screen.
|
|
|
|
## Frontend-Architektur
|
|
|
|
React + Vite, kein zusaetzliches Routing (nur zwei Views, ein einfacher
|
|
State-Switch reicht - YAGNI). Struktur:
|
|
|
|
```
|
|
web/
|
|
src/
|
|
main.tsx # Einstiegspunkt
|
|
App.tsx # Login-Gate + Nav zwischen Chat/Dashboard
|
|
api.ts # fetch-Wrapper: haengt X-Admin-Key an, wirft
|
|
# bei 401 einen speziellen Fehler, den App.tsx
|
|
# abfaengt um zurueck zum Login zu wechseln
|
|
components/
|
|
Login.tsx # Passwort-Feld, Testaufruf, Fehleranzeige
|
|
Chat.tsx # Nachrichtenliste + Eingabefeld
|
|
Dashboard.tsx # Stats-Karten + Health-Tabelle
|
|
index.html
|
|
package.json
|
|
vite.config.ts
|
|
Dockerfile # Multi-Stage: node:20-slim build -> nginx:alpine serve
|
|
nginx.conf # SPA-Fallback (alle Routen -> index.html)
|
|
```
|
|
|
|
`VITE_API_URL` (Build-Zeit-Env-Var) zeigt auf
|
|
`https://api.jarvis.mbo-tech-it.de`.
|
|
|
|
### Chat (`Chat.tsx`)
|
|
|
|
- Lokaler State: `messages: {role, content}[]`, `conversationId: number | null`.
|
|
- Eingabefeld + Senden-Button (auch Enter-Taste). Waehrend eine Antwort
|
|
aussteht: Eingabe gesperrt, Ladeindikator.
|
|
- Sendet `POST /api/v1/chat` mit `{conversation_id: conversationId, message}`.
|
|
Antwort haengt User- und Assistant-Nachricht an `messages` an, setzt
|
|
`conversationId` aus der Response.
|
|
- Fehler (z.B. 503 wegen fehlendem Claude-Guthaben) werden als Systemzeile
|
|
im Chatverlauf angezeigt, nicht stillschweigend verschluckt.
|
|
|
|
### Dashboard (`Dashboard.tsx`)
|
|
|
|
- Beim Mount: `GET /api/v1/admin/stats` und
|
|
`GET /api/v1/admin/health/detailed` parallel laden.
|
|
- Stats als drei Zahlen-Karten (Conversations/Tasks/Documents).
|
|
- Health als Tabelle: Service-Name, Status (ok/error als farbiges Badge),
|
|
Response-Time. Manueller "Aktualisieren"-Button (kein Auto-Polling - fuer
|
|
den aktuellen Umfang unnoetig, YAGNI).
|
|
|
|
## Fehlerbehandlung
|
|
|
|
- Netzwerkfehler (API nicht erreichbar): Inline-Fehlermeldung statt
|
|
unbehandeltem Absturz, sowohl in Chat als auch Dashboard.
|
|
- 401 an beliebiger Stelle: zentral in `api.ts` behandelt (siehe oben),
|
|
nicht in jeder Komponente einzeln.
|
|
- Leere Eingabe im Chat: Senden-Button deaktiviert, kein Request.
|
|
|
|
## Testing
|
|
|
|
- Backend: Unit-Test fuer `require_admin_key` (gueltiger Key -> durchgelassen,
|
|
fehlender Key -> 401, falscher Key -> 401) mit FastAPI `TestClient`.
|
|
- Frontend: Unit-Test (Vitest) fuer `api.ts` - prueft, dass der
|
|
`X-Admin-Key`-Header aus `localStorage` gesetzt wird und dass eine
|
|
401-Antwort den `localStorage`-Eintrag entfernt.
|
|
- Manueller End-to-End-Test im Browser nach Deployment: Login mit falschem
|
|
Passwort (Fehler sichtbar), Login mit richtigem Passwort, eine
|
|
Chat-Nachricht senden und Antwort sehen, zum Dashboard wechseln und Stats/
|
|
Health sehen (passend zum bisherigen Muster in diesem Projekt - kein
|
|
automatisierter Browser-Test-Runner vorhanden).
|
|
|
|
## Out of Scope (bewusst nicht Teil dieser Phase)
|
|
|
|
- Vollwertiges User-/Auth-System (Login pro Benutzer, JWT, Rollen) - das ist
|
|
weiterhin offener Punkt in Phase 3 von `JARVIS_HANDOFF.md`, unabhaengig von
|
|
dieser Spec.
|
|
- Tasks/Documents-Verwaltung im Frontend (Erstellen/Anzeigen ueber die UI) -
|
|
nur Chat + Dashboard in dieser Phase.
|
|
- Auto-Refresh/Live-Updates im Dashboard.
|
|
- Mobile-optimiertes Layout ueber einfache Responsivitaet hinaus.
|