This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/docs/consent-banner/SPECIFICATION.md
Benjamin Admin bfdaf63ba9 fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00

48 KiB

Cookie & Consent Banner - Technische Spezifikation

Version: 1.0.0 Status: Draft Lizenz: Apache 2.0 (Open Source, kommerziell nutzbar) Letzte Aktualisierung: 2026-02-04


Inhaltsverzeichnis

  1. Executive Summary
  2. Rechtliche Anforderungen
  3. Architektur-Übersicht
  4. Consent-Kategorien
  5. SDK-Spezifikation
  6. API-Spezifikation
  7. UI/UX-Anforderungen
  8. Plattform-Integrationen
  9. Datenspeicherung & Audit
  10. Sicherheit & Privacy
  11. Implementierungs-Roadmap
  12. Anhang

1. Executive Summary

1.1 Projektziel

Entwicklung eines plattformübergreifenden Consent-Management-Systems (CMP), das:

  • DSGVO, TTDSG und ePrivacy-Richtlinie vollständig erfüllt
  • In PWAs, Websites, Mobile Apps und Desktop-Anwendungen integrierbar ist
  • Als Open-Source-Lösung kommerziell nutzbar ist (Apache 2.0)
  • Über SDKs für alle gängigen Plattformen verfügbar ist
  • Mit dem bestehenden BreakPilot Consent-Service integriert

1.2 Kernfunktionen

Funktion Beschreibung
Consent Collection Granulare Einwilligung pro Kategorie und Anbieter
Consent Storage Revisionssichere Speicherung aller Einwilligungen
Consent Withdrawal Jederzeitiger Widerruf mit gleicher Einfachheit
Cross-Platform Sync Consent-Status über alle Plattformen synchronisiert
TCF 2.2 Support IAB Transparency & Consent Framework Integration
A/B Testing DSGVO-konforme Banner-Optimierung
Analytics Anonymisierte Consent-Statistiken

1.3 Zielplattformen

  • Web: JavaScript SDK (Vanilla, React, Vue, Angular, Svelte)
  • PWA: Service Worker Integration mit Offline-Support
  • iOS: Swift SDK (SwiftUI & UIKit)
  • Android: Kotlin SDK (Jetpack Compose & XML Views)
  • Flutter: Cross-Platform SDK
  • React Native: Cross-Platform SDK

2. Rechtliche Anforderungen

2.1 DSGVO (EU 2016/679)

Artikel Anforderung Umsetzung
Art. 4 Nr. 11 Einwilligung muss freiwillig, bestimmt, informiert und unmissverständlich sein Granulare Opt-in-Buttons, keine vorausgewählten Checkboxen
Art. 6 Abs. 1 lit. a Einwilligung als Rechtsgrundlage Dokumentierte Consent-Erfassung mit Timestamp
Art. 7 Abs. 1 Nachweis der Einwilligung Revisionssichere Speicherung, Audit-Log
Art. 7 Abs. 2 Abgrenzung von anderen Sachverhalten Separate Consent-Abfrage, kein Bundling
Art. 7 Abs. 3 Widerruf jederzeit möglich Persistenter "Einstellungen"-Button, gleichwertige Widerrufsmöglichkeit
Art. 7 Abs. 4 Koppelungsverbot Keine Dienstverweigerung bei Ablehnung
Art. 12 Transparente Information Klare, verständliche Sprache
Art. 13/14 Informationspflichten Verlinkung zur Datenschutzerklärung
Art. 17 Recht auf Löschung Löschung aller Consent-Daten auf Anfrage
Art. 20 Datenportabilität Export aller Consent-Daten als JSON

2.2 TTDSG (Deutschland)

§ Anforderung Umsetzung
§ 25 Abs. 1 Einwilligung für nicht-notwendige Cookies Opt-in für alle nicht-essentiellen Technologien
§ 25 Abs. 2 Ausnahmen für technisch notwendige Speicherung Klare Kategorisierung "Essentiell" ohne Einwilligung
§ 25 Abs. 2 Nr. 2 Ausnahme für vom Nutzer gewünschte Dienste Dokumentation der Notwendigkeit

2.3 ePrivacy-Richtlinie (2002/58/EG)

Artikel Anforderung Umsetzung
Art. 5 Abs. 3 Einwilligung vor Cookie-Setzung Blockierung aller Skripte bis Consent
Art. 5 Abs. 3 Klare Information über Zweck Transparente Kategoriebeschreibungen

2.4 Planet49-Urteil (EuGH C-673/17)

Kernaussagen:

  • Vorausgewählte Checkboxen sind KEINE gültige Einwilligung
  • Cookie-Laufzeit muss angegeben werden
  • Drittanbieter müssen benannt werden

Umsetzung:

  • Alle Checkboxen standardmäßig NICHT ausgewählt
  • Anzeige der Cookie-Laufzeit pro Anbieter
  • Auflistung aller Drittanbieter mit Links zu deren Datenschutzerklärung

2.5 DSK-Orientierungshilfe Telemedien

Anforderungen:

  1. "Ablehnen" muss genauso prominent sein wie "Akzeptieren"
  2. Keine Dark Patterns (versteckte Ablehnungsoptionen)
  3. Keine Nudging-Techniken (farbliche Hervorhebung von "Akzeptieren")
  4. Direkter Zugang zu granularen Einstellungen

Kernaussagen:

  • "Alles akzeptieren" nur zulässig wenn gleichwertige "Alles ablehnen"-Option
  • Keine versteckten Ablehungs-Flows
  • Consent-Banner darf Seiteninhalt nicht vollständig verdecken

3. Architektur-Übersicht

3.1 System-Architektur

