upd
This commit is contained in:
parent
cf2e875968
commit
788b63907a
5 changed files with 160 additions and 57 deletions
|
|
@ -35,6 +35,7 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en).
|
|||
| RBAC | b-reference/platform/rbac.md | 4-Stufen-Modell, Template-Rollen, Resolution, Datenmodell |
|
||||
| Datenbank-Architektur | b-reference/platform/database-architecture.md | Interface-Pattern, Connector, Auto-Init, DB-Liste |
|
||||
| Navigation | b-reference/platform/navigation.md | Menü-Struktur, Admin-Seiten, API |
|
||||
| Compliance & AI-Audit | b-reference/platform/audit.md | AI-Datenfluss-Log, Security-Audit, Statistiken, RBAC |
|
||||
| i18n / Mehrsprachigkeit | b-reference/gateway/architecture.md (Abschnitt i18n), d-guides/coding-conventions.md (Backend i18n), b-reference/frontend-nyla/architecture.md (Routing/i18n) | `t()`, `@i18nModel`, UiLanguageSet, TextMultilingual, AI-Uebersetzung, Boot-Sync |
|
||||
|
||||
## Aktive Arbeiten (c-work)
|
||||
|
|
|
|||
112
b-reference/platform/audit.md
Normal file
112
b-reference/platform/audit.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<!-- status: canonical -->
|
||||
<!-- lastReviewed: 2026-04-14 -->
|
||||
|
||||
# Compliance & AI-Audit
|
||||
|
||||
## Überblick
|
||||
|
||||
PORTA protokolliert jeden AI-Provider-Call in einem dedizierten **AI-Audit-Log**. Parallel existiert das bestehende **Security/GDPR-Audit-Log** für Zugriffs- und Sicherheitsereignisse. Beide Logs sind über die Compliance-Seite im Frontend einsehbar.
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
AI-Pipeline (mainServiceAi._createBillingCallback)
|
||||
│
|
||||
├──> serviceBilling.recordUsage() (Abrechnung)
|
||||
└──> aiAuditLogger.logAiCall() (Compliance-Log)
|
||||
│
|
||||
└──> DB: poweron_app / Tabelle AiAuditLogEntry
|
||||
```
|
||||
|
||||
## Backend-Komponenten
|
||||
|
||||
| Datei | Funktion |
|
||||
|-------|----------|
|
||||
| `modules/datamodels/datamodelAiAudit.py` | Pydantic-Model `AiAuditLogEntry` mit `@i18nModel` |
|
||||
| `modules/shared/aiAuditLogger.py` | Singleton `aiAuditLogger` — schreibt und liest AI-Audit-Einträge |
|
||||
| `modules/routes/routeAudit.py` | 4 API-Endpoints unter `/api/audit/` |
|
||||
| `modules/shared/auditLogger.py` | Bestehendes Security/GDPR-Audit-Log (`AuditLogEntry`) |
|
||||
|
||||
### Datenmodell: AiAuditLogEntry
|
||||
|
||||
Kernfelder:
|
||||
|
||||
- **Kontext:** `userId`, `username`, `mandateId`, `featureInstanceId`, `featureCode`, `instanceLabel`
|
||||
- **AI-Call:** `aiProvider`, `aiModel`, `operationType`, `tokensInput`, `tokensOutput`, `processingTimeMs`, `priceCHF`
|
||||
- **Neutralisierung:** `neutralizationActive`, `neutralizationMappingsCount`
|
||||
- **Content:** `contentStored`, `contentInputHash` (SHA-256), `contentInputPreview` / `contentOutputPreview` (200 Zeichen), `contentInputFull` / `contentOutputFull` (nur bei Mandant opt-in)
|
||||
- **Status:** `success`, `errorMessage`
|
||||
|
||||
### AI-Audit-Logger API
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---------|-------------|
|
||||
| `logAiCall(userId, mandateId, aiProvider, aiModel, ...)` | Schreibt einen Eintrag |
|
||||
| `getAiAuditLogs(mandateId, *, userId, featureInstanceId, ...)` | Paginierte Abfrage mit Filtern |
|
||||
| `getAiAuditEntryContent(entryId, mandateId)` | Vollständiger Content eines Eintrags |
|
||||
| `getAiAuditStats(mandateId, *, timeRangeDays, groupBy)` | Aggregierte Statistiken |
|
||||
|
||||
### Pipeline-Integration
|
||||
|
||||
In `mainServiceAi.py` wird der `_createBillingCallback` nach jedem erfolgreichen oder fehlerhaften AI-Call aufgerufen. Neben dem Billing-Eintrag schreibt er einen AI-Audit-Eintrag. Der Audit-Call ist in `try/except` gewrappt — Fehler im Audit-Logger brechen den AI-Call nicht ab.
|
||||
|
||||
## API-Endpoints
|
||||
|
||||
| Endpoint | Tab | Query-Parameter |
|
||||
|----------|-----|-----------------|
|
||||
| `GET /api/audit/ai-log` | A: AI-Datenfluss | `userId`, `featureInstanceId`, `aiModel`, `dateFrom`, `dateTo`, `limit`, `offset` |
|
||||
| `GET /api/audit/ai-log/{entryId}/content` | A: Detail | — |
|
||||
| `GET /api/audit/log` | B: Security/GDPR | `userId`, `category`, `action`, `dateFrom`, `dateTo`, `limit` |
|
||||
| `GET /api/audit/stats` | C: Statistiken | `timeRange` (Tage), `groupBy` |
|
||||
|
||||
### RBAC
|
||||
|
||||
Alle Endpoints prüfen über `_requireAuditAccess`:
|
||||
1. SysAdmin → Zugriff
|
||||
2. `ui.system.complianceAudit` UI-Objekt mit `view`-Berechtigung → Zugriff
|
||||
3. Sonst → HTTP 403
|
||||
|
||||
## Frontend
|
||||
|
||||
| Datei | Funktion |
|
||||
|-------|----------|
|
||||
| `pages/ComplianceAuditPage.tsx` | Hauptseite mit 3 Tabs |
|
||||
| `pages/ComplianceAuditPage.module.css` | Styling (Dark-Mode via CSS-Variablen) |
|
||||
| `config/pageRegistry.tsx` | Icon `FaShieldAlt` für `page.system.complianceAudit` |
|
||||
| `App.tsx` | Route `/compliance-audit` |
|
||||
|
||||
### Tab A: AI-Datenfluss-Log
|
||||
|
||||
Tabelle mit Zeitpunkt, Benutzer, Feature, AI-Modell (Badge), Typ, Tokens (↑/↓), Kosten, Neutralisierung, Status. Pagination in 50er-Schritten.
|
||||
|
||||
### Tab B: Audit-Log
|
||||
|
||||
Tabelle mit Zeitpunkt, Benutzer, Kategorie (farbcodiert nach Typ), Aktion, Ressource, Details, Erfolg/Fehler, IP-Adresse.
|
||||
|
||||
### Tab C: Statistiken
|
||||
|
||||
Zeitraum-Selektor (7/30/90 Tage), KPI-Karten (Total Calls, Neutralisierungsquote, Modelle, Kosten), Charts via recharts (Line, Pie, Bar).
|
||||
|
||||
## Navigation
|
||||
|
||||
"Compliance & Audit" ist in der neuen Subgroup **"Übersichten"** unter "Meine Sicht" angeordnet, zusammen mit "Integrationen":
|
||||
|
||||
```
|
||||
Meine Sicht
|
||||
├── Übersicht (Home)
|
||||
├── Übersichten
|
||||
│ ├── Integrationen
|
||||
│ └── Compliance & Audit ← neu
|
||||
├── Basisdaten
|
||||
│ ├── Verbindungen
|
||||
│ ├── Dateien
|
||||
│ └── Prompts
|
||||
└── Nutzung
|
||||
├── Abrechnung
|
||||
├── Statistiken
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Content-Speicherung (Opt-in)
|
||||
|
||||
Full-Content-Speicherung (Prompt + Response) ist im Datenmodell vorbereitet (`contentInputFull`, `contentOutputFull`, `contentStored`), aber standardmässig deaktiviert. Nur Metadaten + Previews (200 Zeichen) werden gespeichert. Die Aktivierung pro Mandant ist für eine spätere Phase vorgesehen.
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<!-- status: plan -->
|
||||
<!-- status: done -->
|
||||
<!-- started: 2026-04-13 -->
|
||||
<!-- completed: 2026-04-14 -->
|
||||
<!-- component: gateway | frontend-nyla | platform -->
|
||||
|
||||
# Compliance & Audit View + Navigations-Rubrik "Übersichten"
|
||||
|
|
@ -112,17 +113,17 @@ Für den Compliance-View brauchen wir ein **neues AI-Audit-Log**, das pro AI-Int
|
|||
|
||||
### Phase 1: Navigation — Subgroup "Übersichten" (Gateway + Frontend)
|
||||
|
||||
- [ ] **`mainSystem.py`:** Neue Subgroup `system-overviews` ("Übersichten") unter Section `system` erstellen
|
||||
- [ ] **`mainSystem.py`:** "Integrationen" von Top-Level-Item in die neue Subgroup verschieben
|
||||
- [ ] **`mainSystem.py`:** Neues Item "Compliance & Audit" in Subgroup `system-overviews` hinzufügen
|
||||
- [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"`
|
||||
- [ ] **`pageRegistry.tsx`:** Icon-Eintrag für `page.system.complianceAudit`
|
||||
- [ ] **`App.tsx`:** Route `/compliance-audit` → `ComplianceAuditPage`
|
||||
- [ ] **Frontend Navigation:** Sicherstellen, dass `MandateNavigation.tsx` Subgroups unter "Meine Sicht" korrekt rendert (bestehendes Pattern: Basisdaten, Nutzung)
|
||||
- [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
|
||||
|
||||
- [ ] **`datamodelAiAudit.py`** (neu) — Datenmodell:
|
||||
- [x] **`datamodelAiAudit.py`** (neu) — Datenmodell:
|
||||
|
||||
```python
|
||||
class AiAuditLogEntry(BaseModel):
|
||||
|
|
@ -160,78 +161,68 @@ class AiAuditLogEntry(BaseModel):
|
|||
errorMessage: Optional[str]
|
||||
```
|
||||
|
||||
- [ ] **`aiAuditLogger.py`** (neu) — Service zum Schreiben von AI-Audit-Einträgen
|
||||
- [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
|
||||
- [ ] **DB-Tabelle** `ai_audit_log` anlegen (via DatabaseConnector-Pattern)
|
||||
- [x] **DB-Tabelle** `ai_audit_log` — Auto-Init via `_ensureTableExists(AiAuditLogEntry)` im DatabaseConnector-Pattern
|
||||
|
||||
### Phase 3: Backend — AI-Audit in AI-Pipeline integrieren
|
||||
|
||||
- [ ] **`mainServiceAi.py`:** Nach jedem AI-Call `aiAuditLogger.logAiCall()` aufrufen
|
||||
- [x] **`mainServiceAi.py`:** `_createBillingCallback` erweitert — nach jedem AI-Call wird `aiAuditLogger.logAiCall()` aufgerufen
|
||||
- Provider, Model, Tokens, Processing-Time aus `AiCallResponse`
|
||||
- Content (Input/Output) nur wenn Mandant opt-in
|
||||
- Neutralisierungs-Status aus Call-Context
|
||||
- [ ] **`mainServiceAgent.py`:** Agent-Calls ebenfalls loggen (delegiert an serviceAi)
|
||||
- [ ] **Neutralisierungs-Integration:** Wenn Neutralisierung aktiv, `neutralizationActive=True` + Mapping-Count loggen
|
||||
- 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
|
||||
|
||||
- [ ] **`routeAudit.py`** (neu) — API-Endpoints:
|
||||
- [x] **`routeAudit.py`** (neu) — API-Endpoints:
|
||||
- `GET /api/audit/ai-log` — AI-Datenfluss-Log (Tab A)
|
||||
- Query-Params: `mandateId`, `userId`, `featureInstanceId`, `aiModel`, `dateFrom`, `dateTo`, `limit`, `offset`
|
||||
- RBAC: Mandate-Admin oder `compliance-viewer`
|
||||
- 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: Mandate-Admin oder `compliance-viewer`
|
||||
- RBAC: wie oben
|
||||
- `GET /api/audit/log` — Security/GDPR Audit-Log (Tab B)
|
||||
- Query-Params: `mandateId`, `userId`, `category`, `action`, `dateFrom`, `dateTo`, `limit`, `offset`
|
||||
- RBAC: Mandate-Admin oder `compliance-viewer`
|
||||
- Query-Params: `userId`, `category`, `action`, `dateFrom`, `dateTo`, `limit`
|
||||
- RBAC: wie oben
|
||||
- `GET /api/audit/stats` — Audit-Statistiken (Tab C)
|
||||
- Query-Params: `mandateId`, `timeRange` (7d/30d/90d/custom), `groupBy` (model/user/feature/day)
|
||||
- RBAC: Mandate-Admin oder `compliance-viewer`
|
||||
- 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
|
||||
|
||||
- [ ] **`ComplianceAuditPage.tsx`** (neu) — Hauptseite mit 3 Tabs:
|
||||
- [x] **`ComplianceAuditPage.tsx`** (neu) — Hauptseite mit 3 Tabs:
|
||||
|
||||
**Tab A: AI-Datenfluss-Log**
|
||||
- Tabelle mit Spalten: Zeitpunkt, User, Instanz (Feature + Label), AI-Modell, Typ, Tokens (In/Out), Kosten, Neutralisierung (Ja/Nein), Preview, Download-Button
|
||||
- Filter: Zeitraum, User, Feature, Modell
|
||||
- Sortierung: nach Zeitpunkt (neueste zuerst)
|
||||
- Pagination
|
||||
- Download-Button pro Eintrag → öffnet Detail-Modal oder lädt Content
|
||||
- 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 mit Spalten: Zeitpunkt, User, Kategorie, Aktion, Ressource, Details, Erfolg, IP
|
||||
- Filter: Zeitraum, User, Kategorie, Aktion
|
||||
- Farbcodierung: Erfolg (grün), Fehler (rot), Warnung (gelb)
|
||||
- Pagination
|
||||
- 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 Tage, 30 Tage, 90 Tage, Custom)
|
||||
- Kontext-Filter (Mandant, Feature, User)
|
||||
- Charts:
|
||||
- AI-Calls pro Tag (Liniendiagramm)
|
||||
- AI-Calls nach Modell (Donut/Pie)
|
||||
- AI-Calls nach Feature (Balkendiagramm)
|
||||
- Kosten-Verlauf (Liniendiagramm)
|
||||
- Top-User nach AI-Usage (Balkendiagramm)
|
||||
- Neutralisierungs-Quote (Gauge oder Prozent-Anzeige)
|
||||
- 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)
|
||||
|
||||
- [ ] **`auditApi.ts`** (neu) — API-Funktionen für alle Endpoints
|
||||
- [ ] **`useAudit.ts`** (neu) — Hooks: `useAiAuditLog()`, `useAuditLog()`, `useAuditStats()`
|
||||
- [ ] **CSS/Styling** — konsistent mit bestehenden Admin-Seiten, Dark-Mode-Support
|
||||
- [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
|
||||
|
||||
- [ ] API-Endpunkte: 4 neue Endpoints unter `/api/audit/`
|
||||
- [ ] DB-Schema / Migration: ja — neue Tabelle `ai_audit_log`
|
||||
- [ ] Frontend-Komponenten: `ComplianceAuditPage` (neu), Navigation-Anpassung
|
||||
- [ ] RBAC / Permissions: Mandate-Admin + neue Rolle `compliance-viewer`
|
||||
- [ ] Neutralisierung betroffen? Ja — Neutralisierungs-Status wird im AI-Audit-Log erfasst
|
||||
- [ ] Navigation / Routing: Neue Subgroup "Übersichten", Integrationen verschoben
|
||||
- [ ] Billing-Impact? Nein (ergänzend zu Billing, nicht ersetzend)
|
||||
- [ ] i18n: Alle Labels mehrsprachig (bestehendes Pattern)
|
||||
- [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"]`
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -273,7 +264,6 @@ class AiAuditLogEntry(BaseModel):
|
|||
|
||||
## Abschluss
|
||||
|
||||
- [ ] b-reference/ aktualisiert (`b-reference/platform/audit.md` — neu anlegen)
|
||||
- [ ] b-reference/gateway/architecture.md aktualisiert (AI-Audit-Logger)
|
||||
- [ ] TOPICS.md aktualisiert (neues Thema "Compliance & Audit")
|
||||
- [ ] Dieses Dokument → z-archive/ verschoben
|
||||
- [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
|
||||
Binary file not shown.
Loading…
Reference in a new issue