# 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 (`gateway/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 | gateway/tests/audit/test_ai_audit_log.py | pending | | T3 | 4 | api | ja | gateway/tests/audit/test_audit_log_api.py | pending | | T4 | 5 | e2e | nein | Manuell: Charts prüfen | pending | | T5 | 6 | api | ja | gateway/tests/audit/test_audit_rbac.py | pending | | T6 | 7 | integration | ja | gateway/tests/audit/test_ai_audit_neutralization.py | pending | | T7 | 8 | performance | nein | Manuell: Load-Test mit >10k Einträgen | pending | ## Links - Bestehendes Audit-System: `gateway/modules/shared/auditLogger.py` - Audit-Datenmodell: `gateway/modules/datamodels/datamodelAudit.py` - AI-Datenmodell: `gateway/modules/datamodels/datamodelAi.py` - Billing-Service: `gateway/modules/serviceCenter/services/serviceBilling/mainServiceBilling.py` - AI-Service: `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py` - Navigation: `gateway/modules/system/mainSystem.py` - Integrationsseite: `frontend_nyla/src/pages/IntegrationsOverviewPage.tsx` - Navigation-Rendering: `frontend_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