┌─────────────────────────────────────────────────────────────────────────┐
│                         Client-Plattformen                               │
├──────────┬──────────┬──────────┬──────────┬──────────┬─────────────────┤
│   Web    │   PWA    │   iOS    │ Android  │ Flutter  │  React Native   │
│   SDK    │   SDK    │   SDK    │   SDK    │   SDK    │      SDK        │
└────┬─────┴────┬─────┴────┬─────┴────┬─────┴────┬─────┴────────┬────────┘
     │          │          │          │          │              │
     └──────────┴──────────┴────┬─────┴──────────┴──────────────┘
                                │
                    ┌───────────▼───────────┐
                    │   Consent Gateway     │
                    │   (REST + WebSocket)  │
                    └───────────┬───────────┘
                                │
     ┌──────────────────────────┼──────────────────────────┐
     │                          │                          │
     ▼                          ▼                          ▼
┌─────────────┐      ┌─────────────────┐      ┌─────────────────┐
│   Consent   │      │   Config        │      │   Analytics     │
│   Service   │      │   Service       │      │   Service       │
│   (Go)      │      │   (Go)          │      │   (Go)          │
└──────┬──────┘      └────────┬────────┘      └────────┬────────┘
       │                      │                        │
       └──────────────────────┼────────────────────────┘
                              │
                    ┌─────────▼─────────┐
                    │    PostgreSQL     │
                    │  (Consent Store)  │
                    └───────────────────┘

3.2 Komponenten

Komponente Technologie Beschreibung
Web SDK TypeScript Vanilla JS + Framework-Wrapper
Mobile SDKs Swift/Kotlin Native Implementierungen
Consent Gateway Go + Gin API-Gateway mit Rate-Limiting
Consent Service Go Consent-Logik, bereits vorhanden
Config Service Go Banner-Konfiguration, TCF-Vendors
Analytics Service Go Anonymisierte Statistiken
PostgreSQL PostgreSQL 16 Revisionssichere Speicherung

3.3 Datenfluss

1. Nutzer öffnet Website/App
         │
         ▼
2. SDK prüft lokalen Consent-Status
         │
    ┌────┴────┐
    │ Consent │
    │ exists? │
    └────┬────┘
    No   │   Yes
    │    │    │
    ▼    │    ▼
3. Banner│ 5. Apply
   anzeigen   Consent
         │
         ▼
4. Nutzer wählt
   Kategorien
         │
         ▼
6. SDK speichert lokal
   + sendet an Backend
         │
         ▼
7. Backend speichert
   revisionssicher
         │
         ▼
8. SDK blockiert/erlaubt
   entsprechende Skripte

4.1 Standard-Kategorien (IAB TCF 2.2 kompatibel)

ID Kategorie Beschreibung Rechtsgrundlage
essential Essentiell Technisch notwendig für Grundfunktionen TTDSG § 25 Abs. 2 (keine Einwilligung nötig)
functional Funktional Personalisierung, Spracheinstellungen DSGVO Art. 6 Abs. 1 lit. a
analytics Statistik Anonyme Nutzungsanalyse DSGVO Art. 6 Abs. 1 lit. a
marketing Marketing Werbung, Retargeting DSGVO Art. 6 Abs. 1 lit. a
social Soziale Medien Social Plugins, Sharing DSGVO Art. 6 Abs. 1 lit. a

4.2 Kategorie-Details

4.2.1 Essentiell (essential)

Beschreibung: Cookies und Technologien, die für den Betrieb der Website unbedingt erforderlich sind.

Beispiele:

  • Session-Cookies
  • Warenkorb-Cookies
  • Authentifizierung
  • Load-Balancing
  • CSRF-Token
  • Consent-Cookie selbst

Rechtsgrundlage: TTDSG § 25 Abs. 2 Nr. 2 - keine Einwilligung erforderlich

UI: Immer aktiv, nicht deaktivierbar, mit Erklärung warum

4.2.2 Funktional (functional)

Beschreibung: Cookies, die die Website-Funktionalität verbessern, aber nicht essentiell sind.

Beispiele:

  • Sprachpräferenzen
  • Theme-Einstellungen (Dark Mode)
  • Zuletzt angesehene Produkte
  • Chat-Widget-Status
  • Video-Player-Einstellungen

Rechtsgrundlage: DSGVO Art. 6 Abs. 1 lit. a - Einwilligung erforderlich

4.2.3 Statistik (analytics)

Beschreibung: Cookies zur anonymen Analyse des Nutzerverhaltens.

Beispiele:

  • Google Analytics
  • Matomo/Piwik
  • Hotjar (Heatmaps)
  • Plausible Analytics

Rechtsgrundlage: DSGVO Art. 6 Abs. 1 lit. a - Einwilligung erforderlich

Hinweis: Auch bei Anonymisierung ist Einwilligung erforderlich (EuGH-Rechtsprechung)

4.2.4 Marketing (marketing)

Beschreibung: Cookies für personalisierte Werbung und Retargeting.

Beispiele:

  • Google Ads
  • Facebook Pixel
  • LinkedIn Insight Tag
  • Criteo
  • Affiliate-Tracking

Rechtsgrundlage: DSGVO Art. 6 Abs. 1 lit. a - Einwilligung erforderlich

4.2.5 Soziale Medien (social)

Beschreibung: Cookies von Social-Media-Plattformen.

Beispiele:

  • Facebook Like-Button
  • Twitter Share
  • Instagram Embed
  • YouTube Embed
  • LinkedIn Share

Rechtsgrundlage: DSGVO Art. 6 Abs. 1 lit. a - Einwilligung erforderlich

4.3 Anbieter-Granularität (TCF 2.2)

Zusätzlich zur Kategorie kann der Nutzer einzelne Anbieter aktivieren/deaktivieren:

