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()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user