Initial commit: breakpilot-core - Shared Infrastructure

Docker Compose with 24+ services:
- PostgreSQL (PostGIS), Valkey, MinIO, Qdrant
- Vault (PKI/TLS), Nginx (Reverse Proxy)
- Backend Core API, Consent Service, Billing Service
- RAG Service, Embedding Service
- Gitea, Woodpecker CI/CD
- Night Scheduler, Health Aggregator
- Jitsi (Web/XMPP/JVB/Jicofo), Mailpit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-11 23:47:13 +01:00
commit ad111d5e69
244 changed files with 84288 additions and 0 deletions

707
docs-src/consent-sdk/dist/index.d.mts vendored Normal file
View File

@@ -0,0 +1,707 @@
/**
* Consent SDK Types
*
* DSGVO/TTDSG-konforme Typdefinitionen für das Consent Management System.
*/
/**
* Standard-Consent-Kategorien nach IAB TCF 2.2
*/
type ConsentCategory = 'essential' | 'functional' | 'analytics' | 'marketing' | 'social';
/**
* Consent-Status pro Kategorie
*/
type ConsentCategories = Record<ConsentCategory, boolean>;
/**
* Consent-Status pro Vendor
*/
type ConsentVendors = Record<string, boolean>;
/**
* Aktueller Consent-Zustand
*/
interface ConsentState {
/** Consent pro Kategorie */
categories: ConsentCategories;
/** Consent pro Vendor (optional, für granulare Kontrolle) */
vendors: ConsentVendors;
/** Zeitstempel der letzten Aenderung */
timestamp: string;
/** SDK-Version bei Erstellung */
version: string;
/** Eindeutige Consent-ID vom Backend */
consentId?: string;
/** Ablaufdatum */
expiresAt?: string;
/** IAB TCF String (falls aktiviert) */
tcfString?: string;
}
/**
* Minimaler Consent-Input fuer setConsent()
*/
type ConsentInput = Partial<ConsentCategories> | {
categories?: Partial<ConsentCategories>;
vendors?: ConsentVendors;
};
/**
* UI-Position des Banners
*/
type BannerPosition = 'bottom' | 'top' | 'center';
/**
* Banner-Layout
*/
type BannerLayout = 'bar' | 'modal' | 'floating';
/**
* Farbschema
*/
type BannerTheme = 'light' | 'dark' | 'auto';
/**
* UI-Konfiguration
*/
interface ConsentUIConfig {
/** Position des Banners */
position?: BannerPosition;
/** Layout-Typ */
layout?: BannerLayout;
/** Farbschema */
theme?: BannerTheme;
/** Pfad zu Custom CSS */
customCss?: string;
/** z-index fuer Banner */
zIndex?: number;
/** Scroll blockieren bei Modal */
blockScrollOnModal?: boolean;
/** Custom Container-ID */
containerId?: string;
}
/**
* Consent-Verhaltens-Konfiguration
*/
interface ConsentBehaviorConfig {
/** Muss Nutzer interagieren? */
required?: boolean;
/** "Alle ablehnen" Button sichtbar */
rejectAllVisible?: boolean;
/** "Alle akzeptieren" Button sichtbar */
acceptAllVisible?: boolean;
/** Einzelne Kategorien waehlbar */
granularControl?: boolean;
/** Einzelne Vendors waehlbar */
vendorControl?: boolean;
/** Auswahl speichern */
rememberChoice?: boolean;
/** Speicherdauer in Tagen */
rememberDays?: number;
/** Nur in EU anzeigen (Geo-Targeting) */
geoTargeting?: boolean;
/** Erneut nachfragen nach X Tagen */
recheckAfterDays?: number;
}
/**
* TCF 2.2 Konfiguration
*/
interface TCFConfig {
/** TCF aktivieren */
enabled?: boolean;
/** CMP ID */
cmpId?: number;
/** CMP Version */
cmpVersion?: number;
}
/**
* PWA-spezifische Konfiguration
*/
interface PWAConfig {
/** Offline-Unterstuetzung aktivieren */
offlineSupport?: boolean;
/** Bei Reconnect synchronisieren */
syncOnReconnect?: boolean;
/** Cache-Strategie */
cacheStrategy?: 'stale-while-revalidate' | 'network-first' | 'cache-first';
}
/**
* Haupt-Konfiguration fuer ConsentManager
*/
interface ConsentConfig {
/** API-Endpunkt fuer Consent-Backend */
apiEndpoint: string;
/** Site-ID */
siteId: string;
/** Sprache (ISO 639-1) */
language?: string;
/** Fallback-Sprache */
fallbackLanguage?: string;
/** UI-Konfiguration */
ui?: ConsentUIConfig;
/** Consent-Verhaltens-Konfiguration */
consent?: ConsentBehaviorConfig;
/** Aktive Kategorien */
categories?: ConsentCategory[];
/** TCF 2.2 Konfiguration */
tcf?: TCFConfig;
/** PWA-Konfiguration */
pwa?: PWAConfig;
/** Callback bei Consent-Aenderung */
onConsentChange?: (consent: ConsentState) => void;
/** Callback wenn Banner angezeigt wird */
onBannerShow?: () => void;
/** Callback wenn Banner geschlossen wird */
onBannerHide?: () => void;
/** Callback bei Fehler */
onError?: (error: Error) => void;
/** Debug-Modus aktivieren */
debug?: boolean;
}
/**
* Cookie-Information
*/
interface CookieInfo {
/** Cookie-Name */
name: string;
/** Cookie-Domain */
domain: string;
/** Ablaufzeit (z.B. "2 Jahre", "Session") */
expiration: string;
/** Speichertyp */
type: 'http' | 'localStorage' | 'sessionStorage' | 'indexedDB';
/** Beschreibung */
description: string;
}
/**
* Vendor-Definition
*/
interface ConsentVendor {
/** Eindeutige Vendor-ID */
id: string;
/** Anzeigename */
name: string;
/** Kategorie */
category: ConsentCategory;
/** IAB TCF Purposes (falls relevant) */
purposes?: number[];
/** Legitimate Interests */
legitimateInterests?: number[];
/** Cookie-Liste */
cookies: CookieInfo[];
/** Link zur Datenschutzerklaerung */
privacyPolicyUrl: string;
/** Datenaufbewahrung */
dataRetention?: string;
/** Datentransfer (z.B. "USA (EU-US DPF)", "EU") */
dataTransfer?: string;
}
/**
* API-Antwort fuer Consent-Erstellung
*/
interface ConsentAPIResponse {
consentId: string;
timestamp: string;
expiresAt: string;
version: string;
}
/**
* API-Antwort fuer Site-Konfiguration
*/
interface SiteConfigResponse {
siteId: string;
siteName: string;
categories: CategoryConfig[];
ui: ConsentUIConfig;
legal: LegalConfig;
tcf?: TCFConfig;
}
/**
* Kategorie-Konfiguration vom Server
*/
interface CategoryConfig {
id: ConsentCategory;
name: Record<string, string>;
description: Record<string, string>;
required: boolean;
vendors: ConsentVendor[];
}
/**
* Rechtliche Konfiguration
*/
interface LegalConfig {
privacyPolicyUrl: string;
imprintUrl: string;
dpo?: {
name: string;
email: string;
};
}
/**
* Event-Typen
*/
type ConsentEventType = 'init' | 'change' | 'accept_all' | 'reject_all' | 'save_selection' | 'banner_show' | 'banner_hide' | 'settings_open' | 'settings_close' | 'vendor_enable' | 'vendor_disable' | 'error';
/**
* Event-Listener Callback
*/
type ConsentEventCallback<T = unknown> = (data: T) => void;
/**
* Event-Daten fuer verschiedene Events
*/
type ConsentEventData = {
init: ConsentState | null;
change: ConsentState;
accept_all: ConsentState;
reject_all: ConsentState;
save_selection: ConsentState;
banner_show: undefined;
banner_hide: undefined;
settings_open: undefined;
settings_close: undefined;
vendor_enable: string;
vendor_disable: string;
error: Error;
};
/**
* Storage-Adapter Interface
*/
interface ConsentStorageAdapter {
/** Consent laden */
get(): ConsentState | null;
/** Consent speichern */
set(consent: ConsentState): void;
/** Consent loeschen */
clear(): void;
/** Pruefen ob Consent existiert */
exists(): boolean;
}
/**
* Uebersetzungsstruktur
*/
interface ConsentTranslations {
title: string;
description: string;
acceptAll: string;
rejectAll: string;
settings: string;
saveSelection: string;
close: string;
categories: {
[K in ConsentCategory]: {
name: string;
description: string;
};
};
footer: {
privacyPolicy: string;
imprint: string;
cookieDetails: string;
};
accessibility: {
closeButton: string;
categoryToggle: string;
requiredCategory: string;
};
}
/**
* Alle unterstuetzten Sprachen
*/
type SupportedLanguage = 'de' | 'en' | 'fr' | 'es' | 'it' | 'nl' | 'pl' | 'pt' | 'cs' | 'da' | 'el' | 'fi' | 'hu' | 'ro' | 'sk' | 'sl' | 'sv';
/**
* ConsentManager - Hauptklasse fuer das Consent Management
*
* DSGVO/TTDSG-konformes Consent Management fuer Web, PWA und Mobile.
*/
/**
* ConsentManager - Zentrale Klasse fuer Consent-Verwaltung
*/
declare class ConsentManager {
private config;
private storage;
private scriptBlocker;
private api;
private events;
private currentConsent;
private initialized;
private bannerVisible;
private deviceFingerprint;
constructor(config: ConsentConfig);
/**
* SDK initialisieren
*/
init(): Promise<void>;
/**
* Pruefen ob Consent fuer Kategorie vorhanden
*/
hasConsent(category: ConsentCategory): boolean;
/**
* Pruefen ob Consent fuer Vendor vorhanden
*/
hasVendorConsent(vendorId: string): boolean;
/**
* Aktuellen Consent-State abrufen
*/
getConsent(): ConsentState | null;
/**
* Consent setzen
*/
setConsent(input: ConsentInput): Promise<void>;
/**
* Alle Kategorien akzeptieren
*/
acceptAll(): Promise<void>;
/**
* Alle nicht-essentiellen Kategorien ablehnen
*/
rejectAll(): Promise<void>;
/**
* Alle Einwilligungen widerrufen
*/
revokeAll(): Promise<void>;
/**
* Consent-Daten exportieren (DSGVO Art. 20)
*/
exportConsent(): Promise<string>;
/**
* Pruefen ob Consent-Abfrage noetig
*/
needsConsent(): boolean;
/**
* Banner anzeigen
*/
showBanner(): void;
/**
* Banner verstecken
*/
hideBanner(): void;
/**
* Einstellungs-Modal oeffnen
*/
showSettings(): void;
/**
* Pruefen ob Banner sichtbar
*/
isBannerVisible(): boolean;
/**
* Event-Listener registrieren
*/
on<T extends ConsentEventType>(event: T, callback: ConsentEventCallback<ConsentEventData[T]>): () => void;
/**
* Event-Listener entfernen
*/
off<T extends ConsentEventType>(event: T, callback: ConsentEventCallback<ConsentEventData[T]>): void;
/**
* Konfiguration zusammenfuehren
*/
private mergeConfig;
/**
* Consent-Input normalisieren
*/
private normalizeConsentInput;
/**
* Consent anwenden (Skripte aktivieren/blockieren)
*/
private applyConsent;
/**
* Google Consent Mode v2 aktualisieren
*/
private updateGoogleConsentMode;
/**
* Pruefen ob Consent abgelaufen
*/
private isConsentExpired;
/**
* Event emittieren
*/
private emit;
/**
* Fehler behandeln
*/
private handleError;
/**
* Debug-Logging
*/
private log;
/**
* SDK-Version abrufen
*/
static getVersion(): string;
}
/**
* ConsentStorage - Lokale Speicherung des Consent-Status
*
* Speichert Consent-Daten im localStorage mit HMAC-Signatur
* zur Manipulationserkennung.
*/
/**
* ConsentStorage - Persistente Speicherung
*/
declare class ConsentStorage {
private config;
private storageKey;
constructor(config: ConsentConfig);
/**
* Consent laden
*/
get(): ConsentState | null;
/**
* Consent speichern
*/
set(consent: ConsentState): void;
/**
* Consent loeschen
*/
clear(): void;
/**
* Pruefen ob Consent existiert
*/
exists(): boolean;
/**
* Consent als Cookie setzen
*/
private setCookie;
/**
* Cookie loeschen
*/
private clearCookie;
/**
* Signatur generieren
*/
private generateSignature;
/**
* Signatur verifizieren
*/
private verifySignature;
/**
* Einfache Hash-Funktion (djb2)
*/
private simpleHash;
/**
* Debug-Logging
*/
private log;
}
/**
* ScriptBlocker - Blockiert Skripte bis Consent erteilt wird
*
* Verwendet das data-consent Attribut zur Identifikation von
* Skripten, die erst nach Consent geladen werden duerfen.
*
* Beispiel:
* <script data-consent="analytics" data-src="..." type="text/plain"></script>
*/
/**
* ScriptBlocker - Verwaltet Script-Blocking
*/
declare class ScriptBlocker {
private config;
private observer;
private enabledCategories;
private processedElements;
constructor(config: ConsentConfig);
/**
* Initialisieren und Observer starten
*/
init(): void;
/**
* Kategorie aktivieren
*/
enableCategory(category: ConsentCategory): void;
/**
* Kategorie deaktivieren
*/
disableCategory(category: ConsentCategory): void;
/**
* Alle Kategorien blockieren (ausser Essential)
*/
blockAll(): void;
/**
* Pruefen ob Kategorie aktiviert
*/
isCategoryEnabled(category: ConsentCategory): boolean;
/**
* Observer stoppen
*/
destroy(): void;
/**
* Bestehende Elemente verarbeiten
*/
private processExistingElements;
/**
* Element verarbeiten
*/
private processElement;
/**
* Script-Element verarbeiten
*/
private processScript;
/**
* iFrame-Element verarbeiten
*/
private processIframe;
/**
* Script aktivieren
*/
private activateScript;
/**
* iFrame aktivieren
*/
private activateIframe;
/**
* Placeholder fuer blockierten iFrame anzeigen
*/
private showPlaceholder;
/**
* Alle Elemente einer Kategorie aktivieren
*/
private activateCategory;
/**
* Kategorie-Name fuer UI
*/
private getCategoryName;
/**
* Debug-Logging
*/
private log;
}
/**
* ConsentAPI - Kommunikation mit dem Consent-Backend
*
* Sendet Consent-Entscheidungen an das Backend zur
* revisionssicheren Speicherung.
*/
/**
* Request-Payload fuer Consent-Speicherung
*/
interface SaveConsentRequest {
siteId: string;
userId?: string;
deviceFingerprint: string;
consent: ConsentState;
metadata?: {
userAgent?: string;
language?: string;
screenResolution?: string;
platform?: string;
appVersion?: string;
};
}
/**
* ConsentAPI - Backend-Kommunikation
*/
declare class ConsentAPI {
private config;
private baseUrl;
constructor(config: ConsentConfig);
/**
* Consent speichern
*/
saveConsent(request: SaveConsentRequest): Promise<ConsentAPIResponse>;
/**
* Consent abrufen
*/
getConsent(siteId: string, deviceFingerprint: string): Promise<ConsentState | null>;
/**
* Consent widerrufen
*/
revokeConsent(consentId: string): Promise<void>;
/**
* Site-Konfiguration abrufen
*/
getSiteConfig(siteId: string): Promise<SiteConfigResponse>;
/**
* Consent-Historie exportieren (DSGVO Art. 20)
*/
exportConsent(userId: string): Promise<unknown>;
/**
* Fetch mit Standard-Headers
*/
private fetch;
/**
* Signatur-Headers generieren (HMAC)
*/
private getSignatureHeaders;
/**
* Einfache Hash-Funktion (djb2)
*/
private simpleHash;
/**
* Debug-Logging
*/
private log;
}
/**
* EventEmitter - Typsicherer Event-Handler
*/
type EventCallback<T = unknown> = (data: T) => void;
declare class EventEmitter<Events extends Record<string, any> = Record<string, unknown>> {
private listeners;
/**
* Event-Listener registrieren
* @returns Unsubscribe-Funktion
*/
on<K extends keyof Events>(event: K, callback: EventCallback<Events[K]>): () => void;
/**
* Event-Listener entfernen
*/
off<K extends keyof Events>(event: K, callback: EventCallback<Events[K]>): void;
/**
* Event emittieren
*/
emit<K extends keyof Events>(event: K, data: Events[K]): void;
/**
* Einmaligen Listener registrieren
*/
once<K extends keyof Events>(event: K, callback: EventCallback<Events[K]>): () => void;
/**
* Alle Listener entfernen
*/
clear(): void;
/**
* Alle Listener fuer ein Event entfernen
*/
clearEvent<K extends keyof Events>(event: K): void;
/**
* Anzahl Listener fuer ein Event
*/
listenerCount<K extends keyof Events>(event: K): number;
}
/**
* Device Fingerprinting - Datenschutzkonform
*
* Generiert einen anonymen Fingerprint OHNE:
* - Canvas Fingerprinting
* - WebGL Fingerprinting
* - Audio Fingerprinting
* - Hardware-spezifische IDs
*
* Verwendet nur:
* - User Agent
* - Sprache
* - Bildschirmaufloesung
* - Zeitzone
* - Platform
*/
/**
* Datenschutzkonformen Fingerprint generieren
*
* Der Fingerprint ist:
* - Nicht eindeutig (viele Nutzer teilen sich denselben)
* - Nicht persistent (aendert sich bei Browser-Updates)
* - Nicht invasiv (keine Canvas/WebGL/Audio)
* - Anonymisiert (SHA-256 Hash)
*/
declare function generateFingerprint(): Promise<string>;
/**
* Synchrone Version (mit einfachem Hash)
*/
declare function generateFingerprintSync(): string;
/**
* SDK Version
*/
declare const SDK_VERSION = "1.0.0";
export { type BannerLayout, type BannerPosition, type BannerTheme, type CategoryConfig, ConsentAPI, type ConsentAPIResponse, type ConsentBehaviorConfig, type ConsentCategories, type ConsentCategory, type ConsentConfig, type ConsentEventCallback, type ConsentEventData, type ConsentEventType, type ConsentInput, ConsentManager, type ConsentState, ConsentStorage, type ConsentStorageAdapter, type ConsentTranslations, type ConsentUIConfig, type ConsentVendor, type ConsentVendors, type CookieInfo, EventEmitter, type LegalConfig, type PWAConfig, SDK_VERSION, ScriptBlocker, type SiteConfigResponse, type SupportedLanguage, type TCFConfig, ConsentManager as default, generateFingerprint, generateFingerprintSync };