interface ConsentVendor {
  id: string;              // TCF Vendor ID oder custom ID
  name: string;            // "Google LLC"
  category: ConsentCategory;
  purposes: TCFPurpose[];  // IAB TCF Purposes
  legitimateInterests?: TCFPurpose[];
  cookies: CookieInfo[];
  privacyPolicyUrl: string;
  dataRetention: string;   // "2 Jahre" / "Session"
  dataTransfer?: string;   // "USA (EU-US DPF)" / "EU"
}

interface CookieInfo {
  name: string;           // "_ga"
  domain: string;         // ".example.com"
  expiration: string;     // "2 Jahre"
  type: "http" | "localStorage" | "sessionStorage" | "indexedDB";
  description: string;
}

5. SDK-Spezifikation

5.1 Web SDK (JavaScript/TypeScript)

5.1.1 Installation

# npm
npm install @breakpilot/consent-sdk

# yarn
yarn add @breakpilot/consent-sdk

# pnpm
pnpm add @breakpilot/consent-sdk

# CDN (für Vanilla JS)
<script src="https://cdn.breakpilot.eu/consent-sdk/v1/consent.min.js"></script>

5.1.2 Basis-Konfiguration

import { ConsentManager, ConsentConfig } from '@breakpilot/consent-sdk';

const config: ConsentConfig = {
  // Pflichtfelder
  apiEndpoint: 'https://consent.example.com/api/v1',
  siteId: 'site_abc123',

  // Sprache
  language: 'de',
  fallbackLanguage: 'en',

  // UI-Optionen
  ui: {
    position: 'bottom',           // 'bottom' | 'top' | 'center'
    layout: 'bar',                // 'bar' | 'modal' | 'floating'
    theme: 'auto',                // 'light' | 'dark' | 'auto'
    customCss: '/css/consent.css',
    zIndex: 999999,
    blockScrollOnModal: true,
  },

  // Consent-Optionen
  consent: {
    required: true,               // Muss Nutzer interagieren?
    rejectAllVisible: true,       // "Alle ablehnen" Button sichtbar
    acceptAllVisible: true,       // "Alle akzeptieren" Button sichtbar
    granularControl: true,        // Einzelne Kategorien wählbar
    vendorControl: true,          // Einzelne Anbieter wählbar
    rememberChoice: true,         // Auswahl speichern
    rememberDays: 365,            // Speicherdauer in Tagen
    geoTargeting: true,           // Nur in EU anzeigen
    recheckAfterDays: 180,        // Erneut nachfragen nach X Tagen
  },

  // Kategorien aktivieren
  categories: ['essential', 'functional', 'analytics', 'marketing', 'social'],

  // Callbacks
  onConsentChange: (consent) => {
    console.log('Consent changed:', consent);
  },
  onBannerShow: () => {
    console.log('Banner shown');
  },
  onBannerHide: () => {
    console.log('Banner hidden');
  },

  // Debug-Modus
  debug: process.env.NODE_ENV === 'development',
};

// Manager initialisieren
const consent = new ConsentManager(config);
consent.init();

5.1.3 Skript-Blocking

<!-- Skripte mit data-consent blockieren -->
<script
  data-consent="analytics"
  data-src="https://www.googletagmanager.com/gtag/js?id=GA-XXXXX"
  type="text/plain">
</script>

<!-- Inline-Skripte blockieren -->
<script data-consent="marketing" type="text/plain">
  fbq('init', 'XXXXX');
</script>

<!-- iFrames blockieren (YouTube, etc.) -->
<iframe
  data-consent="social"
  data-src="https://www.youtube.com/embed/XXXXX"
  title="YouTube Video">
  <p>Bitte akzeptieren Sie Marketing-Cookies, um dieses Video zu sehen.</p>
</iframe>

5.1.4 API-Methoden

// Consent-Status prüfen
const hasAnalytics = consent.hasConsent('analytics');
const hasVendor = consent.hasVendorConsent('google-analytics');

// Consent programmatisch setzen
await consent.setConsent({
  essential: true,
  functional: true,
  analytics: false,
  marketing: false,
  social: false,
});

// Alle Einwilligungen widerrufen
await consent.revokeAll();

// Banner erneut anzeigen
consent.showBanner();

// Einstellungs-Modal öffnen
consent.showSettings();

// Consent-Objekt abrufen
const currentConsent = consent.getConsent();
// {
//   categories: { essential: true, analytics: false, ... },
//   vendors: { 'google-analytics': false, ... },
//   timestamp: '2026-02-04T12:00:00Z',
//   version: '1.0.0',
//   consentId: 'cns_abc123',
// }

// Consent exportieren (für Nutzeranfragen)
const exportData = consent.exportConsent();
// JSON mit allen historischen Consents

// Event-Listener
consent.on('change', (newConsent) => { ... });
consent.on('vendor:enable', (vendorId) => { ... });
consent.on('vendor:disable', (vendorId) => { ... });

5.1.5 Framework-Integrationen

React:

import { ConsentProvider, useConsent, ConsentBanner } from '@breakpilot/consent-sdk/react';

function App() {
  return (
    <ConsentProvider config={config}>
      <ConsentBanner />
      <MainContent />
    </ConsentProvider>
  );
}

function AnalyticsComponent() {
  const { hasConsent, isLoading } = useConsent('analytics');

  if (isLoading) return <Skeleton />;
  if (!hasConsent) return <ConsentPlaceholder category="analytics" />;

  return <GoogleAnalytics />;
}

Vue 3:

<template>
  <ConsentBanner />
  <AnalyticsComponent v-if="hasConsent('analytics')" />
  <ConsentPlaceholder v-else category="analytics" />
</template>

<script setup>
import { useConsent, ConsentBanner, ConsentPlaceholder } from '@breakpilot/consent-sdk/vue';

const { hasConsent } = useConsent();
</script>

Angular:

import { ConsentModule } from '@breakpilot/consent-sdk/angular';

