# Banner Consent — Device-basiertes Cookie-Consent Das Banner-Consent-Modul verwaltet **anonyme Geraete-Consents** fuer Cookie-Banner auf Kunden-Websites. Es ermoeglicht die Erfassung, Verwaltung und den DSGVO-konformen Export von Cookie-Einwilligungen ohne personenbezogene Daten — stattdessen wird ein Device-Fingerprint verwendet. --- ## Uebersicht | Eigenschaft | Wert | |-------------|------| | **SDK-Route** | `/sdk/cookie-banner` | | **Backend** | `backend-compliance:8002` | | **Router-Prefix** | `/api/compliance/banner` | | **Rechtsgrundlage** | TTDSG § 25, Art. 5 Abs. 3 ePrivacy-RL | | **DB-Migration** | 029_banner_consent.sql | | **Tests** | 25 Tests (`test_banner_routes.py`) | | **Status** | 100% | --- ## Funktionsprinzip ```mermaid graph LR A[Kunden-Website] -->|POST /banner/consent| B[Compliance Backend] B -->|Upsert| C[(compliance_banner_consents)] B -->|Audit-Log| D[(compliance_banner_consent_audit_log)] E[Admin Dashboard] -->|GET /banner/admin/stats| B E -->|Site/Category Config| B ``` 1. **Besucher** oeffnet Website → Cookie-Banner wird angezeigt 2. **Besucher** waehlt Kategorien (Notwendig, Analyse, Marketing, ...) → `POST /banner/consent` 3. **Backend** speichert Consent per `site_id` + `device_fingerprint` (Upsert — bei erneutem Besuch wird aktualisiert) 4. **IP-Adresse** wird als SHA256-Hash gespeichert (Datenschutz) 5. **Admin** kann Statistiken pro Site einsehen (Acceptance Rate pro Kategorie) --- ## API-Endpoints ### Public SDK-Endpoints (fuer Einbettung in Kunden-Websites) | Methode | Pfad | Beschreibung | |---------|------|--------------| | `POST` | `/banner/consent` | Device-Consent erfassen (Upsert) | | `GET` | `/banner/consent` | Consent abrufen (`?site_id=...&device_fingerprint=...`) | | `DELETE` | `/banner/consent/{id}` | Consent widerrufen | | `GET` | `/banner/config/{site_id}` | Site-Konfiguration laden (Banner-Titel, Kategorien) | | `GET` | `/banner/consent/export` | DSGVO-Export (Consents + Audit-Trail) | ### Admin-Endpoints | Methode | Pfad | Beschreibung | |---------|------|--------------| | `GET` | `/banner/admin/stats/{site_id}` | Consent-Statistiken (total, pro Kategorie) | ### Site-Konfiguration | Methode | Pfad | Beschreibung | |---------|------|--------------| | `GET` | `/banner/admin/sites` | Alle Site-Konfigurationen | | `POST` | `/banner/admin/sites` | Neue Site anlegen | | `PUT` | `/banner/admin/sites/{site_id}` | Site aktualisieren | | `DELETE` | `/banner/admin/sites/{site_id}` | Site loeschen | ### Kategorien-Verwaltung | Methode | Pfad | Beschreibung | |---------|------|--------------| | `GET` | `/banner/admin/sites/{site_id}/categories` | Kategorien einer Site | | `POST` | `/banner/admin/sites/{site_id}/categories` | Kategorie hinzufuegen | | `DELETE` | `/banner/admin/categories/{id}` | Kategorie loeschen | ### Vendor-Verwaltung | Methode | Pfad | Beschreibung | |---------|------|--------------| | `GET` | `/banner/admin/sites/{site_id}/vendors` | Vendors einer Site | | `POST` | `/banner/admin/sites/{site_id}/vendors` | Vendor hinzufuegen | | `DELETE` | `/banner/admin/vendors/{id}` | Vendor loeschen | --- ## DB-Tabellen (Migration 029) | Tabelle | Beschreibung | |---------|--------------| | `compliance_banner_consents` | Anonyme Geraete-Consents (site_id, device_fingerprint, categories, ip_hash, expires_at) | | `compliance_banner_consent_audit_log` | Immutabler Audit-Trail (consent_given, consent_updated, consent_withdrawn) | | `compliance_banner_site_configs` | Site-Konfiguration (Banner-Titel, Privacy-URL, DSB-Info, TCF) | | `compliance_banner_category_configs` | Consent-Kategorien pro Site (name_de, name_en, is_required, sort_order) | | `compliance_banner_vendor_configs` | Third-Party-Vendor-Tracking (cookie_names, retention_days) | --- ## Consent-Erfassung ### Request (POST /banner/consent) ```json { "site_id": "example.com", "device_fingerprint": "fp-a1b2c3d4e5", "categories": ["necessary", "analytics"], "ip_address": "192.168.1.100" } ``` ### Response ```json { "id": "uuid", "site_id": "example.com", "device_fingerprint": "fp-a1b2c3d4e5", "categories": ["necessary", "analytics"], "ip_hash": "a1b2c3...", "expires_at": "2027-03-05T10:00:00Z", "created_at": "2026-03-05T10:00:00Z" } ``` !!! info "Upsert-Verhalten" Wenn ein Consent fuer die gleiche Kombination `site_id` + `device_fingerprint` existiert, wird der bestehende Eintrag aktualisiert (Kategorien ueberschrieben, `updated_at` gesetzt). Die IP wird immer als SHA256-Hash gespeichert — nie im Klartext. --- ## Statistiken `GET /banner/admin/stats/{site_id}` liefert: ```json { "site_id": "example.com", "total_consents": 1542, "category_acceptance": { "necessary": { "count": 1542, "percentage": 100.0 }, "analytics": { "count": 892, "percentage": 57.8 }, "marketing": { "count": 423, "percentage": 27.4 } } } ``` --- ## Frontend-Proxy | Frontend-Route | Ziel | |----------------|------| | `/api/sdk/v1/compliance/banner/*` | `backend:8002/api/compliance/banner/*` | Nutzt den bestehenden Compliance-Catch-All-Proxy (`/api/sdk/v1/compliance/[[...path]]`).