15 KiB
Compliance & Audit View + Navigations-Rubrik "Übersichten"
Beschreibung und Kontext
Was: Zwei zusammenhängende Verbesserungen:
- Neue Navigations-Rubrik "Übersichten" unter "Meine Sicht" — dorthin die bestehende "Integrationen"-Seite verschieben und eine neue "Compliance & AI-Audit"-Seite hinzufügen.
- 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:
AuditLogEntryerfasst: 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 aufAuditLogger.
AI-Usage-Logging:
serviceBilling.recordUsageerfasst 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/transactionsabrufbar, 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)
mainSystem.py: Neue Subgroupsystem-overviews("Übersichten") unter SectionsystemerstellenmainSystem.py: "Integrationen" von Top-Level-Item in die neue Subgroup verschiebenmainSystem.py: Neues Item "Compliance & Audit" in Subgroupsystem-overviewshinzufügenobjectKey: "ui.system.complianceAudit",path: "/compliance-audit",icon: "FaShieldAlt"
pageRegistry.tsx: Icon-Eintrag fürpage.system.complianceAuditApp.tsx: Route/compliance-audit→ComplianceAuditPage- Frontend Navigation: Bestehendes Subgroup-Pattern (
MandateNavigation.tsx) rendert korrekt — keine Änderung nötig
Phase 2: Backend — AI-Audit-Log Datenmodell & Logger
datamodelAiAudit.py(neu) — Datenmodell:
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]
aiAuditLogger.py(neu) — Service zum Schreiben von AI-Audit-EinträgenlogAiCall(...)— schreibt einen EintraggetAiAuditLogs(mandateId, filters)— liest Einträge mit PaginationgetAiAuditStats(mandateId, timeRange, groupBy)— Aggregationen für Tab C
- DB-Tabelle
ai_audit_log— Auto-Init via_ensureTableExists(AiAuditLogEntry)im DatabaseConnector-Pattern
Phase 3: Backend — AI-Audit in AI-Pipeline integrieren
mainServiceAi.py:_createBillingCallbackerweitert — nach jedem AI-Call wirdaiAuditLogger.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
- Provider, Model, Tokens, Processing-Time aus
mainServiceAgent.py: Agent-Calls werden über serviceAi geloggt (delegiert an _createBillingCallback)- Neutralisierungs-Integration: Felder
neutralizationActive+neutralizationMappingsCountim Datenmodell vorbereitet
Phase 4: Backend — API-Endpoints
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.complianceAuditview
- Query-Params:
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
- Query-Params:
GET /api/audit/stats— Audit-Statistiken (Tab C)- Query-Params:
timeRange(1–365 Tage),groupBy(model/user/feature/day) - RBAC: wie oben
- Query-Params:
app.py: Router registriert (auditRouter)
Phase 5: Frontend — Compliance & Audit Page
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)
-
API-Aufrufe direkt über
useApiRequestHook (kein separatesauditApi.ts/useAudit.tsnötig — Pattern konsistent mit anderen Seiten) -
ComplianceAuditPage.module.css— CSS Module mit Dark-Mode-Support via CSS-Variablen, responsive Chart-Grid
Querschnitt-Checks
- API-Endpunkte: 4 neue Endpoints unter
/api/audit/ - DB-Schema / Migration:
AiAuditLogEntry— Auto-Init via_ensureTableExists - Frontend-Komponenten:
ComplianceAuditPage(neu), Navigation-Anpassung - RBAC / Permissions: SysAdmin + Mandate-Admin +
ui.system.complianceAuditUI-Objekt-Berechtigung - Neutralisierung betroffen? Felder vorbereitet (
neutralizationActive,neutralizationMappingsCount) - Navigation / Routing: Neue Subgroup "Übersichten", Integrationen verschoben
- Billing-Impact? Nein (ergänzend zu Billing, nicht ersetzend)
- i18n: Alle Frontend-Labels mit
t(), Backend-Labels mitapiRouteContext, 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
- b-reference/ aktualisiert (
b-reference/platform/audit.md— neu angelegt) - TOPICS.md aktualisiert (neues Thema "Compliance & Audit")
- Dieses Dokument → c-work/4-done/ verschoben