@NgModule({
  imports: [
    ConsentModule.forRoot(config),
  ],
})
export class AppModule {}

// In Component:
@Component({...})
export class MyComponent {
  constructor(private consent: ConsentService) {}

  get hasAnalytics(): boolean {
    return this.consent.hasConsent('analytics');
  }
}

5.2 PWA-spezifische Features

5.2.1 Offline-Support

const pwaConfig: ConsentConfig = {
  ...baseConfig,
  pwa: {
    offlineSupport: true,
    syncOnReconnect: true,
    cacheStrategy: 'stale-while-revalidate',
  },
};

// Service Worker Integration
// consent-sw.js wird automatisch registriert

5.2.2 App-Banner Integration

// Consent vor PWA-Install-Banner abfragen
consent.on('beforeInstallPrompt', (event) => {
  if (!consent.hasConsent('functional')) {
    event.preventDefault();
    consent.showBanner({
      message: 'Für die App-Installation benötigen wir Ihre Einwilligung.',
      highlightCategory: 'functional',
    });
  }
});

5.3 iOS SDK (Swift)

5.3.1 Installation

// Swift Package Manager
dependencies: [
    .package(url: "https://github.com/breakpilot/consent-sdk-ios", from: "1.0.0")
]

// CocoaPods
pod 'BreakPilotConsent', '~> 1.0'

5.3.2 Konfiguration

import BreakPilotConsent

let config = ConsentConfig(
    apiEndpoint: "https://consent.example.com/api/v1",
    siteId: "site_abc123",
    language: .german,
    categories: [.essential, .functional, .analytics, .marketing]
)

// AppDelegate oder SceneDelegate
ConsentManager.shared.configure(with: config)

5.3.3 SwiftUI Integration

import SwiftUI
import BreakPilotConsent

struct ContentView: View {
    @StateObject private var consent = ConsentManager.shared

    var body: some View {
        VStack {
            if consent.needsConsent {
                ConsentBannerView()
            }

            MainContent()
        }
        .consentGate(category: .analytics) {
            AnalyticsView()
        } placeholder: {
            ConsentPlaceholder(category: .analytics)
        }
    }
}

5.3.4 UIKit Integration

import BreakPilotConsent

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if ConsentManager.shared.needsConsent {
            let bannerVC = ConsentBannerViewController()
            bannerVC.modalPresentationStyle = .overFullScreen
            present(bannerVC, animated: true)
        }
    }

    func loadAnalytics() {
        guard ConsentManager.shared.hasConsent(.analytics) else {
            showConsentRequired(for: .analytics)
            return
        }
        // Analytics laden
    }
}

5.3.5 App Tracking Transparency (ATT) Integration

import AppTrackingTransparency

// Consent-SDK koordiniert mit ATT
ConsentManager.shared.configure(with: config) { manager in
    // Nach Consent-Banner ATT-Dialog anzeigen
    if manager.hasConsent(.marketing) {
        ATTrackingManager.requestTrackingAuthorization { status in
            switch status {
            case .authorized:
                manager.updateATTStatus(.authorized)
            case .denied, .restricted:
                manager.revokeConsent(.marketing)
            case .notDetermined:
                break
            @unknown default:
                break
            }
        }
    }
}

5.4 Android SDK (Kotlin)

5.4.1 Installation

// build.gradle.kts
dependencies {
    implementation("eu.breakpilot:consent-sdk:1.0.0")
}

5.4.2 Konfiguration

import eu.breakpilot.consent.ConsentManager
import eu.breakpilot.consent.ConsentConfig

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        val config = ConsentConfig.Builder()
            .apiEndpoint("https://consent.example.com/api/v1")
            .siteId("site_abc123")
            .language(Language.GERMAN)
            .categories(
                Category.ESSENTIAL,
                Category.FUNCTIONAL,
                Category.ANALYTICS,
                Category.MARKETING
            )
            .build()

        ConsentManager.initialize(this, config)
    }
}

5.4.3 Jetpack Compose Integration

import eu.breakpilot.consent.compose.*

@Composable
fun MainScreen() {
    val consent = rememberConsentState()

    if (consent.needsConsent) {
        ConsentBanner(
            onAcceptAll = { consent.acceptAll() },
            onRejectAll = { consent.rejectAll() },
            onCustomize = { /* Öffne Einstellungen */ }
        )
    }

    ConsentGate(
        category = Category.ANALYTICS,
        placeholder = { ConsentPlaceholder(Category.ANALYTICS) }
    ) {
        AnalyticsContent()
    }
}

5.4.4 XML Views Integration

class MainActivity : AppCompatActivity() {
    private val consent = ConsentManager.instance

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        consent.observe(this) { state ->
            when {
                state.needsConsent -> showConsentBanner()
                state.hasConsent(Category.ANALYTICS) -> loadAnalytics()
            }
        }
    }

    private fun showConsentBanner() {
        ConsentBannerFragment.show(supportFragmentManager)
    }
}

5.5 Flutter SDK

import 'package:breakpilot_consent/breakpilot_consent.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await ConsentManager.initialize(
    config: ConsentConfig(
      apiEndpoint: 'https://consent.example.com/api/v1',
      siteId: 'site_abc123',
      language: Language.german,
      categories: [
        Category.essential,
        Category.functional,
        Category.analytics,
        Category.marketing,
      ],
    ),
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ConsentProvider(
      child: MaterialApp(
        home: ConsentAwareHome(),
      ),
    );
  }
}

class ConsentAwareHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ConsentBuilder(
      builder: (context, consent) {
        if (consent.needsConsent) {
          return ConsentBanner();
        }

        return Scaffold(
          body: Column(
            children: [
              ConsentGate(
                category: Category.analytics,
                child: AnalyticsWidget(),
                placeholder: ConsentPlaceholder(category: Category.analytics),
              ),
            ],
          ),
        );
      },
    );
  }
}

