feat(scope): Split HT-H01 B2B/B2C + register Verbraucherschutz document types + RAG ingestion
Some checks failed
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 38s
CI/CD / test-python-backend-compliance (push) Successful in 39s
CI/CD / test-python-document-crawler (push) Successful in 27s
CI/CD / test-python-dsms-gateway (push) Successful in 24s
CI/CD / deploy-hetzner (push) Has been cancelled
Some checks failed
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 38s
CI/CD / test-python-backend-compliance (push) Successful in 39s
CI/CD / test-python-document-crawler (push) Successful in 27s
CI/CD / test-python-dsms-gateway (push) Successful in 24s
CI/CD / deploy-hetzner (push) Has been cancelled
- Split HT-H01 into HT-H01a (B2C/Hybrid mit Verbraucherschutzpflichten) und HT-H01b (reiner B2B mit Basis-Pflichten). B2B-Webshops bekommen keine Widerrufsbelehrung/Preisangaben/Fernabsatz mehr. - Add excludeWhen/requireWhen to HardTriggerRule for conditional trigger logic - Register 6 neue ScopeDocumentType: widerrufsbelehrung, preisangaben, fernabsatz_info, streitbeilegung, produktsicherheit, ai_act_doku - Full DOCUMENT_SCOPE_MATRIX L1-L4 for all new types - Align HardTriggerRule interface with actual engine field names - Add Phase H (Verbraucherschutz) to RAG ingestion script: 10 deutsche Gesetze + 4 EU-Verordnungen + HLEG Ethics Guidelines - Add scripts/rag-sources.md with license documentation - 9 new tests for B2B/B2C trigger split, all 326 tests pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -370,3 +370,101 @@ describe('evaluateRiskFlags', () => {
|
||||
expect(orgFlag).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// HT-H01a/b: B2B vs B2C Webshop Trigger Split
|
||||
// ============================================================================
|
||||
|
||||
describe('HT-H01a/b — B2B vs B2C Webshop', () => {
|
||||
it('B2C webshop triggers HT-H01a with Verbraucherschutz documents', () => {
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', true),
|
||||
ans('org_business_model', 'B2C'),
|
||||
])
|
||||
const h01a = triggers.find((t: any) => t.ruleId === 'HT-H01a')
|
||||
const h01b = triggers.find((t: any) => t.ruleId === 'HT-H01b')
|
||||
expect(h01a).toBeDefined()
|
||||
expect(h01b).toBeUndefined()
|
||||
expect(h01a!.mandatoryDocuments).toContain('WIDERRUFSBELEHRUNG')
|
||||
expect(h01a!.mandatoryDocuments).toContain('PREISANGABEN')
|
||||
expect(h01a!.mandatoryDocuments).toContain('FERNABSATZ_INFO')
|
||||
expect(h01a!.mandatoryDocuments).toContain('STREITBEILEGUNG')
|
||||
})
|
||||
|
||||
it('B2B webshop triggers HT-H01b without Verbraucherschutz documents', () => {
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', true),
|
||||
ans('org_business_model', 'B2B'),
|
||||
])
|
||||
const h01a = triggers.find((t: any) => t.ruleId === 'HT-H01a')
|
||||
const h01b = triggers.find((t: any) => t.ruleId === 'HT-H01b')
|
||||
expect(h01a).toBeUndefined()
|
||||
expect(h01b).toBeDefined()
|
||||
expect(h01b!.mandatoryDocuments).toContain('DSE')
|
||||
expect(h01b!.mandatoryDocuments).toContain('AGB')
|
||||
expect(h01b!.mandatoryDocuments).toContain('COOKIE_BANNER')
|
||||
expect(h01b!.mandatoryDocuments).not.toContain('WIDERRUFSBELEHRUNG')
|
||||
expect(h01b!.mandatoryDocuments).not.toContain('PREISANGABEN')
|
||||
})
|
||||
|
||||
it('B2B_B2C (hybrid) webshop triggers HT-H01a (Verbraucherschutz applies)', () => {
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', true),
|
||||
ans('org_business_model', 'B2B_B2C'),
|
||||
])
|
||||
const h01a = triggers.find((t: any) => t.ruleId === 'HT-H01a')
|
||||
const h01b = triggers.find((t: any) => t.ruleId === 'HT-H01b')
|
||||
expect(h01a).toBeDefined()
|
||||
expect(h01b).toBeUndefined()
|
||||
})
|
||||
|
||||
it('no webshop → neither HT-H01a nor HT-H01b fires', () => {
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', false),
|
||||
ans('org_business_model', 'B2C'),
|
||||
])
|
||||
const h01a = triggers.find((t: any) => t.ruleId === 'HT-H01a')
|
||||
const h01b = triggers.find((t: any) => t.ruleId === 'HT-H01b')
|
||||
expect(h01a).toBeUndefined()
|
||||
expect(h01b).toBeUndefined()
|
||||
})
|
||||
|
||||
it('webshop without business_model answer → HT-H01a fires (excludeWhen not matched)', () => {
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', true),
|
||||
])
|
||||
const h01a = triggers.find((t: any) => t.ruleId === 'HT-H01a')
|
||||
const h01b = triggers.find((t: any) => t.ruleId === 'HT-H01b')
|
||||
// excludeWhen B2B: not matched (undefined !== 'B2B') → fires
|
||||
expect(h01a).toBeDefined()
|
||||
// requireWhen B2B: not matched (undefined !== 'B2B') → does not fire
|
||||
expect(h01b).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// excludeWhen / requireWhen Logic (unit)
|
||||
// ============================================================================
|
||||
|
||||
describe('excludeWhen / requireWhen — generic logic', () => {
|
||||
it('excludeWhen with array value excludes any matching value', () => {
|
||||
// HT-H01a has excludeWhen: { questionId: 'org_business_model', value: 'B2B' }
|
||||
// This test verifies the single-value case works (B2B excluded)
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', true),
|
||||
ans('org_business_model', 'B2B'),
|
||||
])
|
||||
const h01a = triggers.find((t: any) => t.ruleId === 'HT-H01a')
|
||||
expect(h01a).toBeUndefined()
|
||||
})
|
||||
|
||||
it('requireWhen with non-matching value prevents trigger', () => {
|
||||
// HT-H01b has requireWhen: { questionId: 'org_business_model', value: 'B2B' }
|
||||
const triggers = complianceScopeEngine.evaluateHardTriggers([
|
||||
ans('prod_webshop', true),
|
||||
ans('org_business_model', 'B2C'),
|
||||
])
|
||||
const h01b = triggers.find((t: any) => t.ruleId === 'HT-H01b')
|
||||
expect(h01b).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -642,16 +642,31 @@ export const HARD_TRIGGER_RULES: HardTriggerRule[] = [
|
||||
|
||||
// ========== H: Produkt/Business (7 rules) ==========
|
||||
{
|
||||
id: 'HT-H01',
|
||||
id: 'HT-H01a',
|
||||
category: 'product',
|
||||
questionId: 'prod_webshop',
|
||||
condition: 'EQUALS',
|
||||
conditionValue: true,
|
||||
excludeWhen: { questionId: 'org_business_model', value: 'B2B' },
|
||||
minimumLevel: 'L2',
|
||||
requiresDSFA: false,
|
||||
mandatoryDocuments: ['DSE', 'AGB', 'COOKIE_BANNER', 'EINWILLIGUNGEN', 'VERBRAUCHERSCHUTZ'],
|
||||
mandatoryDocuments: ['DSE', 'AGB', 'COOKIE_BANNER', 'EINWILLIGUNGEN',
|
||||
'WIDERRUFSBELEHRUNG', 'PREISANGABEN', 'FERNABSATZ_INFO', 'STREITBEILEGUNG'],
|
||||
legalReference: 'Art. 6 DSGVO + Fernabsatzrecht + PAngV + VSBG',
|
||||
description: 'E-Commerce / Webshop (B2C) — Verbraucherschutzpflichten',
|
||||
},
|
||||
{
|
||||
id: 'HT-H01b',
|
||||
category: 'product',
|
||||
questionId: 'prod_webshop',
|
||||
condition: 'EQUALS',
|
||||
conditionValue: true,
|
||||
requireWhen: { questionId: 'org_business_model', value: 'B2B' },
|
||||
minimumLevel: 'L2',
|
||||
requiresDSFA: false,
|
||||
mandatoryDocuments: ['DSE', 'AGB', 'COOKIE_BANNER'],
|
||||
legalReference: 'Art. 6 DSGVO + eCommerce',
|
||||
description: 'E-Commerce / Webshop-Betrieb',
|
||||
description: 'E-Commerce / Webshop (B2B) — Basis-Pflichten',
|
||||
},
|
||||
{
|
||||
id: 'HT-H02',
|
||||
@@ -1224,6 +1239,26 @@ export class ComplianceScopeEngine {
|
||||
|
||||
if (!baseCondition) return false
|
||||
|
||||
// Exclude-Bedingung: Regel feuert NICHT wenn excludeWhen zutrifft
|
||||
if (rule.excludeWhen) {
|
||||
const exVal = answerMap.get(rule.excludeWhen.questionId)
|
||||
if (Array.isArray(rule.excludeWhen.value)
|
||||
? rule.excludeWhen.value.includes(exVal)
|
||||
: exVal === rule.excludeWhen.value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Require-Bedingung: Regel feuert NUR wenn requireWhen zutrifft
|
||||
if (rule.requireWhen) {
|
||||
const reqVal = answerMap.get(rule.requireWhen.questionId)
|
||||
if (Array.isArray(rule.requireWhen.value)
|
||||
? !rule.requireWhen.value.includes(reqVal)
|
||||
: reqVal !== rule.requireWhen.value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Combined checks
|
||||
if (rule.combineWithArt9) {
|
||||
const art9 = answerMap.get('data_art9')
|
||||
@@ -1388,10 +1423,14 @@ export class ComplianceScopeEngine {
|
||||
NOTFALLPLAN: 12,
|
||||
COOKIE_BANNER: 4,
|
||||
AGB: 6,
|
||||
VERBRAUCHERSCHUTZ: 4,
|
||||
WIDERRUFSBELEHRUNG: 3,
|
||||
PREISANGABEN: 2,
|
||||
FERNABSATZ_INFO: 4,
|
||||
STREITBEILEGUNG: 1,
|
||||
PRODUKTSICHERHEIT: 8,
|
||||
AI_ACT_DOKU: 12,
|
||||
AUDIT_CHECKLIST: 8,
|
||||
VENDOR_MANAGEMENT: 10,
|
||||
AI_ACT_DOKU: 12,
|
||||
}
|
||||
return effortMap[docType] || 6
|
||||
}
|
||||
|
||||
@@ -130,24 +130,38 @@ export type HardTriggerOperator =
|
||||
export interface HardTriggerRule {
|
||||
/** Eindeutige ID der Regel */
|
||||
id: string;
|
||||
/** Kurze Bezeichnung */
|
||||
label: string;
|
||||
/** Detaillierte Beschreibung */
|
||||
description: string;
|
||||
/** Feld, das geprüft wird (questionId oder company_profile Feld) */
|
||||
conditionField: string;
|
||||
/** Kategorie der Regel */
|
||||
category: string;
|
||||
/** Frage-ID, die geprüft wird */
|
||||
questionId: string;
|
||||
/** Bedingungsoperator */
|
||||
conditionOperator: HardTriggerOperator;
|
||||
condition: HardTriggerOperator;
|
||||
/** Wert, der geprüft wird */
|
||||
conditionValue: unknown;
|
||||
/** Minimal erforderliches Level */
|
||||
minimumLevel: ComplianceDepthLevel;
|
||||
/** Pflichtdokumente bei Trigger */
|
||||
mandatoryDocuments: ScopeDocumentType[];
|
||||
/** DSFA erforderlich? */
|
||||
dsfaRequired: boolean;
|
||||
requiresDSFA: boolean;
|
||||
/** Pflichtdokumente bei Trigger */
|
||||
mandatoryDocuments: string[];
|
||||
/** Rechtsgrundlage */
|
||||
legalReference: string;
|
||||
/** Detaillierte Beschreibung */
|
||||
description: string;
|
||||
/** Kombiniert mit Art. 9 Daten? */
|
||||
combineWithArt9?: boolean;
|
||||
/** Kombiniert mit Minderjährigen-Daten? */
|
||||
combineWithMinors?: boolean;
|
||||
/** Kombiniert mit KI-Nutzung? */
|
||||
combineWithAI?: boolean;
|
||||
/** Kombiniert mit Mitarbeiterüberwachung? */
|
||||
combineWithEmployeeMonitoring?: boolean;
|
||||
/** Kombiniert mit automatisierter Entscheidungsfindung? */
|
||||
combineWithADM?: boolean;
|
||||
/** Regel feuert NICHT wenn diese Bedingung zutrifft */
|
||||
excludeWhen?: { questionId: string; value: string | string[] };
|
||||
/** Regel feuert NUR wenn diese Bedingung zutrifft */
|
||||
requireWhen?: { questionId: string; value: string | string[] };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +209,13 @@ export type ScopeDocumentType =
|
||||
| 'notfallplan' // Notfall- & Krisenplan
|
||||
| 'zertifizierung' // Zertifizierungsvorbereitung
|
||||
| 'datenschutzmanagement' // Datenschutzmanagement-System (DSMS)
|
||||
| 'iace_ce_assessment'; // CE-Risikobeurteilung SW/FW/KI (IACE)
|
||||
| 'iace_ce_assessment' // CE-Risikobeurteilung SW/FW/KI (IACE)
|
||||
| 'widerrufsbelehrung' // Widerrufsbelehrung (§ 312g BGB)
|
||||
| 'preisangaben' // Preisangaben (PAngV)
|
||||
| 'fernabsatz_info' // Informationspflichten Fernabsatz (§ 312d BGB)
|
||||
| 'streitbeilegung' // Streitbeilegungshinweis (VSBG § 36)
|
||||
| 'produktsicherheit' // Produktsicherheit (GPSR EU 2023/988)
|
||||
| 'ai_act_doku'; // AI Act Technische Dokumentation (Art. 11)
|
||||
|
||||
// ============================================================================
|
||||
// Decision & Output Types
|
||||
@@ -429,6 +449,12 @@ export const DOCUMENT_TYPE_LABELS: Record<ScopeDocumentType, string> = {
|
||||
zertifizierung: 'Zertifizierungsvorbereitung',
|
||||
datenschutzmanagement: 'Datenschutzmanagement-System (DSMS)',
|
||||
iace_ce_assessment: 'CE-Risikobeurteilung SW/FW/KI (IACE)',
|
||||
widerrufsbelehrung: 'Widerrufsbelehrung (§ 312g BGB)',
|
||||
preisangaben: 'Preisangaben (PAngV)',
|
||||
fernabsatz_info: 'Informationspflichten Fernabsatz (§ 312d BGB)',
|
||||
streitbeilegung: 'Streitbeilegungshinweis (VSBG § 36)',
|
||||
produktsicherheit: 'Produktsicherheitsdokumentation (GPSR)',
|
||||
ai_act_doku: 'AI Act Technische Dokumentation (Art. 11)',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1311,6 +1337,231 @@ export const DOCUMENT_SCOPE_MATRIX: Record<ScopeDocumentType, DocumentScopeRequi
|
||||
estimatedEffort: '24 Stunden',
|
||||
},
|
||||
},
|
||||
widerrufsbelehrung: {
|
||||
L1: {
|
||||
required: false,
|
||||
depth: 'Nicht relevant',
|
||||
detailItems: ['Nur bei B2C-Fernabsatz erforderlich'],
|
||||
estimatedEffort: '0',
|
||||
},
|
||||
L2: {
|
||||
required: true,
|
||||
depth: 'Standard',
|
||||
detailItems: [
|
||||
'Muster-Widerrufsbelehrung nach EGBGB Anlage 1',
|
||||
'Muster-Widerrufsformular nach EGBGB Anlage 2',
|
||||
'Integration in Bestellprozess',
|
||||
'14-Tage Widerrufsfrist korrekt dargestellt',
|
||||
],
|
||||
estimatedEffort: '2-4 Stunden',
|
||||
},
|
||||
L3: {
|
||||
required: true,
|
||||
depth: 'Erweitert',
|
||||
detailItems: [
|
||||
'Wie L2 + digitale Inhalte (§ 356 Abs. 5 BGB)',
|
||||
'Ausnahmen dokumentiert (§ 312g Abs. 2 BGB)',
|
||||
],
|
||||
estimatedEffort: '4-6 Stunden',
|
||||
},
|
||||
L4: {
|
||||
required: true,
|
||||
depth: 'Vollstaendig',
|
||||
detailItems: [
|
||||
'Wie L3 + automatisierte Pruefung',
|
||||
'Mehrsprachig bei EU-Verkauf',
|
||||
],
|
||||
estimatedEffort: '6-8 Stunden',
|
||||
},
|
||||
},
|
||||
preisangaben: {
|
||||
L1: {
|
||||
required: false,
|
||||
depth: 'Nicht relevant',
|
||||
detailItems: ['Nur bei B2C-Preisauszeichnung erforderlich'],
|
||||
estimatedEffort: '0',
|
||||
},
|
||||
L2: {
|
||||
required: true,
|
||||
depth: 'Standard',
|
||||
detailItems: [
|
||||
'Gesamtpreisangabe inkl. MwSt (§ 1 PAngV)',
|
||||
'Grundpreisangabe bei Mengenware (§ 4 PAngV)',
|
||||
'Versandkosten deutlich angegeben',
|
||||
],
|
||||
estimatedEffort: '2-3 Stunden',
|
||||
},
|
||||
L3: {
|
||||
required: true,
|
||||
depth: 'Erweitert',
|
||||
detailItems: [
|
||||
'Wie L2 + Preishistorie bei Rabattaktionen (Omnibus-RL)',
|
||||
'Streichpreise korrekt dargestellt',
|
||||
],
|
||||
estimatedEffort: '3-5 Stunden',
|
||||
},
|
||||
L4: {
|
||||
required: true,
|
||||
depth: 'Vollstaendig',
|
||||
detailItems: [
|
||||
'Wie L3 + automatisierte Pruefung',
|
||||
'Mehrwaehrungsunterstuetzung',
|
||||
],
|
||||
estimatedEffort: '5-8 Stunden',
|
||||
},
|
||||
},
|
||||
fernabsatz_info: {
|
||||
L1: {
|
||||
required: false,
|
||||
depth: 'Nicht relevant',
|
||||
detailItems: ['Nur bei Fernabsatzvertraegen erforderlich'],
|
||||
estimatedEffort: '0',
|
||||
},
|
||||
L2: {
|
||||
required: true,
|
||||
depth: 'Standard',
|
||||
detailItems: [
|
||||
'Pflichtinformationen nach § 312d BGB i.V.m. Art. 246a EGBGB',
|
||||
'Wesentliche Eigenschaften der Ware/Dienstleistung',
|
||||
'Identitaet und Anschrift des Unternehmers',
|
||||
'Zahlungs-, Liefer- und Leistungsbedingungen',
|
||||
],
|
||||
estimatedEffort: '3-5 Stunden',
|
||||
},
|
||||
L3: {
|
||||
required: true,
|
||||
depth: 'Erweitert',
|
||||
detailItems: [
|
||||
'Wie L2 + Informationen zu digitalen Inhalten/Diensten',
|
||||
'Funktionalitaet und Interoperabilitaet (§ 327 BGB)',
|
||||
],
|
||||
estimatedEffort: '5-8 Stunden',
|
||||
},
|
||||
L4: {
|
||||
required: true,
|
||||
depth: 'Vollstaendig',
|
||||
detailItems: [
|
||||
'Wie L3 + mehrsprachige Informationspflichten',
|
||||
'Automatisierte Vollstaendigkeitspruefung',
|
||||
],
|
||||
estimatedEffort: '8-12 Stunden',
|
||||
},
|
||||
},
|
||||
streitbeilegung: {
|
||||
L1: {
|
||||
required: false,
|
||||
depth: 'Nicht relevant',
|
||||
detailItems: ['Nur bei B2C-Handel erforderlich'],
|
||||
estimatedEffort: '0',
|
||||
},
|
||||
L2: {
|
||||
required: true,
|
||||
depth: 'Standard',
|
||||
detailItems: [
|
||||
'Hinweis auf OS-Plattform der EU-Kommission (Art. 14 ODR-VO)',
|
||||
'Erklaerung zur Teilnahmebereitschaft an Streitbeilegung (§ 36 VSBG)',
|
||||
'Link zur OS-Plattform im Impressum/AGB',
|
||||
],
|
||||
estimatedEffort: '1-2 Stunden',
|
||||
},
|
||||
L3: {
|
||||
required: true,
|
||||
depth: 'Erweitert',
|
||||
detailItems: [
|
||||
'Wie L2 + Benennung zustaendiger Verbraucherschlichtungsstelle',
|
||||
'Prozess fuer Streitbeilegungsanfragen dokumentiert',
|
||||
],
|
||||
estimatedEffort: '2-3 Stunden',
|
||||
},
|
||||
L4: {
|
||||
required: true,
|
||||
depth: 'Vollstaendig',
|
||||
detailItems: [
|
||||
'Wie L3 + Eskalationsprozess dokumentiert',
|
||||
'Regelmaessige Auswertung von Beschwerden',
|
||||
],
|
||||
estimatedEffort: '3-4 Stunden',
|
||||
},
|
||||
},
|
||||
produktsicherheit: {
|
||||
L1: {
|
||||
required: false,
|
||||
depth: 'Minimal',
|
||||
detailItems: ['Grundlegende Produktkennzeichnung pruefen'],
|
||||
estimatedEffort: '1 Stunde',
|
||||
},
|
||||
L2: {
|
||||
required: true,
|
||||
depth: 'Standard',
|
||||
detailItems: [
|
||||
'Produktsicherheitsbewertung nach GPSR (EU 2023/988)',
|
||||
'CE-Kennzeichnung und Konformitaetserklaerung',
|
||||
'Wirtschaftsakteur-Angaben auf Produkt/Verpackung',
|
||||
'Technische Dokumentation fuer Marktaufsicht',
|
||||
],
|
||||
estimatedEffort: '8-12 Stunden',
|
||||
},
|
||||
L3: {
|
||||
required: true,
|
||||
depth: 'Erweitert',
|
||||
detailItems: [
|
||||
'Wie L2 + Risikoanalyse fuer alle Produktvarianten',
|
||||
'Rueckrufplan und Marktbeobachtungspflichten',
|
||||
'Supply-Chain-Dokumentation',
|
||||
],
|
||||
estimatedEffort: '16-24 Stunden',
|
||||
},
|
||||
L4: {
|
||||
required: true,
|
||||
depth: 'Vollstaendig',
|
||||
detailItems: [
|
||||
'Wie L3 + vollstaendige GPSR-Konformitaetsakte',
|
||||
'Post-Market-Surveillance System',
|
||||
'Audit-Trail fuer alle Sicherheitsbewertungen',
|
||||
],
|
||||
estimatedEffort: '24-40 Stunden',
|
||||
},
|
||||
},
|
||||
ai_act_doku: {
|
||||
L1: {
|
||||
required: false,
|
||||
depth: 'Minimal',
|
||||
detailItems: ['KI-Risikokategorisierung (Art. 6 AI Act)'],
|
||||
estimatedEffort: '2 Stunden',
|
||||
},
|
||||
L2: {
|
||||
required: true,
|
||||
depth: 'Standard',
|
||||
detailItems: [
|
||||
'Technische Dokumentation nach Art. 11 AI Act',
|
||||
'Transparenzpflichten (Art. 52 AI Act)',
|
||||
'Risikomanagement-Grundlagen (Art. 9 AI Act)',
|
||||
'Menschliche Aufsicht dokumentiert (Art. 14 AI Act)',
|
||||
],
|
||||
estimatedEffort: '8-12 Stunden',
|
||||
},
|
||||
L3: {
|
||||
required: true,
|
||||
depth: 'Erweitert',
|
||||
detailItems: [
|
||||
'Wie L2 + Datenqualitaetsmanagement (Art. 10 AI Act)',
|
||||
'Genauigkeits- und Robustheitstests (Art. 15 AI Act)',
|
||||
'Vollstaendige Konformitaetsbewertung fuer Hochrisiko-KI',
|
||||
],
|
||||
estimatedEffort: '16-24 Stunden',
|
||||
},
|
||||
L4: {
|
||||
required: true,
|
||||
depth: 'Audit-Ready',
|
||||
detailItems: [
|
||||
'Wie L3 + Zertifizierungsfertige AI Act Dokumentation',
|
||||
'EU-Datenbank-Registrierung (Art. 60 AI Act)',
|
||||
'Post-Market Monitoring fuer KI-Systeme',
|
||||
'Continuous Compliance Framework fuer KI',
|
||||
],
|
||||
estimatedEffort: '24-40 Stunden',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@@ -1339,6 +1590,12 @@ export const DOCUMENT_SDK_STEP_MAP: Partial<Record<ScopeDocumentType, string>> =
|
||||
zertifizierung: '/sdk/iace',
|
||||
datenschutzmanagement: '/sdk/dsms',
|
||||
iace_ce_assessment: '/sdk/iace',
|
||||
widerrufsbelehrung: '/sdk/policy-generator',
|
||||
preisangaben: '/sdk/policy-generator',
|
||||
fernabsatz_info: '/sdk/policy-generator',
|
||||
streitbeilegung: '/sdk/policy-generator',
|
||||
produktsicherheit: '/sdk/iace',
|
||||
ai_act_doku: '/sdk/ai-act',
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -35,7 +35,7 @@ while [[ $# -gt 0 ]]; do
|
||||
--only) ONLY_PHASE="$2"; shift 2 ;;
|
||||
-h|--help)
|
||||
echo "Usage: $0 [--skip-download] [--only PHASE]"
|
||||
echo "Phases: download, gesetze, eu, templates, datenschutz, verify, version"
|
||||
echo "Phases: download, gesetze, eu, templates, datenschutz, verbraucherschutz, verify, version"
|
||||
exit 0
|
||||
;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
@@ -762,6 +762,148 @@ phase_datenschutz() {
|
||||
log "Collection $col: $before → $after chunks"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# PHASE H: Verbraucherschutz & AI Act
|
||||
# =============================================================================
|
||||
phase_verbraucherschutz() {
|
||||
log "=========================================="
|
||||
log "PHASE H: Verbraucherschutz & AI Act"
|
||||
log "=========================================="
|
||||
|
||||
mkdir -p "$WORK_DIR"/{pdfs,texts}
|
||||
|
||||
# --- H1: Deutsche Verbraucherschutz-Gesetze → bp_compliance_gesetze ---
|
||||
local col="bp_compliance_gesetze"
|
||||
local before
|
||||
before=$(collection_count "$col")
|
||||
log "Collection $col: $before chunks (before)"
|
||||
|
||||
# Download + Ingest deutsche Gesetze (gesetze-im-internet.de, Public Domain § 5 UrhG)
|
||||
local -a verbraucherschutz_gesetze=(
|
||||
"pangv_2022/PAngV:PAngV:Preisangabenverordnung"
|
||||
"vsbg/VSBG:VSBG:Verbraucherstreitbeilegungsgesetz"
|
||||
"prodhaftg/ProdHaftG:ProdHaftG:Produkthaftungsgesetz"
|
||||
"verpackg/VerpackG:VerpackG:Verpackungsgesetz"
|
||||
"elektrog_2015/ElektroG:ElektroG:Elektro- und Elektronikgeraetegesetz"
|
||||
"battdg/BattDG:BattDG:Batteriegesetz"
|
||||
"bfsg/BFSG:BFSG:Barrierefreiheitsstaerkungsgesetz"
|
||||
"uwg_2004/UWG:UWG:Gesetz gegen den unlauteren Wettbewerb"
|
||||
)
|
||||
|
||||
for entry in "${verbraucherschutz_gesetze[@]}"; do
|
||||
local path="${entry%%:*}"
|
||||
local rest="${entry#*:}"
|
||||
local short="${rest%%:*}"
|
||||
local fullname="${rest#*:}"
|
||||
local pdf_file="$WORK_DIR/pdfs/${short}.pdf"
|
||||
|
||||
download_pdf \
|
||||
"https://www.gesetze-im-internet.de/${path}.pdf" \
|
||||
"$pdf_file"
|
||||
|
||||
if [[ -f "$pdf_file" ]]; then
|
||||
upload_file "$pdf_file" "$col" "compliance" "legal_reference" "2025" \
|
||||
"{\"regulation_id\":\"${short,,}\",\"regulation_name_de\":\"$fullname ($short)\",\"category\":\"verbraucherschutz\",\"license\":\"public_domain_§5_UrhG\",\"source\":\"gesetze-im-internet.de\"}" \
|
||||
"$short ($fullname)"
|
||||
fi
|
||||
done
|
||||
|
||||
# BGB komplett (Fernabsatz §§ 312-312k, Digitale Inhalte §§ 327-327u, Kaufrecht §§ 433-480)
|
||||
download_pdf \
|
||||
"https://www.gesetze-im-internet.de/bgb/BGB.pdf" \
|
||||
"$WORK_DIR/pdfs/BGB_full.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/BGB_full.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/BGB_full.pdf" "$col" "compliance" "legal_reference" "2025" \
|
||||
'{"regulation_id":"bgb_fernabsatz","regulation_name_de":"BGB (Fernabsatz, Digitale Inhalte, Kaufrecht)","category":"verbraucherschutz","license":"public_domain_§5_UrhG","source":"gesetze-im-internet.de"}' \
|
||||
"BGB (Fernabsatz/Digitale Inhalte/Kaufrecht)"
|
||||
fi
|
||||
|
||||
# EGBGB fuer Muster-Widerrufsbelehrung (Anlage 1+2 zu Art. 246a)
|
||||
download_pdf \
|
||||
"https://www.gesetze-im-internet.de/bgbeg/BGBEG.pdf" \
|
||||
"$WORK_DIR/pdfs/BGBEG.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/BGBEG.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/BGBEG.pdf" "$col" "compliance" "legal_reference" "2025" \
|
||||
'{"regulation_id":"egbgb_muster_widerruf","regulation_name_de":"EGBGB (Muster-Widerrufsbelehrung, Anlage 1+2 zu Art. 246a)","category":"verbraucherschutz","license":"public_domain_§5_UrhG","source":"gesetze-im-internet.de"}' \
|
||||
"EGBGB (Muster-Widerrufsbelehrung)"
|
||||
fi
|
||||
|
||||
local after
|
||||
after=$(collection_count "$col")
|
||||
log "Collection $col: $before → $after chunks"
|
||||
|
||||
# --- H2: EU-Verordnungen → bp_compliance_ce ---
|
||||
col="bp_compliance_ce"
|
||||
before=$(collection_count "$col")
|
||||
log "Collection $col: $before chunks (before)"
|
||||
|
||||
# GPSR (EU 2023/988) - Produktsicherheit
|
||||
download_pdf \
|
||||
"https://eur-lex.europa.eu/legal-content/DE/TXT/PDF/?uri=CELEX:32023R0988" \
|
||||
"$WORK_DIR/pdfs/GPSR_2023_988.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/GPSR_2023_988.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/GPSR_2023_988.pdf" "$col" "compliance_ce" "legal_reference" "2024" \
|
||||
'{"regulation_id":"gpsr","regulation_name_de":"Allgemeine Produktsicherheitsverordnung (GPSR)","regulation_name_en":"General Product Safety Regulation","regulation_short":"GPSR","celex":"32023R0988","category":"produktsicherheit","license":"CC_BY_4.0","source":"eur-lex"}' \
|
||||
"GPSR (EU) 2023/988"
|
||||
fi
|
||||
|
||||
# AI Act (EU 2024/1689)
|
||||
download_pdf \
|
||||
"https://eur-lex.europa.eu/legal-content/DE/TXT/PDF/?uri=OJ:L_202401689" \
|
||||
"$WORK_DIR/pdfs/AI_Act_2024_1689.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/AI_Act_2024_1689.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/AI_Act_2024_1689.pdf" "$col" "compliance_ce" "legal_reference" "2024" \
|
||||
'{"regulation_id":"ai_act","regulation_name_de":"KI-Verordnung (AI Act)","regulation_name_en":"Artificial Intelligence Act","regulation_short":"AI Act","celex":"32024R1689","category":"ki_regulierung","license":"CC_BY_4.0","source":"eur-lex"}' \
|
||||
"AI Act (EU) 2024/1689"
|
||||
fi
|
||||
|
||||
# EU Batterieverordnung (EU 2023/1542)
|
||||
download_pdf \
|
||||
"https://eur-lex.europa.eu/legal-content/DE/TXT/PDF/?uri=CELEX:32023R1542" \
|
||||
"$WORK_DIR/pdfs/Batterie_VO_2023_1542.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/Batterie_VO_2023_1542.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/Batterie_VO_2023_1542.pdf" "$col" "compliance_ce" "legal_reference" "2024" \
|
||||
'{"regulation_id":"batterie_vo","regulation_name_de":"Batterieverordnung","regulation_name_en":"Battery Regulation","regulation_short":"BattVO","celex":"32023R1542","category":"produktsicherheit","license":"CC_BY_4.0","source":"eur-lex"}' \
|
||||
"EU Batterieverordnung (EU) 2023/1542"
|
||||
fi
|
||||
|
||||
# Digitale-Inhalte-Richtlinie (EU 2019/770)
|
||||
download_pdf \
|
||||
"https://eur-lex.europa.eu/legal-content/DE/TXT/PDF/?uri=CELEX:32019L0770" \
|
||||
"$WORK_DIR/pdfs/Digitale_Inhalte_RL_2019_770.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/Digitale_Inhalte_RL_2019_770.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/Digitale_Inhalte_RL_2019_770.pdf" "$col" "compliance_ce" "legal_reference" "2019" \
|
||||
'{"regulation_id":"digitale_inhalte_rl","regulation_name_de":"Richtlinie ueber digitale Inhalte","regulation_name_en":"Digital Content Directive","regulation_short":"DCD","celex":"32019L0770","category":"verbraucherschutz","license":"CC_BY_4.0","source":"eur-lex"}' \
|
||||
"Digitale-Inhalte-RL (EU) 2019/770"
|
||||
fi
|
||||
|
||||
after=$(collection_count "$col")
|
||||
log "Collection $col: $before → $after chunks"
|
||||
|
||||
# --- H3: HLEG Ethics Guidelines → bp_compliance_datenschutz ---
|
||||
col="bp_compliance_datenschutz"
|
||||
before=$(collection_count "$col")
|
||||
|
||||
download_pdf \
|
||||
"https://op.europa.eu/en/publication-detail/-/publication/d3988569-0434-11ea-8c1f-01aa75ed71a1/language-en/format-PDF" \
|
||||
"$WORK_DIR/pdfs/hleg_trustworthy_ai.pdf"
|
||||
|
||||
if [[ -f "$WORK_DIR/pdfs/hleg_trustworthy_ai.pdf" ]]; then
|
||||
upload_file "$WORK_DIR/pdfs/hleg_trustworthy_ai.pdf" "$col" "compliance_datenschutz" "guidance" "2019" \
|
||||
'{"source_id":"hleg","doc_type":"ethics_guidelines","guideline_name":"Ethics Guidelines for Trustworthy AI","license":"CC_BY_4.0","attribution":"High-Level Expert Group on AI (HLEG)","source":"op.europa.eu"}' \
|
||||
"HLEG Ethics Guidelines Trustworthy AI"
|
||||
fi
|
||||
|
||||
after=$(collection_count "$col")
|
||||
log "Collection $col: $before → $after chunks"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# PHASE F: Verifizierung
|
||||
# =============================================================================
|
||||
@@ -809,6 +951,36 @@ try:
|
||||
for r in results[:3]:
|
||||
print(f' [{r.get(\"score\",0):.3f}] {r.get(\"regulation_code\",\"?\")} - {r.get(\"content\",\"\")[:80]}...')
|
||||
except: print(' (parse error)')
|
||||
" 2>/dev/null || echo " (search failed)"
|
||||
|
||||
log "Suche: 'Widerrufsbelehrung Fernabsatz' in bp_compliance_gesetze"
|
||||
curl $CURL_OPTS -X POST "https://localhost:8097/api/v1/search" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"query":"Widerrufsbelehrung Fernabsatz Widerrufsfrist","regulation_codes":null,"limit":3,"min_score":0.5}' 2>/dev/null \
|
||||
| python3 -c "
|
||||
import sys,json
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
results = data.get('results', [])
|
||||
print(f' Treffer: {len(results)}')
|
||||
for r in results[:3]:
|
||||
print(f' [{r.get(\"score\",0):.3f}] {r.get(\"regulation_code\",\"?\")} - {r.get(\"content\",\"\")[:80]}...')
|
||||
except: print(' (parse error)')
|
||||
" 2>/dev/null || echo " (search failed)"
|
||||
|
||||
log "Suche: 'AI Act Hochrisiko Konformitaet' in bp_compliance_ce"
|
||||
curl $CURL_OPTS -X POST "https://localhost:8097/api/v1/search" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"query":"AI Act Hochrisiko Konformitaetsbewertung","regulation_codes":null,"limit":3,"min_score":0.5}' 2>/dev/null \
|
||||
| python3 -c "
|
||||
import sys,json
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
results = data.get('results', [])
|
||||
print(f' Treffer: {len(results)}')
|
||||
for r in results[:3]:
|
||||
print(f' [{r.get(\"score\",0):.3f}] {r.get(\"regulation_code\",\"?\")} - {r.get(\"content\",\"\")[:80]}...')
|
||||
except: print(' (parse error)')
|
||||
" 2>/dev/null || echo " (search failed)"
|
||||
|
||||
log "Suche: 'Privacy Policy Template GDPR' in bp_legal_templates"
|
||||
@@ -925,9 +1097,10 @@ main() {
|
||||
gesetze) phase_gesetze ;;
|
||||
eu) phase_eu ;;
|
||||
templates) phase_templates ;;
|
||||
datenschutz) phase_datenschutz ;;
|
||||
verify) phase_verify ;;
|
||||
version) phase_register_version ;;
|
||||
datenschutz) phase_datenschutz ;;
|
||||
verbraucherschutz) phase_verbraucherschutz ;;
|
||||
verify) phase_verify ;;
|
||||
version) phase_register_version ;;
|
||||
*) fail "Unknown phase: $ONLY_PHASE"; exit 1 ;;
|
||||
esac
|
||||
else
|
||||
@@ -945,6 +1118,8 @@ main() {
|
||||
echo ""
|
||||
phase_datenschutz
|
||||
echo ""
|
||||
phase_verbraucherschutz
|
||||
echo ""
|
||||
phase_verify
|
||||
echo ""
|
||||
phase_register_version
|
||||
|
||||
77
scripts/rag-sources.md
Normal file
77
scripts/rag-sources.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# RAG-Quellennachweis — BreakPilot Compliance
|
||||
|
||||
Stand: 2026-03-11
|
||||
|
||||
## Collection: bp_compliance_gesetze
|
||||
|
||||
| # | Dokument | Quelle | Lizenz |
|
||||
|---|----------|--------|--------|
|
||||
| 1 | DDG § 5 (Impressum) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 2 | TDDDG § 25 (Cookies) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 3 | UrhG § 5 (Amtliche Werke) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 4 | EGBGB Muster-Widerrufsbelehrung | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 5 | BGB (komplett) | github.com/bundestag/gesetze | Unlicense |
|
||||
| 6 | UrhG (komplett) | github.com/bundestag/gesetze | Unlicense |
|
||||
| 7 | TMG (komplett) | github.com/bundestag/gesetze | Unlicense |
|
||||
| 8 | PAngV (Preisangabenverordnung) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 9 | VSBG (Verbraucherstreitbeilegungsgesetz) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 10 | ProdHaftG (Produkthaftungsgesetz) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 11 | VerpackG (Verpackungsgesetz) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 12 | ElektroG (WEEE) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 13 | BattDG (Batterierecht) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 14 | BFSG (Barrierefreiheit) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 15 | UWG (Unlauterer Wettbewerb) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 16 | BGB (Fernabsatz/Digitale Inhalte/Kaufrecht) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
| 17 | EGBGB (Muster-Widerrufsbelehrung Anlage 1+2) | gesetze-im-internet.de | Public Domain (§ 5 UrhG) |
|
||||
|
||||
## Collection: bp_compliance_ce
|
||||
|
||||
| # | Dokument | Quelle | Lizenz |
|
||||
|---|----------|--------|--------|
|
||||
| 1 | Digital Services Act (EU) 2022/2065 | eur-lex.europa.eu | CC BY 4.0 |
|
||||
| 2 | ePrivacy-Richtlinie 2002/58/EC | eur-lex.europa.eu | CC BY 4.0 |
|
||||
| 3 | Standardvertragsklauseln (EU) 2021/914 | eur-lex.europa.eu | CC BY 4.0 |
|
||||
| 4 | GPSR (EU) 2023/988 | eur-lex.europa.eu | CC BY 4.0 |
|
||||
| 5 | AI Act (EU) 2024/1689 | eur-lex.europa.eu | CC BY 4.0 |
|
||||
| 6 | Batterieverordnung (EU) 2023/1542 | eur-lex.europa.eu | CC BY 4.0 |
|
||||
| 7 | Digitale-Inhalte-RL (EU) 2019/770 | eur-lex.europa.eu | CC BY 4.0 |
|
||||
|
||||
## Collection: bp_legal_templates
|
||||
|
||||
| # | Dokument | Quelle | Lizenz |
|
||||
|---|----------|--------|--------|
|
||||
| 1 | GitHub Site Policy | github.com/github/site-policy | CC0 |
|
||||
| 2 | OpenGov Site Policy | github.com/opengovfoundation/site-policy | CC0 |
|
||||
| 3 | CC Legal Tools | github.com/creativecommons/cc-legal-tools-data | CC0 |
|
||||
| 4 | opr.vc DSGVO-Mustertexte | github.com/oprvc/oprvc.github.io | CC0 |
|
||||
| 5 | webflorist Privacy Policy Text | github.com/webflorist/privacy-policy-text | MIT |
|
||||
| 6 | Tempest Privacy Policy Generator | github.com/Tempest-Solutions-Company | MIT |
|
||||
| 7 | Tempest Terms of Service Generator | github.com/Tempest-Solutions-Company | MIT |
|
||||
| 8 | Tempest Cookie Banner | github.com/Tempest-Solutions-Company | MIT |
|
||||
| 9 | CookieConsent (orestbida) | github.com/orestbida/cookieconsent | MIT |
|
||||
| 10 | CommonPaper CSA/SLA/PSA | github.com/CommonPaper | CC BY 4.0 |
|
||||
| 11 | Datennutzungsklauseln | gitlab.opencode.de/wernerth | CC BY 4.0 |
|
||||
|
||||
## Collection: bp_compliance_datenschutz
|
||||
|
||||
| # | Dokument | Quelle | Lizenz |
|
||||
|---|----------|--------|--------|
|
||||
| 1 | EDPB Guidelines 05/2020 Consent | edpb.europa.eu | Reuse Notice |
|
||||
| 2 | EDPB Guidelines 4/2019 Privacy by Design | edpb.europa.eu | Reuse Notice |
|
||||
| 3 | EDPB Guidelines 03/2022 Dark Patterns | edpb.europa.eu | Reuse Notice |
|
||||
| 4 | EDPB Guidelines 8/2020 Social Media Targeting | edpb.europa.eu | Reuse Notice |
|
||||
| 5 | EDPB Cookie Banner Taskforce Report 2023 | edpb.europa.eu | Reuse Notice |
|
||||
| 6 | EDPB Guidelines 2/2023 ePrivacy Art. 5(3) | edpb.europa.eu | Reuse Notice |
|
||||
| 7 | EDPB Guidelines 1/2024 Legitimate Interest | edpb.europa.eu | Reuse Notice |
|
||||
| 8 | EDPB DPO Enforcement Report 2024 | edpb.europa.eu | Reuse Notice |
|
||||
| 9 | EDPS GenAI Orientations 2024 | edps.europa.eu | Reuse Notice |
|
||||
| 10 | EDPS Digital Ethics Report 2018 | edps.europa.eu | Reuse Notice |
|
||||
| 11 | HLEG Ethics Guidelines Trustworthy AI | op.europa.eu | CC BY 4.0 |
|
||||
|
||||
## Lizenz-Hinweise
|
||||
|
||||
- **Public Domain (§ 5 UrhG):** Deutsche amtliche Werke (Gesetze, Verordnungen) sind gemeinfrei.
|
||||
- **CC BY 4.0:** EU-Rechtstexte und EU-Publikationen. Attribution: "European Union, https://eur-lex.europa.eu"
|
||||
- **CC0:** Public-Domain-Widmung, keine Einschraenkungen.
|
||||
- **MIT:** Permissive Open-Source-Lizenz, kommerzielle Nutzung erlaubt.
|
||||
- **Reuse Notice:** EDPB/EDPS-Dokumente duerfen unter Quellenangabe wiederverwendet werden.
|
||||
Reference in New Issue
Block a user