feat: enhance whistleblower HinSchG content, fix control-library filter layout
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 34s
CI/CD / test-python-backend-compliance (push) Successful in 35s
CI/CD / test-python-document-crawler (push) Successful in 26s
CI/CD / test-python-dsms-gateway (push) Successful in 21s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s

- Whistleblower page: expand overview tab with comprehensive HinSchG legal info
  (Gesetzliche Grundlage, Fristen-Cards, Anwendungsbereich, Schutz des Hinweisgebers)
- StepHeader: enrich whistleblower tips with detailed HinSchG paragraphs and sanctions
- Wiki: add migration 054 with 5 new/updated HinSchG articles (Anwendungsbereich,
  Hinweisgeberschutz, Meldestellen, Verfahrensablauf, Datenschutz-Anforderungen)
- MKDocs: rewrite whistleblower docs with full legal basis, architecture, API, DB schema
- Control library: fix filter dropdown overflow by splitting into search + filter rows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-15 00:23:19 +01:00
parent 2ed1c08acf
commit f3e05c1bf7
5 changed files with 746 additions and 110 deletions

View File

@@ -363,83 +363,85 @@ export default function ControlLibraryPage() {
)} )}
{/* Filters */} {/* Filters */}
<div className="flex items-center gap-3"> <div className="space-y-3">
<div className="relative flex-1"> <div className="flex items-center gap-3">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" /> <div className="relative flex-1">
<input <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
type="text" <input
placeholder="Controls durchsuchen..." type="text"
value={searchQuery} placeholder="Controls durchsuchen..."
onChange={e => setSearchQuery(e.target.value)} value={searchQuery}
className="w-full pl-9 pr-4 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" onChange={e => setSearchQuery(e.target.value)}
/> className="w-full pl-9 pr-4 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"
/>
</div>
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-2 flex-wrap">
<Filter className="w-4 h-4 text-gray-400" /> <Filter className="w-4 h-4 text-gray-400" />
<select
value={severityFilter}
onChange={e => setSeverityFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Schweregrad</option>
<option value="critical">Kritisch</option>
<option value="high">Hoch</option>
<option value="medium">Mittel</option>
<option value="low">Niedrig</option>
</select>
<select
value={domainFilter}
onChange={e => setDomainFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Domain</option>
{domains.map(d => (
<option key={d} value={d}>{d}</option>
))}
</select>
<select
value={stateFilter}
onChange={e => setStateFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Status</option>
<option value="draft">Draft</option>
<option value="approved">Approved</option>
<option value="needs_review">Review noetig</option>
<option value="too_close">Zu aehnlich</option>
<option value="duplicate">Duplikat</option>
</select>
<select
value={verificationFilter}
onChange={e => setVerificationFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Nachweis</option>
{Object.entries(VERIFICATION_METHODS).map(([k, v]) => (
<option key={k} value={k}>{v.label}</option>
))}
</select>
<select
value={categoryFilter}
onChange={e => setCategoryFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Kategorie</option>
{CATEGORY_OPTIONS.map(c => (
<option key={c.value} value={c.value}>{c.label}</option>
))}
</select>
<select
value={audienceFilter}
onChange={e => setAudienceFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Zielgruppe</option>
{Object.entries(TARGET_AUDIENCE_OPTIONS).map(([k, v]) => (
<option key={k} value={k}>{v.label}</option>
))}
</select>
</div> </div>
<select
value={severityFilter}
onChange={e => setSeverityFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Schweregrade</option>
<option value="critical">Kritisch</option>
<option value="high">Hoch</option>
<option value="medium">Mittel</option>
<option value="low">Niedrig</option>
</select>
<select
value={domainFilter}
onChange={e => setDomainFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Domains</option>
{domains.map(d => (
<option key={d} value={d}>{d}</option>
))}
</select>
<select
value={stateFilter}
onChange={e => setStateFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Status</option>
<option value="draft">Draft</option>
<option value="approved">Approved</option>
<option value="needs_review">Review noetig</option>
<option value="too_close">Zu aehnlich</option>
<option value="duplicate">Duplikat</option>
</select>
<select
value={verificationFilter}
onChange={e => setVerificationFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Nachweismethoden</option>
{Object.entries(VERIFICATION_METHODS).map(([k, v]) => (
<option key={k} value={k}>{v.label}</option>
))}
</select>
<select
value={categoryFilter}
onChange={e => setCategoryFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Kategorien</option>
{CATEGORY_OPTIONS.map(c => (
<option key={c.value} value={c.value}>{c.label}</option>
))}
</select>
<select
value={audienceFilter}
onChange={e => setAudienceFilter(e.target.value)}
className="text-sm border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Zielgruppen</option>
{Object.entries(TARGET_AUDIENCE_OPTIONS).map(([k, v]) => (
<option key={k} value={k}>{v.label}</option>
))}
</select>
</div> </div>
{/* Processing Stats */} {/* Processing Stats */}

View File

@@ -1128,24 +1128,88 @@ export default function WhistleblowerPage() {
</div> </div>
)} )}
{/* Info Box about HinSchG Deadlines (Overview Tab) */} {/* Info Box about HinSchG (Overview Tab) */}
{activeTab === 'overview' && ( {activeTab === 'overview' && (
<div className="bg-blue-50 border border-blue-200 rounded-xl p-4"> <div className="space-y-4">
<div className="flex items-start gap-3"> {/* Gesetzliche Grundlage */}
<svg className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <div className="bg-blue-50 border border-blue-200 rounded-xl p-5">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <div className="flex items-start gap-3">
</svg> <svg className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
<h4 className="font-medium text-blue-800">HinSchG-Fristen</h4> </svg>
<p className="text-sm text-blue-600 mt-1"> <div>
Nach dem Hinweisgeberschutzgesetz (HinSchG) gelten folgende Fristen: <h4 className="font-medium text-blue-800">Gesetzliche Grundlage: Hinweisgeberschutzgesetz (HinSchG)</h4>
Die Eingangsbestaetigung muss innerhalb von <strong>7 Tagen</strong> an den <p className="text-sm text-blue-600 mt-1">
Hinweisgeber versendet werden (ss 17 Abs. 1 S. 2). Das HinSchG setzt die <strong>EU-Whistleblowing-Richtlinie (2019/1937)</strong> in deutsches Recht um
Eine Rueckmeldung ueber ergriffene Massnahmen muss innerhalb von <strong>3 Monaten</strong> nach und ist seit dem <strong>2. Juli 2023</strong> in Kraft. Seit dem <strong>17. Dezember 2023</strong> gilt
Eingangsbestaetigung erfolgen (ss 17 Abs. 2). die Pflicht zur Einrichtung einer internen Meldestelle auch fuer Unternehmen ab 50 Beschaeftigten (ss 12 HinSchG).
Der Schutz des Hinweisgebers vor Repressalien ist zwingend sicherzustellen (ss 36). </p>
</div>
</div>
</div>
{/* Fristen & Pflichten */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-white border border-gray-200 rounded-xl p-4">
<div className="flex items-center gap-2 mb-2">
<svg className="w-4 h-4 text-orange-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<h5 className="text-sm font-semibold text-gray-900">7-Tage-Frist</h5>
</div>
<p className="text-xs text-gray-600">
Eingangsbestaetigung an den Hinweisgeber innerhalb von 7 Tagen nach Meldungseingang (ss 17 Abs. 1 S. 2 HinSchG).
</p> </p>
</div> </div>
<div className="bg-white border border-gray-200 rounded-xl p-4">
<div className="flex items-center gap-2 mb-2">
<svg className="w-4 h-4 text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<h5 className="text-sm font-semibold text-gray-900">3-Monate-Frist</h5>
</div>
<p className="text-xs text-gray-600">
Rueckmeldung ueber ergriffene Folgemaßnahmen innerhalb von 3 Monaten nach Eingangsbestaetigung (ss 17 Abs. 2 HinSchG).
</p>
</div>
<div className="bg-white border border-gray-200 rounded-xl p-4">
<div className="flex items-center gap-2 mb-2">
<svg className="w-4 h-4 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<h5 className="text-sm font-semibold text-gray-900">3 Jahre Aufbewahrung</h5>
</div>
<p className="text-xs text-gray-600">
Dokumentation der Meldungen und Folgemaßnahmen ist 3 Jahre nach Abschluss aufzubewahren (ss 11 Abs. 5 HinSchG).
</p>
</div>
</div>
{/* Sachlicher Anwendungsbereich & Schutz */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4">
<h5 className="text-sm font-semibold text-amber-800 mb-2">Sachlicher Anwendungsbereich (ss 2 HinSchG)</h5>
<ul className="text-xs text-amber-700 space-y-1">
<li>Verstoesse gegen Strafvorschriften (StGB, Nebenstrafrecht)</li>
<li>Verstoesse gegen Datenschutzrecht (DSGVO, BDSG)</li>
<li>Geldwaesche und Terrorismusfinanzierung (GwG)</li>
<li>Produktsicherheit und Verbraucherschutz</li>
<li>Umweltschutz und Lebensmittelsicherheit</li>
<li>Arbeitsschutz und Arbeitnehmerrechte</li>
<li>Wettbewerbs- und Kartellrecht</li>
<li>Steuer- und Abgabenrecht (bei Unternehmen)</li>
</ul>
</div>
<div className="bg-green-50 border border-green-200 rounded-xl p-4">
<h5 className="text-sm font-semibold text-green-800 mb-2">Schutz des Hinweisgebers (ss 3637 HinSchG)</h5>
<ul className="text-xs text-green-700 space-y-1">
<li><strong>Repressalienverbot:</strong> Jede Benachteiligung ist untersagt (ss 36)</li>
<li><strong>Beweislastumkehr:</strong> Arbeitgeber muss beweisen, dass Maßnahmen nicht mit Meldung zusammenhaengen</li>
<li><strong>Schadensersatz:</strong> Bei Verstoessen gegen Repressalienverbot (ss 37)</li>
<li><strong>Vertraulichkeit:</strong> Identitaet darf nur bei Zustimmung oder gesetzlicher Pflicht offengelegt werden (ss 8)</li>
<li><strong>Bussgelder:</strong> Bis zu 50.000 EUR bei Verstoessen gegen die Einrichtungspflicht (ss 40)</li>
</ul>
</div>
</div> </div>
</div> </div>
)} )}

View File

@@ -852,18 +852,28 @@ export const STEP_EXPLANATIONS = {
}, },
'whistleblower': { 'whistleblower': {
title: 'Hinweisgebersystem', title: 'Hinweisgebersystem',
description: 'Meldestelle gemaess Hinweisgeberschutzgesetz (HinSchG)', description: 'Interne Meldestelle gemaess Hinweisgeberschutzgesetz (HinSchG) — seit 17. Dezember 2023 Pflicht fuer alle Unternehmen ab 50 Beschaeftigten',
explanation: 'Das Hinweisgebersystem bietet eine sichere, anonyme Meldestelle fuer Compliance-Verstoesse gemaess dem Hinweisgeberschutzgesetz (HinSchG). Unternehmen ab 50 Mitarbeitern sind zur Einrichtung verpflichtet.', explanation: 'Das Hinweisgebersystem implementiert eine HinSchG-konforme interne Meldestelle fuer die sichere, auch anonyme Meldung von Rechtsverstoessen. Es setzt die EU-Whistleblowing-Richtlinie (2019/1937) in deutsches Recht um. Beschaeftigungsgeber mit mindestens 50 Beschaeftigten sind zur Einrichtung verpflichtet (§ 12 HinSchG). Das System unterstuetzt den gesamten Meldeprozess: Einreichung, Eingangsbestaetigung (7-Tage-Frist), Sachverhaltspruefung, Folgemaßnahmen und Rueckmeldung (3-Monate-Frist).',
tips: [ tips: [
{ {
icon: 'warning' as const, icon: 'warning' as const,
title: 'Pflicht ab 50 MA', title: 'Pflicht ab 50 Beschaeftigten',
description: 'Seit Juli 2023 muessen Unternehmen ab 50 Mitarbeitern eine interne Meldestelle einrichten (HinSchG §12).', description: 'Seit 17.12.2023 gilt die Pflicht fuer ALLE Unternehmen ab 50 Beschaeftigten (§ 12 HinSchG). Verstoesse koennen mit Bussgeldern bis zu 50.000 EUR geahndet werden (§ 40 HinSchG).',
}, },
{ {
icon: 'info' as const, icon: 'info' as const,
title: 'Anonymitaet', title: 'Anonymitaet & Vertraulichkeit',
description: 'Die Identitaet des Hinweisgebers muss geschuetzt werden. Repressalien gegen Hinweisgeber sind verboten.', description: 'Die Identitaet des Hinweisgebers ist streng vertraulich zu behandeln (§ 8 HinSchG). Anonyme Meldungen sollen bearbeitet werden. Repressalien sind verboten und loesen Schadensersatzpflicht aus (§ 36, § 37 HinSchG).',
},
{
icon: 'lightbulb' as const,
title: 'Gesetzliche Fristen',
description: 'Eingangsbestaetigung innerhalb von 7 Tagen (§ 17 Abs. 1 S. 2). Rueckmeldung ueber ergriffene Folgemaßnahmen innerhalb von 3 Monaten nach Eingangsbestaetigung (§ 17 Abs. 2). Die Dokumentation muss 3 Jahre aufbewahrt werden (§ 11 HinSchG).',
},
{
icon: 'warning' as const,
title: 'Sachlicher Anwendungsbereich',
description: 'Erfasst werden Verstoesse gegen EU-Recht und nationales Recht, u.a. Strafrecht, Datenschutz (DSGVO/BDSG), Arbeitsschutz, Umweltschutz, Geldwaesche, Produktsicherheit und Verbraucherschutz (§ 2 HinSchG).',
}, },
], ],
}, },

View File

@@ -0,0 +1,340 @@
-- Migration 054: Erweiterte HinSchG-Wiki-Artikel
-- Ergaenzt die bestehende HinSchG-Kategorie um detaillierte Artikel
-- Bestehenden Grundlagen-Artikel mit umfassenderem Inhalt aktualisieren
UPDATE compliance_wiki_articles
SET content = '## Ueberblick
Das **Hinweisgeberschutzgesetz (HinSchG)** setzt die EU-Whistleblowing-Richtlinie (EU) 2019/1937 in deutsches Recht um. Es schuetzt Personen, die auf Missstaende in Unternehmen und Behoerden hinweisen und ist seit dem **2. Juli 2023** in Kraft.
- Ab 02.07.2023: Pflicht fuer Unternehmen ab **250 Beschaeftigten**
- Ab 17.12.2023: Pflicht fuer Unternehmen ab **50 Beschaeftigten** (§ 12 HinSchG)
## Kernpflichten
### Interne Meldestelle einrichten (§ 12 HinSchG)
- Kann eine **interne Person** (Ombudsperson) oder ein **externer Dienstleister** sein
- Meldungen muessen **muendlich, schriftlich und persoenlich** moeglich sein
- Die Meldestelle muss **unabhaengig** und **fachkundig** sein
- **Gemeinsame Meldestellen** sind fuer Unternehmen mit 50249 Beschaeftigten zulaessig
### Gesetzliche Fristen (§ 17 HinSchG)
- Eingangsbestaetigung innerhalb von **7 Tagen** nach Meldungseingang (§ 17 Abs. 1 S. 2)
- Rueckmeldung ueber Folgemaßnahmen innerhalb von **3 Monaten** nach Eingangsbestaetigung (§ 17 Abs. 2)
- Dokumentation muss **3 Jahre** nach Abschluss aufbewahrt werden (§ 11 Abs. 5)
### Vertraulichkeitsgebot (§ 8 HinSchG)
- Die **Identitaet des Hinweisgebers** darf nur den zustaendigen Personen bekannt sein
- Offenlegung nur mit **Einwilligung** oder bei **gesetzlicher Verpflichtung**
- Verstoss ist bussgeld-bewehrt (bis 50.000 EUR)
## Welche Daten fallen an?
- Identitaet des Hinweisgebers (besonders schuetzenswert!)
- Beschuldigte Personen
- Zeugen und weitere Beteiligte
- Inhalt der Meldung (kann sensible Daten enthalten)
- Kommunikationsverlauf
## Datenschutz-Anforderungen
- **Eigene Verarbeitungstaetigkeit** im VVT anlegen
- Rechtsgrundlage: Art. 6 Abs. 1c DSGVO (rechtliche Verpflichtung)
- **Zugriffsbeschraenkung:** Nur die benannte Meldestelle darf auf die Daten zugreifen
- **Loeschfrist:** 3 Jahre nach Abschluss des Verfahrens (§ 11 Abs. 5 HinSchG)
- Bei Art.-9-Daten in Meldungen: besondere Schutzmassnahmen erforderlich
## Sanktionen (§ 40 HinSchG)
| Verstoss | Bussgeld |
|----------|----------|
| Keine Meldestelle eingerichtet | Bis 20.000 EUR |
| Behinderung einer Meldung | Bis 50.000 EUR |
| Verstoss gegen Vertraulichkeitsgebot | Bis 50.000 EUR |
| Repressalien gegen Hinweisgeber | Bis 50.000 EUR |
## Praxis-Tipp
Pruefen Sie bei externen Meldestellen-Anbietern, ob ein **AVV** erforderlich ist. In den meisten Faellen ja — der Anbieter verarbeitet personenbezogene Daten in Ihrem Auftrag.',
summary = 'Das HinSchG setzt die EU-Whistleblowing-Richtlinie um und verpflichtet seit Dezember 2023 alle Unternehmen ab 50 Beschaeftigten zur Einrichtung einer internen Meldestelle. Verstoesse koennen mit bis zu 50.000 EUR geahndet werden.',
legal_refs = ARRAY['§ 2 HinSchG', '§ 8 HinSchG', '§ 11 Abs. 5 HinSchG', '§ 12 HinSchG', '§ 17 HinSchG', '§ 36 HinSchG', '§ 40 HinSchG', 'Art. 6 Abs. 1c DSGVO', 'EU-RL 2019/1937'],
tags = ARRAY['hinweisgeberschutz', 'whistleblower', 'meldestelle', 'vertraulichkeit', 'fristen', 'bussgelder'],
version = 2,
updated_at = NOW()
WHERE id = 'hinschg-grundlagen';
-- Neuer Artikel: Sachlicher Anwendungsbereich
INSERT INTO compliance_wiki_articles (id, category_id, title, summary, content, legal_refs, tags, relevance, source_urls) VALUES
('hinschg-anwendungsbereich', 'hinschg',
'Sachlicher Anwendungsbereich — Welche Verstoesse sind meldbar?',
'Das HinSchG schuetzt Meldungen ueber Verstoesse gegen EU-Recht und nationales Recht. Der Anwendungsbereich geht weit ueber rein strafrechtliche Verstoesse hinaus.',
'## Ueberblick
Der sachliche Anwendungsbereich des HinSchG (§ 2) ist bewusst weit gefasst. Geschuetzt werden Meldungen ueber Verstoesse, die **strafbewehrt** sind oder **bussgeld-bewehrt**, sowie Verstoesse gegen bestimmte **EU-Rechtsakte** und deren nationale Umsetzungsgesetze.
## Meldbare Verstoesse (§ 2 HinSchG)
### Strafvorschriften
- Alle Straftaten nach dem **StGB** (Betrug, Untreue, Korruption, Urkundenfaelschung)
- Straftaten nach **Nebenstrafrecht** (Umweltstrafrecht, Wirtschaftsstrafrecht)
### Bussgeld-bewehrte Vorschriften
- Verstoesse gegen **Ordnungswidrigkeiten-Vorschriften**, soweit die verletzte Norm dem Schutz von Leben, Leib, Gesundheit oder Rechten von Beschaeftigten dient
### EU-Rechtsakte und nationale Umsetzung
| Rechtsgebiet | Beispiele |
|-------------|-----------|
| Datenschutz | DSGVO, BDSG — z.B. unrechtmaessige Datenweitergabe |
| Geldwaesche | GwG — z.B. fehlende Verdachtsmeldungen |
| Produktsicherheit | ProdSG — z.B. mangelhafte Produkte im Verkehr |
| Umweltschutz | BImSchG, KrWG — z.B. illegale Entsorgung |
| Lebensmittelsicherheit | LFGB — z.B. Hygienemaengel |
| Arbeitsschutz | ArbSchG, ArbZG — z.B. ueberlange Arbeitszeiten |
| Verbraucherschutz | UWG — z.B. irrefuehrende Werbung |
| Wettbewerbsrecht | GWB — z.B. Preisabsprachen, Kartelle |
| Steuerrecht | AO — z.B. Steuerhinterziehung bei Unternehmen |
| Vergaberecht | GWB Teil 4 — z.B. Manipulationen bei oeffentlichen Auftraegen |
## Nicht erfasste Bereiche
- **Rein privatrechtliche Streitigkeiten** (z.B. Vertragskonflikte)
- **Nationale Sicherheit** — Informationen, die der nationalen Sicherheit unterliegen
- **Berufsgeheimnisse** — Anwalts-, Arzt- oder Seelsorgegeheimnis (mit Ausnahmen)
## Praxis-Tipp
Im Zweifelsfall sollte eine Meldung **immer entgegengenommen** und geprueft werden. Die Meldestelle entscheidet erst bei der Sachverhaltspruefung, ob ein meldepflichtiger Verstoss vorliegt.',
ARRAY['§ 2 HinSchG', '§ 3 HinSchG', '§ 5 HinSchG'],
ARRAY['anwendungsbereich', 'verstoesse', 'strafrecht', 'bussgeld', 'eu-recht', 'meldepflicht'],
'important',
ARRAY[]::text[])
ON CONFLICT (id) DO NOTHING;
-- Neuer Artikel: Schutz des Hinweisgebers
INSERT INTO compliance_wiki_articles (id, category_id, title, summary, content, legal_refs, tags, relevance, source_urls) VALUES
('hinschg-hinweisgeberschutz', 'hinschg',
'Schutz des Hinweisgebers — Repressalienverbot und Beweislastumkehr',
'Das HinSchG verbietet jede Form der Benachteiligung von Hinweisgebern. Bei Verstoessen greift eine Beweislastumkehr zugunsten des Hinweisgebers.',
'## Ueberblick
Der Schutz hinweisgebender Personen ist das **Kernziel des HinSchG**. Das Gesetz sieht ein umfassendes Verbot von Repressalien, eine Beweislastumkehr und einen Schadensersatzanspruch vor.
## Repressalienverbot (§ 36 HinSchG)
Verboten ist jede Form der **Benachteiligung** aufgrund einer Meldung:
- **Kuendigung** oder Nichterneuerung eines befristeten Vertrags
- **Abmahnung** oder negative Leistungsbewertung
- **Versetzung**, Degradierung oder Befoerderungsverweigerung
- **Gehaltsreduktion** oder Entzug von Verguenstigungen
- **Mobbing**, Ausgrenzung, Einschuechterung
- **Aufnahme in schwarze Listen** oder Branchenregister
- **Entzug einer Lizenz** oder Genehmigung
- **Anordnung einer psychiatrischen Untersuchung**
## Beweislastumkehr (§ 36 Abs. 2 HinSchG)
Erleidet ein Hinweisgeber nach einer Meldung eine Benachteiligung, wird **vermutet**, dass diese Benachteiligung eine Repressalie ist. Der **Arbeitgeber** muss beweisen, dass die Massnahme:
- Auf hinreichend gerechtfertigten Gruenden beruht
- **Keinen Zusammenhang** mit der Meldung hat
## Schadensersatz (§ 37 HinSchG)
- Hinweisgeber hat Anspruch auf **Ersatz des erlittenen Schadens**
- Umfasst **materielle** Schaeden (Gehaltsverlust) und **immaterielle** Schaeden (Mobbing)
- Kein **Mitverschulden** des Hinweisgebers, wenn die Meldung in gutem Glauben erfolgte
## Geschuetzte Personengruppen (§ 1 HinSchG)
- Arbeitnehmerinnen und Arbeitnehmer
- Beamtinnen und Beamte
- Auszubildende und Praktikanten
- Selbststaendige und Anteilseigner
- Mitglieder von Leitungs- und Aufsichtsorganen
- Ehrenamtlich Taetige und Freiwillige
- Bewerberinnen und Bewerber (bei Informationen im Bewerbungsprozess)
## Voraussetzungen fuer den Schutz (§ 33 HinSchG)
Der Schutz greift, wenn der Hinweisgeber:
- **Hinreichenden Grund** hatte anzunehmen, dass die gemeldeten Informationen der Wahrheit entsprechen
- Die Meldung ueber einen **vorgesehenen Kanal** (intern oder extern) erfolgte
- Der Verstoß in den **sachlichen Anwendungsbereich** faellt
**Achtung:** Wissentlich **falsche Meldungen** sind nicht geschuetzt und koennen eigene Schadensersatzpflichten ausloesen (§ 38 HinSchG).',
ARRAY['§ 1 HinSchG', '§ 33 HinSchG', '§ 36 HinSchG', '§ 37 HinSchG', '§ 38 HinSchG'],
ARRAY['repressalienverbot', 'beweislastumkehr', 'schadensersatz', 'hinweisgeberschutz', 'kuendigungsschutz'],
'critical',
ARRAY[]::text[])
ON CONFLICT (id) DO NOTHING;
-- Neuer Artikel: Interne vs. Externe Meldestelle
INSERT INTO compliance_wiki_articles (id, category_id, title, summary, content, legal_refs, tags, relevance, source_urls) VALUES
('hinschg-meldestellen', 'hinschg',
'Interne vs. Externe Meldestelle — Was ist der Unterschied?',
'Das HinSchG sieht interne und externe Meldestelllen vor. Hinweisgeber koennen frei waehlen, an wen sie sich wenden. Die Einrichtung einer internen Meldestelle ist Pflicht.',
'## Ueberblick
Das HinSchG unterscheidet zwischen **internen Meldestellen** (beim Unternehmen) und **externen Meldestellen** (bei Behoerden). Hinweisgeber haben ein **Wahlrecht** — sie koennen sich direkt an die externe Meldestelle wenden, ohne den internen Weg vorher beschritten zu haben.
## Interne Meldestelle (§§ 1218 HinSchG)
### Einrichtungspflicht
- **Ab 50 Beschaeftigten**: Pflicht zur Einrichtung (seit 17.12.2023)
- Unternehmen mit **50249 Beschaeftigten** duerfen eine gemeinsame Meldestelle nutzen
- Ab **250 Beschaeftigten**: eigene Meldestelle erforderlich
### Anforderungen
- **Unabhaengigkeit** — keine Interessenkonflikte
- **Fachkunde** — geschultes Personal
- Meldekanal muss **muendliche, schriftliche und persoenliche** Meldungen ermoeglichen
- **Anonyme Meldungen** sollen ermoeglicht werden (keine Pflicht, aber empfohlen)
### Besetzung
Die Meldestelle kann besetzt werden durch:
- Interne **Ombudsperson** (Compliance Officer, Datenschutzbeauftragter in Personalunion kritisch)
- **Externer Dienstleister** (Kanzlei, spezialisierter Anbieter) — erfordert AVV
- **Gremium** aus mehreren Personen
## Externe Meldestelle (§§ 1931 HinSchG)
Die wichtigsten externen Meldestellen:
| Meldestelle | Zustaendigkeit |
|-------------|---------------|
| **BfJ (Bundesamt fuer Justiz)** | Auffangmeldestelle fuer alle Verstoesse |
| **BaFin** | Finanzaufsicht, Geldwaesche, Wertpapierrecht |
| **Bundeskartellamt** | Wettbewerbsrecht, Kartelle |
## Wahlrecht des Hinweisgebers
- Hinweisgeber duerfen **frei waehlen** zwischen intern und extern
- Die interne Meldung ist **nicht vorrangig** — anders als bei vielen Unternehmenspolicies
- Ein Unternehmen darf **nicht verbieten**, sich an die externe Stelle zu wenden
## Praxis-Tipp
Gestalten Sie die interne Meldestelle **niedrigschwellig und vertrauenswuerdig**, damit Mitarbeiter sie bevorzugt nutzen. Unternehmen erfahren frueh von Problemen und koennen schneller reagieren.',
ARRAY['§ 12 HinSchG', '§ 13 HinSchG', '§ 14 HinSchG', '§ 16 HinSchG', '§ 17 HinSchG', '§ 19 HinSchG', '§ 27 HinSchG'],
ARRAY['meldestelle', 'intern', 'extern', 'ombudsperson', 'bfj', 'bafin', 'wahlrecht'],
'critical',
ARRAY[]::text[])
ON CONFLICT (id) DO NOTHING;
-- Neuer Artikel: Verfahrensablauf bei einer Meldung
INSERT INTO compliance_wiki_articles (id, category_id, title, summary, content, legal_refs, tags, relevance, source_urls) VALUES
('hinschg-verfahrensablauf', 'hinschg',
'Verfahrensablauf — Von der Meldung bis zur Rueckmeldung',
'Der gesetzlich vorgeschriebene Ablauf einer Meldung umfasst Eingangsbestaetigung, Sachverhaltspruefung, Folgemaßnahmen und Rueckmeldung an den Hinweisgeber.',
'## Ueberblick
Das HinSchG schreibt einen strukturierten Verfahrensablauf fuer jede eingehende Meldung vor (§ 17 HinSchG). Dieser Ablauf ist nicht verhandelbar — die Fristen sind gesetzlich bindend.
## Schritt-fuer-Schritt-Verfahren
### 1. Meldungseingang
- Meldung wird ueber den internen Meldekanal eingereicht
- Das System vergibt automatisch eine **Referenznummer** und einen **Zugangscode**
- Der Zugangscode ermoeglicht dem Hinweisgeber die anonyme Statusabfrage
### 2. Eingangsbestaetigung (Frist: 7 Tage)
- Innerhalb von **7 Tagen** nach Eingang muss die Meldestelle den Eingang bestaetigen (§ 17 Abs. 1 S. 2)
- Bei anonymen Meldungen: Bestaetigung ueber den anonymen Kommunikationskanal
- **Wichtig:** Die Bestaetigung darf keine inhaltliche Bewertung enthalten
### 3. Sachverhaltspruefung
- Die Meldestelle prueft, ob ein **meldepflichtiger Verstoss** vorliegt (§ 2 HinSchG)
- Stichhaltigkeitspruefung der gemeldeten Informationen
- Gegebenenfalls Rueckfragen an den Hinweisgeber (ueber anonymen Kanal)
### 4. Folgemaßnahmen (§ 18 HinSchG)
Moegliche Maßnahmen umfassen:
- **Interne Untersuchung** (ggf. mit externen Gutachtern)
- **Abstellung des Verstosses** durch organisatorische Aenderungen
- Weiterleitung an eine **zustaendige Behoerde**
- **Disziplinarmaßnahmen** gegen Verantwortliche
- **Einstellung** des Verfahrens bei unbegruendeten Meldungen
### 5. Rueckmeldung (Frist: 3 Monate)
- Innerhalb von **3 Monaten** nach Eingangsbestaetigung muss dem Hinweisgeber eine Rueckmeldung ueber ergriffene oder geplante Folgemaßnahmen gegeben werden (§ 17 Abs. 2)
- Die Rueckmeldung soll den Hinweisgeber informieren, **ohne laufende Ermittlungen zu gefaehrden**
### 6. Abschluss und Dokumentation
- Abschließende Dokumentation des gesamten Verfahrens
- Aufbewahrung fuer **3 Jahre** nach Abschluss (§ 11 Abs. 5 HinSchG)
- Danach: Loeschung aller personenbezogenen Daten
## Fristen-Uebersicht
| Schritt | Frist | Ab wann |
|---------|-------|---------|
| Eingangsbestaetigung | 7 Tage | Ab Meldungseingang |
| Rueckmeldung | 3 Monate | Ab Eingangsbestaetigung |
| Aufbewahrung | 3 Jahre | Ab Verfahrensabschluss |
## Praxis-Tipp
Richten Sie ein **automatisches Fristen-Monitoring** ein. Das BreakPilot Hinweisgebersystem berechnet die Fristen automatisch und warnt rechtzeitig vor drohender Ueberschreitung.',
ARRAY['§ 11 Abs. 5 HinSchG', '§ 17 Abs. 1 HinSchG', '§ 17 Abs. 2 HinSchG', '§ 18 HinSchG'],
ARRAY['verfahren', 'ablauf', 'fristen', 'eingangsbestaetigung', 'rueckmeldung', 'folgemaßnahmen', 'dokumentation'],
'important',
ARRAY[]::text[])
ON CONFLICT (id) DO NOTHING;
-- Neuer Artikel: Datenschutz-Anforderungen
INSERT INTO compliance_wiki_articles (id, category_id, title, summary, content, legal_refs, tags, relevance, source_urls) VALUES
('hinschg-datenschutz', 'hinschg',
'Datenschutz im Hinweisgebersystem — DSGVO-Konformitaet sicherstellen',
'Das Hinweisgebersystem verarbeitet besonders sensible personenbezogene Daten. Die DSGVO-Anforderungen an Datenschutz, Loeschfristen und Zugriffskontrollen sind strikt einzuhalten.',
'## Ueberblick
Ein Hinweisgebersystem verarbeitet **hochsensible personenbezogene Daten**: die Identitaet des Hinweisgebers, Beschuldigter, Zeugen und den Inhalt der Meldung. Die DSGVO-Anforderungen muessen mit den HinSchG-Pflichten in Einklang gebracht werden.
## Rechtsgrundlage
Die Verarbeitung stuetzt sich auf:
- **Art. 6 Abs. 1c DSGVO** — Erfuellung einer rechtlichen Verpflichtung (HinSchG)
- **Art. 6 Abs. 1f DSGVO** — Berechtigtes Interesse (fuer nicht-verpflichtete Unternehmen)
- **Art. 9 Abs. 2b DSGVO** — Fuer besondere Datenkategorien im Beschaeftigungskontext
## VVT-Eintrag (Pflicht)
Erstellen Sie einen eigenen VVT-Eintrag fuer das Hinweisgebersystem:
| Feld | Inhalt |
|------|--------|
| Bezeichnung | Betrieb des internen Hinweisgebersystems |
| Rechtsgrundlage | Art. 6 Abs. 1c DSGVO i.V.m. §§ 12 ff. HinSchG |
| Kategorien betroffener Personen | Hinweisgeber, Beschuldigte, Zeugen |
| Datenkategorien | Identitaetsdaten, Kommunikationsdaten, Meldungsinhalt |
| Loeschfrist | 3 Jahre nach Verfahrensabschluss |
| Empfaenger | Interne Meldestelle, ggf. externe Meldestelle |
## Technisch-organisatorische Massnahmen (TOM)
- **Verschluesselung** — Alle Meldungsdaten at-rest und in-transit verschluesselt
- **Zugriffsbeschraenkung** — Nur die benannte Meldestelle darf auf Daten zugreifen
- **Protokollierung** — Revisionssicherer Audit-Trail aller Zugriffe
- **Pseudonymisierung** — Anonyme Meldungen ohne Zuordnung zu Klarnamen
- **Trennung** — Meldungsdaten getrennt von sonstigen HR-Daten speichern
## Loeschkonzept
| Daten | Loeschfrist | Rechtsgrundlage |
|-------|-------------|-----------------|
| Meldungsdaten | 3 Jahre nach Abschluss | § 11 Abs. 5 HinSchG |
| Audit-Trail | 3 Jahre nach Abschluss | § 11 Abs. 5 HinSchG |
| Kommunikationsdaten | 3 Jahre nach Abschluss | § 11 Abs. 5 HinSchG |
| Zugangscodes | Nach Verfahrensabschluss | Zweckerfuellung |
## DSFA-Pflicht?
Eine **Datenschutz-Folgenabschaetzung** (Art. 35 DSGVO) ist in vielen Faellen erforderlich, da:
- **Systematische Ueberwachung** von Beschaeftigten (potenziell)
- Verarbeitung **besonderer Datenkategorien** moeglich (Art. 9 DSGVO)
- **Verletzliche Personengruppen** betroffen (Hinweisgeber, Beschuldigte)
## Praxis-Tipp
Fuehren Sie eine DSFA durch und dokumentieren Sie die Abwaegung. Dies dient auch als Nachweis der Rechenschaftspflicht (Art. 5 Abs. 2 DSGVO).',
ARRAY['Art. 5 Abs. 2 DSGVO', 'Art. 6 Abs. 1c DSGVO', 'Art. 9 Abs. 2b DSGVO', 'Art. 28 DSGVO', 'Art. 35 DSGVO', '§ 8 HinSchG', '§ 11 Abs. 5 HinSchG', '§ 26 BDSG'],
ARRAY['datenschutz', 'dsgvo', 'vvt', 'dsfa', 'loeschfristen', 'tom', 'verschluesselung', 'audit-trail'],
'critical',
ARRAY[]::text[])
ON CONFLICT (id) DO NOTHING;

View File

@@ -1,33 +1,253 @@
# Whistleblower — Hinweisgebersystem # Whistleblower — Hinweisgebersystem
HinSchG-konformes Hinweisgebersystem fuer anonyme Meldungen und sichere Fallbearbeitung. HinSchG-konformes Hinweisgebersystem fuer anonyme und namentliche Meldungen, sichere Fallbearbeitung und automatische Fristenueberwachung.
## Gesetzliche Grundlage
### Hinweisgeberschutzgesetz (HinSchG)
Das **Hinweisgeberschutzgesetz (HinSchG)** setzt die EU-Whistleblowing-Richtlinie (EU) 2019/1937 in deutsches Recht um. Es ist seit dem **2. Juli 2023** in Kraft.
| Datum | Pflicht |
|-------|---------|
| 02.07.2023 | Inkrafttreten fuer Unternehmen ab 250 Beschaeftigten |
| 17.12.2023 | Erweiterung auf Unternehmen ab 50 Beschaeftigten (ss 12 HinSchG) |
### Sachlicher Anwendungsbereich (ss 2 HinSchG)
Das Gesetz schuetzt Hinweisgeber, die Informationen ueber **Verstoesse** melden, die unter anderem folgende Bereiche betreffen:
- **Strafrecht** — Straftaten nach StGB und Nebenstrafrecht
- **Datenschutz** — Verstoesse gegen DSGVO und BDSG
- **Geldwaesche** — Verstoesse gegen das Geldwaeschegesetz (GwG)
- **Produktsicherheit** — Verstoesse gegen Produktsicherheitsvorschriften
- **Umweltschutz** — Verstoesse gegen Umweltauflagen und -gesetze
- **Arbeitsschutz** — Verstoesse gegen Arbeitnehmerrechte und Arbeitsschutzvorschriften
- **Lebensmittelsicherheit** — Verstoesse gegen lebensmittelrechtliche Vorgaben
- **Wettbewerbs- und Kartellrecht** — Unlauterer Wettbewerb, Marktmanipulation
- **Verbraucherschutz** — Verstoesse gegen Verbraucherschutzvorschriften
- **Steuerrecht** — Steuerverstoesse bei Unternehmen
### Geschuetzte Personengruppen (ss 1 HinSchG)
- Arbeitnehmerinnen und Arbeitnehmer
- Beamtinnen und Beamte
- Auszubildende und Praktikanten
- Freiwillige und ehrenamtlich Taetige
- Selbststaendige und Anteilseigner
- Mitglieder von Leitungs- und Aufsichtsorganen
- Personen, die im Rahmen einer Bewerbung Informationen erlangt haben
### Fristen und Pflichten
| Pflicht | Frist | Rechtsgrundlage |
|---------|-------|-----------------|
| Eingangsbestaetigung | **7 Tage** nach Meldungseingang | ss 17 Abs. 1 S. 2 HinSchG |
| Rueckmeldung ueber Folgemaßnahmen | **3 Monate** nach Eingangsbestaetigung | ss 17 Abs. 2 HinSchG |
| Aufbewahrung der Dokumentation | **3 Jahre** nach Abschluss des Verfahrens | ss 11 Abs. 5 HinSchG |
### Schutz des Hinweisgebers
| Schutzmechanismus | Rechtsgrundlage | Beschreibung |
|-------------------|-----------------|--------------|
| **Repressalienverbot** | ss 36 HinSchG | Jede Benachteiligung wegen einer Meldung ist verboten |
| **Beweislastumkehr** | ss 36 Abs. 2 HinSchG | Arbeitgeber muss beweisen, dass Maßnahmen nicht mit Meldung zusammenhaengen |
| **Schadensersatz** | ss 37 HinSchG | Hinweisgeber hat Anspruch auf Ersatz des erlittenen Schadens |
| **Vertraulichkeit** | ss 8 HinSchG | Identitaet darf nur mit Einwilligung oder bei gesetzlicher Pflicht offengelegt werden |
### Sanktionen (ss 40 HinSchG)
| Verstoß | Bussgeld |
|---------|----------|
| Keine interne Meldestelle eingerichtet | Bis zu **20.000 EUR** |
| Behinderung einer Meldung | Bis zu **50.000 EUR** |
| Verstoß gegen Vertraulichkeitsgebot | Bis zu **50.000 EUR** |
| Repressalien gegen Hinweisgeber | Bis zu **50.000 EUR** |
---
## Features ## Features
- **Anonyme Meldungen** — Sichere, anonyme Eingabe von Hinweisen - **Anonyme und namentliche Meldungen** — Sichere Eingabe von Hinweisen, wahlweise anonym oder mit Kontaktdaten
- **Fallbearbeitung** — Workflow fuer Sichtung, Untersuchung und Abschluss - **Mehrstufiger Fallbearbeitungs-Workflow** — Neu → Bestaetigt → In Pruefung Untersuchung → Massnahmen → Abgeschlossen
- **Fristen-Management** — Automatische Ueberwachung der gesetzlichen Bearbeitungsfristen (7 Tage Eingangsbestaetigung, 3 Monate Rueckmeldung) - **Automatisches Fristen-Management** — Ueberwachung der 7-Tage- und 3-Monate-Fristen gemaess ss 17 HinSchG mit Warnungen bei drohender Ueberschreitung
- **Kommunikationskanal** — Anonymer Austausch zwischen Hinweisgeber und Ombudsperson - **Anonymer Kommunikationskanal** — Sicherer Austausch zwischen Hinweisgeber und Ombudsperson ohne Identitaetspreisgabe
- **Audit-Trail** — Lueckenlose Dokumentation aller Bearbeitungsschritte - **Massnahmen-Tracking** — Dokumentation und Nachverfolgung von Folgemaßnahmen
- **Prioritaetsstufen** — Klassifizierung nach Niedrig, Normal, Hoch, Kritisch
- **Audit-Trail** — Lueckenlose, revisionssichere Dokumentation aller Bearbeitungsschritte
- **Kategorisierung** — Vordefinierte Meldekategorien (Korruption, Betrug, Datenschutz, Diskriminierung, Umwelt, Wettbewerb, Produktsicherheit, Steuerhinterziehung)
- **Statistik-Dashboard** — Ueberblick ueber Meldungsaufkommen, Bearbeitungsstand und Fristeneinhaltung
---
## Architektur
### Bearbeitungs-Workflow
```mermaid
stateDiagram-v2
[*] --> Neu: Meldung eingereicht
Neu --> Bestaetigt: Eingangsbestaetigung (≤ 7 Tage)
Bestaetigt --> InPruefung: Inhaltliche Pruefung
InPruefung --> Untersuchung: Formelle Untersuchung
Untersuchung --> Massnahmen: Folgemaßnahmen eingeleitet
Massnahmen --> Abgeschlossen: Rueckmeldung (≤ 3 Monate)
InPruefung --> Abgelehnt: Unbegruendet / nicht zustaendig
Abgeschlossen --> [*]
Abgelehnt --> [*]
```
### Komponenten
| Komponente | Technologie | Beschreibung |
|------------|-------------|--------------|
| Frontend (Admin) | Next.js / React | SDK-Seite unter `/sdk/whistleblower` mit Tabs: Uebersicht, Neue Meldungen, In Untersuchung, Abgeschlossen, Einstellungen |
| API-Proxy | Next.js API Route | `/api/sdk/v1/whistleblower/[[...path]]/route.ts` — Proxy zum Backend |
| Backend-Handlers | Go / Gin | `whistleblower_handlers.go` — REST API fuer Meldungen, Nachrichten, Statistiken |
| Datenschicht | Go | `store.go` — PostgreSQL-Operationen, prepared statements |
| Datenmodell | Go | `models.go` — Structs fuer Report, Message, Measure, AuditEntry |
| TypeScript Types | TypeScript | `lib/sdk/whistleblower/types.ts` — Frontend-Typen, Deadline-Utilities |
| API Client | TypeScript | `lib/sdk/whistleblower/api.ts` — SDK-API-Aufrufe |
| DB-Schema | SQL | `migrations/009_whistleblower_schema.sql` |
---
## API Endpoints ## API Endpoints
Alle unter `/api/v1/whistleblower/`, benoetigen `X-Tenant-ID` Header. Alle unter `/api/v1/whistleblower/`, benoetigen `X-Tenant-ID` Header.
### Admin-Endpoints
| Method | Endpoint | Beschreibung | | Method | Endpoint | Beschreibung |
|--------|----------|-------------| |--------|----------|-------------|
| GET | `/reports` | Meldungen auflisten | | GET | `/reports` | Meldungen auflisten (mit Filter und Paginierung) |
| POST | `/reports` | Neue Meldung erstellen | | POST | `/reports` | Neue Meldung erfassen |
| GET | `/reports/{id}` | Meldungsdetails | | GET | `/reports/{id}` | Meldungsdetails inkl. Nachrichten, Massnahmen, Audit-Trail |
| PUT | `/reports/{id}/status` | Status aktualisieren | | PUT | `/reports/{id}` | Meldung aktualisieren (Status, Prioritaet, Zuweisung) |
| POST | `/reports/{id}/messages` | Nachricht hinzufuegen | | DELETE | `/reports/{id}` | Meldung loeschen |
| GET | `/reports/{id}/messages` | Nachrichten abrufen | | POST | `/reports/{id}/messages` | Nachricht an Hinweisgeber senden (Ombudsperson-Rolle) |
| GET | `/statistics` | Statistiken | | GET | `/reports/{id}/messages` | Nachrichten-Verlauf abrufen |
| GET | `/statistics` | Statistiken (Gesamt, nach Kategorie, nach Status, ueberfaellige) |
### Oeffentliche Endpoints (fuer Hinweisgeber)
| Method | Endpoint | Beschreibung |
|--------|----------|-------------|
| POST | `/public/reports` | Anonyme/namentliche Meldung einreichen |
| GET | `/public/reports/{accessKey}` | Meldungsstatus mit Zugangscode abfragen |
| POST | `/public/reports/{accessKey}/messages` | Nachricht als Hinweisgeber senden |
---
## Frontend ## Frontend
Seite unter `/sdk/whistleblower` mit Meldungsuebersicht, Falldetails und Statistik-Dashboard. ### SDK Admin-Seite (`/sdk/whistleblower`)
Die Seite bietet fuenf Tabs:
| Tab | Inhalt |
|-----|--------|
| **Uebersicht** | Statistik-Cards, HinSchG-Info-Box mit Fristen und Anwendungsbereich, Fristenwarnungen, alle Meldungen |
| **Neue Meldungen** | Gefilterte Ansicht: nur Status "Neu" — Eingangsbestaetigung steht aus |
| **In Untersuchung** | Gefilterte Ansicht: Status "Bestaetigt", "In Pruefung", "Untersuchung", "Massnahmen" |
| **Abgeschlossen** | Gefilterte Ansicht: Status "Abgeschlossen" und "Abgelehnt" |
| **Einstellungen** | Konfiguration (in spaeteren Versionen) |
### Funktionen
- **Meldung erfassen**: Modal-Dialog fuer Titel, Beschreibung, Kategorie, Prioritaet, anonym/namentlich
- **Falldetail-Drawer**: Seitenleiste mit Beschreibung, Badges, Status-Transitions, Zuweisungen, Kommentare, Nachrichten-Verlauf
- **Filter**: Kategorie, Status, Prioritaet — kombinierbar
- **Sortierung**: Ueberfaellige Meldungen zuerst, dann nach Prioritaet, dann nach Datum
- **Fristenwarnungen**: Rote Alerts bei ueberschrittenen 7-Tage- oder 3-Monate-Fristen
---
## Datenbank ## Datenbank
Migration `009_whistleblower_schema.sql` erstellt Tabellen fuer Meldungen, Nachrichten und Bearbeitungsschritte. ### Schema (Migration `009_whistleblower_schema.sql`)
#### Tabelle: `whistleblower_reports`
| Spalte | Typ | Beschreibung |
|--------|-----|--------------|
| `id` | UUID | Primaerschluessel |
| `tenant_id` | UUID | Mandanten-Zuordnung |
| `reference_number` | VARCHAR | Referenznummer (z.B. "WB-2026-000042") |
| `access_key` | VARCHAR | Anonymer Zugangscode (XXXX-XXXX-XXXX) |
| `category` | VARCHAR | Meldekategorie |
| `status` | VARCHAR | Bearbeitungsstatus |
| `priority` | VARCHAR | Prioritaetsstufe |
| `title` | VARCHAR | Meldungstitel |
| `description` | TEXT | Detailbeschreibung |
| `is_anonymous` | BOOLEAN | Anonyme Meldung |
| `reporter_name` | VARCHAR | Name (optional) |
| `reporter_email` | VARCHAR | E-Mail (optional) |
| `assigned_to` | VARCHAR | Zustaendige Person |
| `received_at` | TIMESTAMP | Eingangszeitpunkt |
| `acknowledged_at` | TIMESTAMP | Eingangsbestaetigung |
| `deadline_acknowledgment` | TIMESTAMP | 7-Tage-Frist (automatisch berechnet) |
| `deadline_feedback` | TIMESTAMP | 3-Monate-Frist (automatisch berechnet) |
| `closed_at` | TIMESTAMP | Abschlusszeitpunkt |
#### Tabelle: `whistleblower_messages`
Anonymer Kommunikationskanal zwischen Hinweisgeber und Ombudsperson.
#### Tabelle: `whistleblower_measures`
Dokumentation von Folgemaßnahmen mit Status-Tracking (geplant, in Bearbeitung, abgeschlossen).
#### Tabelle: `whistleblower_audit_trail`
Lueckenlose, revisionssichere Protokollierung aller Bearbeitungsschritte.
---
## Meldekategorien
| Kategorie | Beschreibung | Beispiele |
|-----------|--------------|-----------|
| Korruption | Bestechung, Vorteilsnahme | Schmiergeldzahlungen, Kickback-Vereinbarungen |
| Betrug | Vermoegensdelikte | Urkundenfaelschung, Bilanzbetrug |
| Datenschutz | DSGVO/BDSG-Verstoesse | Unerlaubte Datenweitergabe, fehlende Einwilligung |
| Diskriminierung | Benachteiligung | Mobbing, sexuelle Belaestigung, AGG-Verstoesse |
| Umwelt | Umweltvergehen | Illegale Entsorgung, Emissionsverstoesse |
| Wettbewerb | Kartellrecht | Preisabsprachen, Marktmanipulation |
| Produktsicherheit | Sicherheitsmaengel | Mangelhafte Produkte, fehlende Warnhinweise |
| Steuerhinterziehung | Steuerverstoesse | Steuerhinterziehung, illegale Steuergestaltung |
| Sonstiges | Weitere Verstoesse | Interne Richtlinienverstoesse |
---
## Fristen-Tracking
Das System berechnet Fristen automatisch und warnt bei drohender Ueberschreitung:
| Frist | Berechnung | Warnstufe |
|-------|------------|-----------|
| 7-Tage-Eingangsbestaetigung | `received_at + 7 Tage` | Orange ab 2 Tage vorher, Rot bei Ueberschreitung |
| 3-Monate-Rueckmeldung | `acknowledged_at + 3 Monate` | Orange ab 14 Tage vorher, Rot bei Ueberschreitung |
Utility-Funktionen in `types.ts`:
- `getDaysUntilAcknowledgment(report)` — Verbleibende Tage bis Eingangsbestaetigung
- `getDaysUntilFeedback(report)` — Verbleibende Tage bis Rueckmeldungsfrist
- `isAcknowledgmentOverdue(report)` — Prueft 7-Tage-Frist
- `isFeedbackOverdue(report)` — Prueft 3-Monate-Frist
- `generateAccessKey()` — Erzeugt Zugangscode im Format XXXX-XXXX-XXXX
---
## Datei-Referenz
| Datei | Beschreibung |
|-------|--------------|
| `admin-compliance/app/sdk/whistleblower/page.tsx` | Frontend-Seite (Tabs, Filter, Modals, Detail-Drawer) |
| `admin-compliance/app/api/sdk/v1/whistleblower/[[...path]]/route.ts` | API-Proxy zum Backend |
| `admin-compliance/lib/sdk/whistleblower/types.ts` | TypeScript-Typen, Enums, Deadline-Utilities |
| `admin-compliance/lib/sdk/whistleblower/api.ts` | API-Client fuer SDK-Backend |
| `ai-compliance-sdk/internal/whistleblower/models.go` | Go-Datenmodelle |
| `ai-compliance-sdk/internal/whistleblower/store.go` | PostgreSQL-Store (CRUD, Queries) |
| `ai-compliance-sdk/internal/api/handlers/whistleblower_handlers.go` | REST-API-Handler |
| `ai-compliance-sdk/migrations/009_whistleblower_schema.sql` | Datenbankschema |