5.6 React Native SDK

import {
  ConsentProvider,
  useConsent,
  ConsentBanner,
  ConsentGate,
} from '@breakpilot/consent-sdk-react-native';

const config = {
  apiEndpoint: 'https://consent.example.com/api/v1',
  siteId: 'site_abc123',
  language: 'de',
  categories: ['essential', 'functional', 'analytics', 'marketing'],
};

function App() {
  return (
    <ConsentProvider config={config}>
      <NavigationContainer>
        <MainStack />
      </NavigationContainer>
      <ConsentBanner />
    </ConsentProvider>
  );
}

function AnalyticsScreen() {
  const { hasConsent } = useConsent();

  if (!hasConsent('analytics')) {
    return <ConsentRequired category="analytics" />;
  }

  return <AnalyticsContent />;
}

6. API-Spezifikation

6.1 Base URL

Production: https://consent.breakpilot.eu/api/v1
Staging:    https://consent-staging.breakpilot.eu/api/v1

6.2 Authentifizierung

# API-Key für Server-to-Server
Authorization: Bearer <api_key>

# HMAC für Client-SDKs (verhindert Manipulation)
X-Consent-Signature: sha256=<hmac_signature>
X-Consent-Timestamp: 1707000000

6.3 Endpoints

POST /consent
Content-Type: application/json

{
  "siteId": "site_abc123",
  "userId": "user_xyz789",           // Optional: Für eingeloggte Nutzer
  "deviceFingerprint": "fp_...",     // Anonymisierter Fingerprint
  "consent": {
    "categories": {
      "essential": true,
      "functional": true,
      "analytics": false,
      "marketing": false,
      "social": false
    },
    "vendors": {
      "google-analytics": false,
      "facebook-pixel": false
    }
  },
  "metadata": {
    "userAgent": "Mozilla/5.0...",
    "language": "de-DE",
    "screenResolution": "1920x1080",
    "platform": "web",
    "appVersion": "1.0.0"
  }
}

Response 201:
{
  "consentId": "cns_abc123def456",
  "timestamp": "2026-02-04T12:00:00Z",
  "expiresAt": "2027-02-04T12:00:00Z",
  "version": "1.0.0"
}
GET /consent?siteId=site_abc123&deviceFingerprint=fp_...

Response 200:
{
  "consentId": "cns_abc123def456",
  "consent": {
    "categories": {
      "essential": true,
      "functional": true,
      "analytics": false,
      "marketing": false,
      "social": false
    },
    "vendors": {}
  },
  "createdAt": "2026-02-04T12:00:00Z",
  "updatedAt": "2026-02-04T12:00:00Z",
  "expiresAt": "2027-02-04T12:00:00Z",
  "version": "1.0.0"
}

Response 404:
{
  "error": "consent_not_found",
  "message": "No consent record found"
}
DELETE /consent/{consentId}

Response 200:
{
  "status": "revoked",
  "revokedAt": "2026-02-04T13:00:00Z"
}
GET /consent/export?userId=user_xyz789

Response 200:
{
  "userId": "user_xyz789",
  "exportedAt": "2026-02-04T12:00:00Z",
  "consents": [
    {
      "consentId": "cns_abc123",
      "siteId": "site_abc123",
      "consent": { ... },
      "createdAt": "2026-01-01T12:00:00Z",
      "revokedAt": null
    },
    {
      "consentId": "cns_def456",
      "siteId": "site_abc123",
      "consent": { ... },
      "createdAt": "2025-06-01T12:00:00Z",
      "revokedAt": "2026-01-01T11:59:00Z"
    }
  ]
}

6.3.5 Site-Konfiguration abrufen

GET /config/{siteId}

Response 200:
{
  "siteId": "site_abc123",
  "siteName": "Example Website",
  "categories": [
    {
      "id": "essential",
      "name": { "de": "Essentiell", "en": "Essential" },
      "description": { "de": "...", "en": "..." },
      "required": true,
      "vendors": []
    },
    {
      "id": "analytics",
      "name": { "de": "Statistik", "en": "Analytics" },
      "description": { "de": "...", "en": "..." },
      "required": false,
      "vendors": [
        {
          "id": "google-analytics",
          "name": "Google Analytics",
          "privacyPolicyUrl": "https://policies.google.com/privacy",
          "cookies": [
            {
              "name": "_ga",
              "expiration": "2 Jahre",
              "description": "Unterscheidet Nutzer"
            }
          ]
        }
      ]
    }
  ],
  "ui": {
    "theme": "light",
    "position": "bottom",
    "customCss": "..."
  },
  "legal": {
    "privacyPolicyUrl": "https://example.com/datenschutz",
    "imprintUrl": "https://example.com/impressum",
    "dpo": {
      "name": "Max Mustermann",
      "email": "datenschutz@example.com"
    }
  },
  "tcf": {
    "enabled": true,
    "cmpId": 123,
    "cmpVersion": 1
  }
}
GET /admin/stats/{siteId}
Authorization: Bearer <admin_api_key>

Response 200:
{
  "siteId": "site_abc123",
  "period": {
    "from": "2026-01-01",
    "to": "2026-02-04"
  },
  "totalBannerViews": 150000,
  "totalInteractions": 120000,
  "interactionRate": 0.80,
  "consentByCategory": {
    "essential": { "accepted": 120000, "rate": 1.0 },
    "functional": { "accepted": 95000, "rate": 0.79 },
    "analytics": { "accepted": 45000, "rate": 0.38 },
    "marketing": { "accepted": 25000, "rate": 0.21 },
    "social": { "accepted": 30000, "rate": 0.25 }
  },
  "actions": {
    "acceptAll": 35000,
    "rejectAll": 40000,
    "customize": 45000
  },
  "avgTimeToDecision": "4.2s",
  "bounceAfterBanner": 0.05
}

