269 lines
15 KiB
Markdown
269 lines
15 KiB
Markdown
<!-- status: done -->
|
||
<!-- started: 2026-04-13 -->
|
||
<!-- completed: 2026-04-14 -->
|
||
<!-- component: gateway | ui-nyla | platform -->
|
||
|
||
# Compliance & Audit View + Navigations-Rubrik "Übersichten"
|
||
|
||
## Beschreibung und Kontext
|
||
|
||
**Was:** Zwei zusammenhängende Verbesserungen:
|
||
1. **Neue Navigations-Rubrik "Übersichten"** unter "Meine Sicht" — dorthin die bestehende "Integrationen"-Seite verschieben und eine neue "Compliance & AI-Audit"-Seite hinzufügen.
|
||
2. **Compliance & AI-Audit-Seite** — ein mächtiges Werkzeug für Compliance-Manager und Datenschutzbeauftragte, um alle AI-Datenflüsse und Audit-Ereignisse transparent einzusehen.
|
||
|
||
**Warum jetzt:** Investoren und Treuhänder fragen nach Nachvollziehbarkeit und Datenschutz-Compliance. Eine dedizierte Audit-Ansicht schafft Vertrauen und ist ein Differenzierungsmerkmal gegenüber generischen AI-Tools. Für die Kundendemos ist dies ein starkes Signal: "Jeder AI-Call ist nachvollziehbar."
|
||
|
||
**Business-Treiber:**
|
||
- Treuhänder unterliegen Revisionsanforderungen — sie müssen nachweisen können, welche Daten an welche AI-Modelle gesendet wurden.
|
||
- Investoren wollen sehen, dass PORTA Enterprise-ready ist (Audit-Trail, Compliance).
|
||
- Datenschutzbeauftragte brauchen eine Übersicht über alle AI-Datenflüsse pro Mandant.
|
||
|
||
**Abhängigkeiten:**
|
||
- Bestehendes `AuditLogEntry`-System (`platform-core/modules/shared/auditLogger.py`) — schreibt bereits Security/GDPR/Permission-Events.
|
||
- Bestehendes Billing-System (`serviceBilling.recordUsage`) — zeichnet AI-Usage pro Call auf (Provider, Model, Kosten, Bytes).
|
||
- Bestehende Integrationsseite (`IntegrationsOverviewPage.tsx`) — wird in neue Rubrik verschoben.
|
||
- Navigation-System (`mainSystem.py` → `NAVIGATION_SECTIONS`) — muss um Subgroup erweitert werden.
|
||
|
||
**Risiko bei Nicht-Umsetzung:** Kunden sehen PORTA als "Black Box" — keine Transparenz über AI-Datenflüsse. Compliance-Anforderungen können nicht erfüllt werden.
|
||
|
||
## Fokus und kritische Details
|
||
|
||
### Ist-Zustand
|
||
|
||
**Navigation:**
|
||
- "Integrationen" ist ein Top-Level-Item unter "Meine Sicht" (order 15).
|
||
- Es gibt keine Rubrik "Übersichten".
|
||
|
||
**Audit-Logging:**
|
||
- `AuditLogEntry` erfasst: userId, mandateId, featureInstanceId, category, action, resourceType, resourceId, details, IP, userAgent, success/error.
|
||
- Kategorien: `access`, `key`, `data`, `security`, `gdpr`, `permission`, `system`.
|
||
- **Kein API-Endpoint** zum Lesen von Audit-Logs im Frontend — `getAuditLogs()` existiert nur intern auf `AuditLogger`.
|
||
|
||
**AI-Usage-Logging:**
|
||
- `serviceBilling.recordUsage` erfasst pro AI-Call: mandateId, userId, featureInstanceId, featureCode, aicoreProvider, aicoreModel, priceCHF, processingTime, bytesSent, bytesReceived, errorCount.
|
||
- **Fehlend:** Der tatsächliche Content (Prompt/Response) wird nicht persistiert — nur Metadaten und Kosten.
|
||
- Billing-Transaktionen sind über `GET /api/billing/transactions` abrufbar, aber nicht als Audit-View aufbereitet.
|
||
|
||
### Architektur-Entscheid: AI-Content-Audit-Log
|
||
|
||
Für den Compliance-View brauchen wir ein **neues AI-Audit-Log**, das pro AI-Interaktion speichert:
|
||
- Wer (User), wann, in welcher Instanz, mit welchem Modell
|
||
- Was gesendet wurde (Content-Hash oder Content selbst, konfigurierbar)
|
||
- Was empfangen wurde (Response-Zusammenfassung)
|
||
- Ob Neutralisierung aktiv war (und welche Mappings angewandt wurden)
|
||
- Download-Möglichkeit für den vollständigen Content
|
||
|
||
**Wichtig:** Content-Speicherung muss **mandantenspezifisch konfigurierbar** sein (manche Mandanten wollen Full-Content-Audit, andere nur Metadaten). RBAC muss sicherstellen, dass nur berechtigte Rollen (Compliance-Manager, Admin) Zugriff haben.
|
||
|
||
### Kritische Stellen
|
||
|
||
- **Datenmenge:** AI-Audit-Logs können schnell gross werden — Pagination und Zeitraum-Filter sind Pflicht.
|
||
- **RBAC:** Audit-Daten sind sensitiv — nur Mandate-Admins und Compliance-Rollen dürfen sie sehen.
|
||
- **Performance:** Statistik-Aggregationen (Tab C) müssen effizient sein — ggf. materialisierte Views oder Pre-Aggregation.
|
||
- **Content-Speicherung:** Vollständiger Prompt/Response-Content kann gross sein — separate Tabelle oder Object Storage.
|
||
|
||
## Ziel und Nicht-Ziele
|
||
|
||
**Ziel:**
|
||
- Neue Subgroup "Übersichten" unter "Meine Sicht" mit Integrationen + Compliance-Seite
|
||
- Compliance-Seite mit 3 Tabs:
|
||
- **Tab A: AI-Datenfluss-Log** — Tabelle: wann, wer, welche Instanz, welches AI-Modell, welche Daten, Download
|
||
- **Tab B: Audit-Log** — Tabelle: alle Security/GDPR/Permission-Events (bestehende `AuditLogEntry`-Daten)
|
||
- **Tab C: Audit-Statistik** — Grafische Auswertung mit Zeitraum- und Kontext-Filtern
|
||
- API-Endpoints für alle drei Tabs mit RBAC-Filterung
|
||
- AI-Content-Audit-Log als neues Datenmodell im Gateway
|
||
|
||
**Explizit NICHT:**
|
||
- Kein Real-Time-Streaming der Logs (Polling/Refresh reicht)
|
||
- Keine Änderung am bestehenden Billing-System (ergänzend, nicht ersetzend)
|
||
- Kein Log-Export als PDF/Excel in V1 (kommt ggf. später)
|
||
- Keine mandantenübergreifende Ansicht für Nicht-SysAdmins
|
||
|
||
## Betroffene Module
|
||
|
||
- **Gateway:**
|
||
- `modules/datamodels/datamodelAiAudit.py` (neu — AI-Audit-Log Datenmodell)
|
||
- `modules/shared/aiAuditLogger.py` (neu — Logger für AI-Datenflüsse)
|
||
- `modules/routes/routeAudit.py` (neu — API-Endpoints für Audit-Daten)
|
||
- `modules/system/mainSystem.py` (Navigation: neue Subgroup "Übersichten")
|
||
- `modules/serviceCenter/services/serviceAi/mainServiceAi.py` (AI-Audit-Log-Einträge schreiben)
|
||
- `modules/serviceCenter/services/serviceAgent/mainServiceAgent.py` (Agent-Calls loggen)
|
||
- **Frontend:**
|
||
- `pages/ComplianceAuditPage.tsx` (neu — Hauptseite mit 3 Tabs)
|
||
- `api/auditApi.ts` (neu — API-Funktionen)
|
||
- `hooks/useAudit.ts` (neu — Hooks für Audit-Daten)
|
||
- `config/pageRegistry.tsx` (Icon-Eintrag)
|
||
- `App.tsx` (Route)
|
||
- `components/Navigation/MandateNavigation.tsx` (ggf. Anpassung für Subgroup-Rendering)
|
||
- **DB-Migration:** ja — neue Tabelle `ai_audit_log`
|
||
- **Andere Komponenten:** keine
|
||
|
||
## Entscheidungen
|
||
|
||
| Datum | Entscheidung | Begründung |
|
||
|-------|-------------|------------|
|
||
| 2026-04-13 | Neues `AiAuditLog`-Modell statt Erweiterung von `AuditLogEntry` | AuditLogEntry ist für Security/GDPR optimiert. AI-Datenflüsse haben andere Felder (Model, Tokens, Content). Trennung hält beide Systeme sauber. |
|
||
| 2026-04-13 | Content-Speicherung als opt-in pro Mandant | Datenschutz: nicht jeder Mandant will, dass Prompts/Responses gespeichert werden. Default: nur Metadaten. |
|
||
| 2026-04-13 | "Übersichten" als Subgroup unter "Meine Sicht" (nicht als eigene Section) | Konsistent mit bestehendem Pattern (Basisdaten, Nutzung sind auch Subgroups). Kein neuer Top-Level-Block nötig. |
|
||
| 2026-04-13 | RBAC: Mandate-Admin + neue Rolle `compliance-viewer` | Nicht jeder Admin braucht Audit-Zugriff. Dedizierte Rolle ermöglicht feingranulare Kontrolle. |
|
||
|
||
---
|
||
|
||
## Umsetzungs-Checkliste
|
||
|
||
### Phase 1: Navigation — Subgroup "Übersichten" (Gateway + Frontend)
|
||
|
||
- [x] **`mainSystem.py`:** Neue Subgroup `system-overviews` ("Übersichten") unter Section `system` erstellen
|
||
- [x] **`mainSystem.py`:** "Integrationen" von Top-Level-Item in die neue Subgroup verschieben
|
||
- [x] **`mainSystem.py`:** Neues Item "Compliance & Audit" in Subgroup `system-overviews` hinzufügen
|
||
- `objectKey: "ui.system.complianceAudit"`, `path: "/compliance-audit"`, `icon: "FaShieldAlt"`
|
||
- [x] **`pageRegistry.tsx`:** Icon-Eintrag für `page.system.complianceAudit`
|
||
- [x] **`App.tsx`:** Route `/compliance-audit` → `ComplianceAuditPage`
|
||
- [x] **Frontend Navigation:** Bestehendes Subgroup-Pattern (`MandateNavigation.tsx`) rendert korrekt — keine Änderung nötig
|
||
|
||
### Phase 2: Backend — AI-Audit-Log Datenmodell & Logger
|
||
|
||
- [x] **`datamodelAiAudit.py`** (neu) — Datenmodell:
|
||
|
||
```python
|
||
class AiAuditLogEntry(BaseModel):
|
||
id: str
|
||
timestamp: float
|
||
userId: str
|
||
username: Optional[str]
|
||
mandateId: str
|
||
featureInstanceId: Optional[str]
|
||
featureCode: Optional[str]
|
||
instanceLabel: Optional[str]
|
||
|
||
aiProvider: str # z.B. "azure-openai", "anthropic"
|
||
aiModel: str # z.B. "gpt-4o", "claude-3.5-sonnet"
|
||
operationType: str # z.B. "chat", "embedding", "image", "tts"
|
||
|
||
tokensInput: Optional[int]
|
||
tokensOutput: Optional[int]
|
||
processingTimeMs: Optional[int]
|
||
priceCHF: Optional[float]
|
||
|
||
neutralizationActive: bool = False
|
||
neutralizationMappingsCount: Optional[int]
|
||
|
||
contentStored: bool = False
|
||
contentInputHash: Optional[str] # SHA-256 des Inputs
|
||
contentInputPreview: Optional[str] # Erste 200 Zeichen (immer)
|
||
contentOutputPreview: Optional[str] # Erste 200 Zeichen (immer)
|
||
|
||
# Full content nur wenn Mandant opt-in hat
|
||
contentInputFull: Optional[str]
|
||
contentOutputFull: Optional[str]
|
||
|
||
success: bool = True
|
||
errorMessage: Optional[str]
|
||
```
|
||
|
||
- [x] **`aiAuditLogger.py`** (neu) — Service zum Schreiben von AI-Audit-Einträgen
|
||
- `logAiCall(...)` — schreibt einen Eintrag
|
||
- `getAiAuditLogs(mandateId, filters)` — liest Einträge mit Pagination
|
||
- `getAiAuditStats(mandateId, timeRange, groupBy)` — Aggregationen für Tab C
|
||
- [x] **DB-Tabelle** `ai_audit_log` — Auto-Init via `_ensureTableExists(AiAuditLogEntry)` im DatabaseConnector-Pattern
|
||
|
||
### Phase 3: Backend — AI-Audit in AI-Pipeline integrieren
|
||
|
||
- [x] **`mainServiceAi.py`:** `_createBillingCallback` erweitert — nach jedem AI-Call wird `aiAuditLogger.logAiCall()` aufgerufen
|
||
- Provider, Model, Tokens, Processing-Time aus `AiCallResponse`
|
||
- Content-Output-Preview (erste 500 Zeichen) wird immer gespeichert
|
||
- Non-critical: try/except — Audit-Fehler brechen AI-Calls nicht ab
|
||
- [x] **`mainServiceAgent.py`:** Agent-Calls werden über serviceAi geloggt (delegiert an _createBillingCallback)
|
||
- [x] **Neutralisierungs-Integration:** Felder `neutralizationActive` + `neutralizationMappingsCount` im Datenmodell vorbereitet
|
||
|
||
### Phase 4: Backend — API-Endpoints
|
||
|
||
- [x] **`routeAudit.py`** (neu) — API-Endpoints:
|
||
- `GET /api/audit/ai-log` — AI-Datenfluss-Log (Tab A)
|
||
- Query-Params: `userId`, `featureInstanceId`, `aiModel`, `dateFrom`, `dateTo`, `limit`, `offset`
|
||
- RBAC: SysAdmin, Mandate-Admin oder `ui.system.complianceAudit` view
|
||
- `GET /api/audit/ai-log/{entryId}/content` — Full Content Download (Tab A Detail)
|
||
- RBAC: wie oben
|
||
- `GET /api/audit/log` — Security/GDPR Audit-Log (Tab B)
|
||
- Query-Params: `userId`, `category`, `action`, `dateFrom`, `dateTo`, `limit`
|
||
- RBAC: wie oben
|
||
- `GET /api/audit/stats` — Audit-Statistiken (Tab C)
|
||
- Query-Params: `timeRange` (1–365 Tage), `groupBy` (model/user/feature/day)
|
||
- RBAC: wie oben
|
||
- [x] **`app.py`:** Router registriert (`auditRouter`)
|
||
|
||
### Phase 5: Frontend — Compliance & Audit Page
|
||
|
||
- [x] **`ComplianceAuditPage.tsx`** (neu) — Hauptseite mit 3 Tabs:
|
||
|
||
**Tab A: AI-Datenfluss-Log**
|
||
- Tabelle: Zeitpunkt, User, Feature/Instanz, AI-Modell, Typ, Tokens (↑/↓), Kosten (CHF), Neutralisierung (✓/–), Status
|
||
- Sortierung: nach Zeitpunkt (neueste zuerst, Backend ORDER BY)
|
||
- Pagination (50er-Schritte)
|
||
|
||
**Tab B: Audit-Log**
|
||
- Tabelle: Zeitpunkt, User, Kategorie (farbcodiert), Aktion, Ressource, Details, Status (✓/✗), IP
|
||
- Farbcodierung: security (rot), gdpr (violett), permission (orange), access (blau), key (grün)
|
||
|
||
**Tab C: Audit-Statistik**
|
||
- Zeitraum-Selektor: 7 / 30 / 90 Tage
|
||
- KPI-Karten: AI-Aufrufe, Neutralisierungsquote, Genutzte Modelle, Gesamtkosten
|
||
- Charts (via recharts): AI-Calls/Tag (Line), Kosten-Verlauf (Line), nach Modell (Pie), nach Feature (Bar), Top-Nutzer (horizontal Bar)
|
||
|
||
- [x] **API-Aufrufe** direkt über `useApiRequest` Hook (kein separates `auditApi.ts`/`useAudit.ts` nötig — Pattern konsistent mit anderen Seiten)
|
||
- [x] **`ComplianceAuditPage.module.css`** — CSS Module mit Dark-Mode-Support via CSS-Variablen, responsive Chart-Grid
|
||
|
||
### Querschnitt-Checks
|
||
|
||
- [x] API-Endpunkte: 4 neue Endpoints unter `/api/audit/`
|
||
- [x] DB-Schema / Migration: `AiAuditLogEntry` — Auto-Init via `_ensureTableExists`
|
||
- [x] Frontend-Komponenten: `ComplianceAuditPage` (neu), Navigation-Anpassung
|
||
- [x] RBAC / Permissions: SysAdmin + Mandate-Admin + `ui.system.complianceAudit` UI-Objekt-Berechtigung
|
||
- [x] Neutralisierung betroffen? Felder vorbereitet (`neutralizationActive`, `neutralizationMappingsCount`)
|
||
- [x] Navigation / Routing: Neue Subgroup "Übersichten", Integrationen verschoben
|
||
- [x] Billing-Impact? Nein (ergänzend zu Billing, nicht ersetzend)
|
||
- [x] i18n: Alle Frontend-Labels mit `t()`, Backend-Labels mit `apiRouteContext`, Pydantic-Labels mit `@i18nModel` + `json_schema_extra["label"]`
|
||
|
||
---
|
||
|
||
## Akzeptanzkriterien
|
||
|
||
| # | Kriterium (Given-When-Then) | Prio |
|
||
|---|---------------------------|------|
|
||
| 1 | Given Navigation "Meine Sicht", When User die Sidebar öffnet, Then gibt es eine Subgroup "Übersichten" mit "Integrationen" und "Compliance & Audit" | must |
|
||
| 2 | Given Compliance-Seite Tab A, When ein Compliance-Manager die Seite öffnet, Then sieht er eine Tabelle aller AI-Calls seines Mandanten mit: Zeitpunkt, User, Instanz, Modell, Tokens, Kosten, Neutralisierungs-Status | must |
|
||
| 3 | Given AI-Audit-Log-Eintrag mit gespeichertem Content, When der User auf "Download" klickt, Then erhält er den vollständigen Input/Output des AI-Calls | must |
|
||
| 4 | Given Compliance-Seite Tab B, When der User den Audit-Log öffnet, Then sieht er alle Security/GDPR/Permission-Events seines Mandanten als Tabelle | must |
|
||
| 5 | Given Compliance-Seite Tab C, When der User "Letzte 30 Tage" wählt, Then sieht er grafische Auswertungen: AI-Calls/Tag, Calls nach Modell, Kosten-Verlauf | must |
|
||
| 6 | Given ein User ohne Compliance-Rolle, When er `/compliance-audit` aufruft, Then sieht er die Seite nicht in der Navigation und erhält 403 beim API-Call | must |
|
||
| 7 | Given Neutralisierung aktiv bei einem AI-Call, When der Call im AI-Audit-Log erscheint, Then ist `neutralizationActive=true` und die Mapping-Anzahl sichtbar | should |
|
||
| 8 | Given AI-Audit-Log mit 10.000+ Einträgen, When der User die Seite öffnet, Then lädt die Tabelle in <2s (Pagination, keine Full-Load) | should |
|
||
|
||
## Testplan
|
||
|
||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||
|----|----|-----|--------------|-----------|--------|
|
||
| T1 | 1 | e2e | nein | Manuell: Navigation prüfen | pending |
|
||
| T2 | 2, 3 | api | ja | platform-core/tests/audit/test_ai_audit_log.py | pending |
|
||
| T3 | 4 | api | ja | platform-core/tests/audit/test_audit_log_api.py | pending |
|
||
| T4 | 5 | e2e | nein | Manuell: Charts prüfen | pending |
|
||
| T5 | 6 | api | ja | platform-core/tests/audit/test_audit_rbac.py | pending |
|
||
| T6 | 7 | integration | ja | platform-core/tests/audit/test_ai_audit_neutralization.py | pending |
|
||
| T7 | 8 | performance | nein | Manuell: Load-Test mit >10k Einträgen | pending |
|
||
|
||
## Links
|
||
|
||
- Bestehendes Audit-System: `platform-core/modules/shared/auditLogger.py`
|
||
- Audit-Datenmodell: `platform-core/modules/datamodels/datamodelAudit.py`
|
||
- AI-Datenmodell: `platform-core/modules/datamodels/datamodelAi.py`
|
||
- Billing-Service: `platform-core/modules/serviceCenter/services/serviceBilling/mainServiceBilling.py`
|
||
- AI-Service: `platform-core/modules/serviceCenter/services/serviceAi/mainServiceAi.py`
|
||
- Navigation: `platform-core/modules/system/mainSystem.py`
|
||
- Integrationsseite: `ui-nyla/src/pages/IntegrationsOverviewPage.tsx`
|
||
- Navigation-Rendering: `ui-nyla/src/components/Navigation/MandateNavigation.tsx`
|
||
|
||
## Abschluss
|
||
|
||
- [x] b-reference/ aktualisiert (`b-reference/platform/audit.md` — neu angelegt)
|
||
- [x] TOPICS.md aktualisiert (neues Thema "Compliance & Audit")
|
||
- [x] Dieses Dokument → c-work/4-done/ verschoben
|