feat: Legal Templates Service — eigene Vorlagen für Dokumentengenerator
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 37s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 18s

Implementiert MIT-lizenzierte DSGVO-Templates (DSE, Impressum, AGB) in
der eigenen PostgreSQL-Datenbank statt KLAUSUR_SERVICE-Abhängigkeit.

- Migration 018: compliance_legal_templates Tabelle + 3 Seed-Templates
- Routes: GET/POST/PUT/DELETE /legal-templates + /status + /sources
- Registriert im bestehenden compliance catch-all Proxy (kein neuer Proxy)
- searchTemplates.ts: eigenes Backend als Primary, RAG bleibt Fallback
- ServiceMode-Banner: KLAUSUR_SERVICE-Referenz entfernt
- Tests: 25 Python + 3 Vitest — alle grün

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-03 23:12:07 +01:00
parent 29e6998a28
commit f909182632
8 changed files with 1079 additions and 93 deletions

View File

@@ -1,49 +1,51 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { searchTemplates } from './searchTemplates'
// jsdom doesn't define window.location.origin — stub it
Object.defineProperty(window, 'location', {
value: { origin: 'https://localhost' },
writable: true,
})
describe('searchTemplates', () => {
beforeEach(() => {
vi.restoreAllMocks()
})
it('gibt Ergebnisse zurück wenn KLAUSUR_SERVICE verfügbar', async () => {
it('gibt Ergebnisse zurück wenn eigenes Backend verfügbar', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve([{
id: 't1',
score: 0.9,
text: 'Inhalt',
document_title: 'DSE Template',
template_type: 'privacy_policy',
clause_category: null,
language: 'de',
jurisdiction: 'de',
license_id: 'mit',
license_name: 'MIT',
license_url: null,
attribution_required: false,
attribution_text: null,
source_name: 'Test',
source_url: null,
source_repo: null,
placeholders: [],
is_complete_document: true,
is_modular: false,
requires_customization: false,
output_allowed: true,
modification_allowed: true,
distortion_prohibited: false,
}]),
json: () => Promise.resolve({
templates: [{
id: 't1',
title: 'Datenschutzerklärung (DSGVO-konform)',
document_type: 'privacy_policy',
content: '# Datenschutzerklärung\n\n{{COMPANY_NAME}}',
description: 'Vollständige DSE',
language: 'de',
jurisdiction: 'DE',
license_id: 'mit',
license_name: 'MIT License',
source_name: 'BreakPilot Compliance',
attribution_required: false,
is_complete_document: true,
placeholders: ['{{COMPANY_NAME}}', '{{CONTACT_EMAIL}}'],
}],
total: 1,
}),
}))
const results = await searchTemplates({ query: 'Datenschutzerklärung' })
expect(results).toHaveLength(1)
expect(results[0].documentTitle).toBe('DSE Template')
expect(results[0].documentTitle).toBe('Datenschutzerklärung (DSGVO-konform)')
expect(results[0].templateType).toBe('privacy_policy')
expect(results[0].placeholders).toContain('{{COMPANY_NAME}}')
expect((results[0] as any).source).toBe('db')
})
it('fällt auf RAG zurück wenn KLAUSUR_SERVICE fehlschlägt', async () => {
it('fällt auf RAG zurück wenn Backend fehlschlägt', async () => {
vi.stubGlobal('fetch', vi.fn()
.mockRejectedValueOnce(new Error('KLAUSUR down'))
.mockRejectedValueOnce(new Error('Backend down'))
.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({