6.4 Webhooks

POST https://your-server.com/webhooks/consent

{
  "event": "consent.updated",
  "timestamp": "2026-02-04T12:00:00Z",
  "data": {
    "consentId": "cns_abc123",
    "siteId": "site_abc123",
    "userId": "user_xyz789",
    "changes": {
      "analytics": { "from": true, "to": false },
      "marketing": { "from": false, "to": false }
    }
  }
}

// Event-Typen:
// - consent.created
// - consent.updated
// - consent.revoked
// - consent.expired

7. UI/UX-Anforderungen

7.1 Design-Prinzipien

  1. Gleichwertigkeit: "Ablehnen" und "Akzeptieren" gleich prominent
  2. Transparenz: Alle Informationen auf einen Blick
  3. Barrierefreiheit: WCAG 2.1 AA konform
  4. Mobile-First: Responsive Design
  5. Keine Dark Patterns: Keine manipulativen Design-Elemente

7.2 Banner-Layouts

7.2.1 Bottom Bar (Standard)

┌─────────────────────────────────────────────────────────────────────────┐
│  🍪 Diese Website verwendet Cookies                                     │
│                                                                         │
│  Wir nutzen Cookies und ähnliche Technologien, um Ihnen ein            │
│  optimales Nutzererlebnis zu bieten. [Mehr erfahren]                   │
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐          │
│  │ Alle ablehnen│  │  Einstellungen │  │ Alle akzeptieren │          │
│  └──────────────┘  └──────────────┘  └──────────────────────┘          │
└─────────────────────────────────────────────────────────────────────────┘

7.2.2 Modal (DSGVO-empfohlen)

┌─────────────────────────────────────────────────────────────────────────┐
│                                                                    [X]  │
│                    🍪 Datenschutzeinstellungen                          │
│                                                                         │
│  ───────────────────────────────────────────────────────────────────── │
│                                                                         │
│  Wir respektieren Ihre Privatsphäre. Bitte wählen Sie, welche          │
│  Cookies Sie akzeptieren möchten.                                      │
│                                                                         │
│  ☑ Essentiell (immer aktiv)                                       ⓘ   │
│    Notwendig für die Grundfunktionen der Website.                      │
│                                                                         │
│  ☐ Funktional                                                      ⓘ   │
│    Personalisierung und Komfortfunktionen.                             │
│                                                                         │
│  ☐ Statistik                                                       ⓘ   │
│    Hilft uns, die Website zu verbessern.                               │
│                                                                         │
│  ☐ Marketing                                                       ⓘ   │
│    Personalisierte Werbung.                                            │
│                                                                         │
│  ☐ Soziale Medien                                                  ⓘ   │
│    Inhalte von sozialen Netzwerken.                                    │
│                                                                         │
│  ───────────────────────────────────────────────────────────────────── │
│                                                                         │
│  [Datenschutzerklärung]  [Impressum]  [Cookie-Details]                 │
│                                                                         │
│  ┌──────────────────┐          ┌──────────────────────────┐            │
│  │  Auswahl speichern │          │  Alle akzeptieren  │            │
│  └──────────────────┘          └──────────────────────────┘            │
│                                                                         │
│  ┌──────────────────────────────────────────────────────────┐          │
│  │                    Alle ablehnen                          │          │
│  └──────────────────────────────────────────────────────────┘          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

7.3 Farbschema

// Light Theme
$consent-bg: #ffffff;
$consent-text: #1a1a1a;
$consent-secondary: #666666;
$consent-border: #e0e0e0;

$button-accept-bg: #2563eb;        // Blau (neutral, nicht grün)
$button-accept-text: #ffffff;

$button-reject-bg: #ffffff;        // Gleiche Prominenz!
$button-reject-text: #1a1a1a;
$button-reject-border: #2563eb;

$button-settings-bg: #f3f4f6;
$button-settings-text: #1a1a1a;

// Dark Theme
$consent-bg-dark: #1f2937;
$consent-text-dark: #f9fafb;
// ...

7.4 Barrierefreiheit (WCAG 2.1 AA)

Anforderung Umsetzung
Kontrast Mindestens 4.5:1 für Text
Fokus Sichtbare Fokus-Indikatoren
Tastatur Vollständig per Tastatur bedienbar
Screen Reader ARIA-Labels für alle Elemente
Zoom Funktioniert bei 200% Zoom
Motion Respektiert prefers-reduced-motion
<!-- Beispiel: Barrierefreier Button -->
<button
  role="button"
  aria-label="Alle Cookies akzeptieren"
  aria-describedby="consent-description"
  tabindex="0"
  class="consent-accept-btn"
>
  Alle akzeptieren
</button>

7.5 Animationen

/* Respektiert Nutzereinstellung */
@media (prefers-reduced-motion: reduce) {
  .consent-banner {
    animation: none;
    transition: none;
  }
}

/* Dezente Einblendung */
@media (prefers-reduced-motion: no-preference) {
  .consent-banner {
    animation: slideUp 0.3s ease-out;
  }

  @keyframes slideUp {
    from {
      transform: translateY(100%);
      opacity: 0;
    }
    to {
      transform: translateY(0);
      opacity: 1;
    }
  }
}

7.6 Mehrsprachigkeit

const translations = {
  de: {
    title: 'Datenschutzeinstellungen',
    description: 'Wir nutzen Cookies und ähnliche Technologien...',
    acceptAll: 'Alle akzeptieren',
    rejectAll: 'Alle ablehnen',
    settings: 'Einstellungen',
    saveSelection: 'Auswahl speichern',
    categories: {
      essential: {
        name: 'Essentiell',
        description: 'Notwendig für die Grundfunktionen.',
      },
      analytics: {
        name: 'Statistik',
        description: 'Hilft uns, die Website zu verbessern.',
      },
      // ...
    },
    footer: {
      privacyPolicy: 'Datenschutzerklärung',
      imprint: 'Impressum',
      cookieDetails: 'Cookie-Details',
    },
  },
  en: {
    title: 'Privacy Settings',
    // ...
  },
  fr: { ... },
  es: { ... },
  it: { ... },
  nl: { ... },
  pl: { ... },
  // Alle EU-Sprachen
};

8. Plattform-Integrationen

8.1 Google Tag Manager

// GTM-Template für Consent Mode v2
consent.on('change', (consentState) => {
  gtag('consent', 'update', {
    'ad_storage': consentState.marketing ? 'granted' : 'denied',
    'ad_user_data': consentState.marketing ? 'granted' : 'denied',
    'ad_personalization': consentState.marketing ? 'granted' : 'denied',
    'analytics_storage': consentState.analytics ? 'granted' : 'denied',
    'functionality_storage': consentState.functional ? 'granted' : 'denied',
    'personalization_storage': consentState.functional ? 'granted' : 'denied',
    'security_storage': 'granted', // Immer erlaubt
  });
});

8.2 Meta (Facebook) Pixel

consent.on('change', (consentState) => {
  if (typeof fbq !== 'undefined') {
    if (consentState.marketing) {
      fbq('consent', 'grant');
    } else {
      fbq('consent', 'revoke');
    }
  }
});

8.3 Google Analytics 4

// GA4 mit Consent Mode
consent.on('change', (consentState) => {
  gtag('consent', 'update', {
    'analytics_storage': consentState.analytics ? 'granted' : 'denied',
  });
});

8.4 IAB TCF 2.2

// TCF API Integration
window.__tcfapi = window.__tcfapi || function() {
  (window.__tcfapi.a = window.__tcfapi.a || []).push(arguments);
};

consent.on('change', (consentState, tcfString) => {
  // TC String an CMP-API übergeben
  __tcfapi('setConsentInfo', 2, (success) => {
    if (success) {
      console.log('TCF Consent updated');
    }
  }, { tcString: tcfString });
});

8.5 WordPress Plugin

<?php
/**
 * Plugin Name: BreakPilot Consent
 * Description: DSGVO-konformes Cookie-Banner
 * Version: 1.0.0
 * License: Apache-2.0
 */

function breakpilot_consent_enqueue() {
    wp_enqueue_script(
        'breakpilot-consent',
        'https://cdn.breakpilot.eu/consent-sdk/v1/consent.min.js',
        [],
        '1.0.0',
        true
    );

    wp_add_inline_script('breakpilot-consent', '
        new ConsentManager({
            apiEndpoint: "' . esc_js(get_option('breakpilot_api_endpoint')) . '",
            siteId: "' . esc_js(get_option('breakpilot_site_id')) . '",
            language: "' . esc_js(get_locale()) . '"
        }).init();
    ');
}
add_action('wp_enqueue_scripts', 'breakpilot_consent_enqueue');

9. Datenspeicherung & Audit

9.1 Datenbank-Schema

-- Consent-Einträge
CREATE TABLE consent_records (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    site_id VARCHAR(50) NOT NULL,
    user_id VARCHAR(100),                    -- Optional
    device_fingerprint VARCHAR(64) NOT NULL, -- SHA-256 Hash

    -- Consent-Daten
    categories JSONB NOT NULL,               -- { "analytics": true, ... }
    vendors JSONB DEFAULT '{}',              -- { "google-analytics": true }
    tcf_string TEXT,                         -- IAB TCF String

    -- Metadaten
    ip_hash VARCHAR(64),                     -- Anonymisiert
    user_agent TEXT,
    language VARCHAR(10),
    platform VARCHAR(20),                    -- web, ios, android
    app_version VARCHAR(20),

    -- Zeitstempel
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    expires_at TIMESTAMPTZ,
    revoked_at TIMESTAMPTZ,

    -- Versionierung
    version VARCHAR(20) DEFAULT '1.0.0',

    -- Indizes
    CONSTRAINT fk_site FOREIGN KEY (site_id) REFERENCES sites(id)
);

CREATE INDEX idx_consent_site ON consent_records(site_id);
CREATE INDEX idx_consent_user ON consent_records(user_id) WHERE user_id IS NOT NULL;
CREATE INDEX idx_consent_device ON consent_records(device_fingerprint);
CREATE INDEX idx_consent_created ON consent_records(created_at);

-- Audit-Log (unveränderbar)
CREATE TABLE consent_audit_log (
    id BIGSERIAL PRIMARY KEY,
    consent_id UUID REFERENCES consent_records(id),
    action VARCHAR(20) NOT NULL,             -- created, updated, revoked
    previous_state JSONB,
    new_state JSONB,
    ip_hash VARCHAR(64),
    user_agent TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Kein UPDATE/DELETE auf Audit-Log
REVOKE UPDATE, DELETE ON consent_audit_log FROM PUBLIC;

9.2 Datenaufbewahrung

Datentyp Aufbewahrung Begründung
Consent-Record 3 Jahre Nachweis der Einwilligung (Art. 7 Abs. 1 DSGVO)
Audit-Log 6 Jahre Steuerrechtliche Aufbewahrungspflicht
Statistiken Unbegrenzt Anonymisiert, kein Personenbezug
Abgelaufene Consents 30 Tage Grace Period für Sync-Konflikte

9.3 Löschkonzept

// Automatische Bereinigung
func (s *ConsentService) CleanupExpiredRecords(ctx context.Context) error {
    // Soft-Delete für normale Records
    _, err := s.db.ExecContext(ctx, `
        UPDATE consent_records
        SET deleted_at = NOW()
        WHERE expires_at < NOW() - INTERVAL '30 days'
        AND deleted_at IS NULL
    `)
    if err != nil {
        return err
    }

    // Hard-Delete nach 3 Jahren
    _, err = s.db.ExecContext(ctx, `
        DELETE FROM consent_records
        WHERE deleted_at < NOW() - INTERVAL '3 years'
    `)
    return err
}

9.4 Audit-Trail

Jede Consent-Änderung wird protokolliert:

type AuditEntry struct {
    ConsentID     uuid.UUID `json:"consent_id"`
    Action        string    `json:"action"`        // created, updated, revoked
    PreviousState *Consent  `json:"previous_state"`
    NewState      *Consent  `json:"new_state"`
    IPHash        string    `json:"ip_hash"`
    UserAgent     string    `json:"user_agent"`
    Timestamp     time.Time `json:"timestamp"`
}

func (s *ConsentService) logAudit(ctx context.Context, entry AuditEntry) error {
    _, err := s.db.ExecContext(ctx, `
        INSERT INTO consent_audit_log
        (consent_id, action, previous_state, new_state, ip_hash, user_agent)
        VALUES ($1, $2, $3, $4, $5, $6)
    `, entry.ConsentID, entry.Action,
       entry.PreviousState, entry.NewState,
       entry.IPHash, entry.UserAgent)
    return err
}

10. Sicherheit & Privacy

10.1 Datenschutz by Design

Prinzip Umsetzung
Datenminimierung Nur notwendige Daten speichern
Pseudonymisierung Device-Fingerprint statt direkter Identifikation
Zweckbindung Daten nur für Consent-Nachweis verwenden
Transparenz Alle Datenverarbeitung dokumentiert

10.2 Device Fingerprinting

// Datenschutzkonformes Fingerprinting
function generateFingerprint(): string {
    const components = [
        navigator.userAgent,
        navigator.language,
        screen.colorDepth.toString(),
        new Date().getTimezoneOffset().toString(),
        // KEINE Canvas-Fingerprints oder Hardware-IDs
    ];

    // SHA-256 Hash für Anonymisierung
    return sha256(components.join('|'));
}

10.3 IP-Anonymisierung

func anonymizeIP(ip string) string {
    parsed := net.ParseIP(ip)
    if parsed == nil {
        return ""
    }

    if parsed.To4() != nil {
        // IPv4: Letzte 8 Bit auf 0
        // 192.168.1.123 -> 192.168.1.0
        parsed[15] = 0
    } else {
        // IPv6: Letzte 80 Bit auf 0
        for i := 6; i < 16; i++ {
            parsed[i] = 0
        }
    }

    // Hash für zusätzliche Sicherheit
    return sha256(parsed.String())
}

10.4 Verschlüsselung

Daten Verschlüsselung
In Transit TLS 1.3
At Rest AES-256-GCM
Consent-Cookie HMAC-SHA256 signiert
API-Keys bcrypt (Faktor 12)

10.5 Rate Limiting

// Pro IP-Adresse
var limiter = rate.NewLimiter(
    rate.Every(time.Second), // 1 Request/Sekunde
    10,                       // Burst von 10
)

// Pro Site
var siteLimiter = rate.NewLimiter(
    rate.Every(time.Millisecond * 100), // 10 Requests/Sekunde
    100,                                  // Burst von 100
)

10.6 CORS-Konfiguration

func corsMiddleware() gin.HandlerFunc {
    return cors.New(cors.Config{
        AllowOrigins:     []string{"https://*.example.com"},
        AllowMethods:     []string{"GET", "POST", "DELETE"},
        AllowHeaders:     []string{"Content-Type", "X-Consent-Signature"},
        AllowCredentials: true,
        MaxAge:           12 * time.Hour,
    })
}

11. Implementierungs-Roadmap

Phase 1: Core SDK (8 Wochen)

Woche Aufgabe
1-2 Web SDK Basis (TypeScript)
3-4 Backend API (Go)
5-6 React/Vue Integration
7-8 Testing & Dokumentation

Deliverables:

  • Web SDK v1.0.0
  • REST API v1.0.0
  • React/Vue Wrapper
  • Dokumentation

Phase 2: Mobile SDKs (6 Wochen)

Woche Aufgabe
1-2 iOS SDK (Swift)
3-4 Android SDK (Kotlin)
5-6 Testing & Dokumentation

Deliverables:

  • iOS SDK v1.0.0
  • Android SDK v1.0.0
  • Beispiel-Apps

Phase 3: Cross-Platform (4 Wochen)

Woche Aufgabe
1-2 Flutter SDK
3-4 React Native SDK

Deliverables:

  • Flutter SDK v1.0.0
  • React Native SDK v1.0.0

Phase 4: Enterprise Features (4 Wochen)

Woche Aufgabe
1 TCF 2.2 Integration
2 A/B Testing
3 Analytics Dashboard
4 White-Label UI

Deliverables:

  • TCF 2.2 Unterstützung
  • Admin Dashboard
  • A/B Testing Engine

Phase 5: Integrationen (4 Wochen)

Woche Aufgabe
1 WordPress Plugin
2 Shopify App
3 GTM Template
4 Weitere CMS

12. Anhang

12.1 Glossar

Begriff Beschreibung
CMP Consent Management Platform
TCF IAB Transparency & Consent Framework
DSGVO Datenschutz-Grundverordnung (EU 2016/679)
TTDSG Telekommunikation-Telemedien-Datenschutz-Gesetz
DSK Datenschutzkonferenz (Deutschland)
PWA Progressive Web App
ATT App Tracking Transparency (Apple)

12.2 Referenzen

12.3 Lizenz

Copyright 2026 BreakPilot GmbH

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

12.4 Changelog

Version Datum Änderungen
1.0.0 2026-02-04 Initiale Spezifikation

Autor: BreakPilot Engineering Team Review: Datenschutzbeauftragter Freigabe: Pending