test+docs: add policy library tests (67 tests) and MKDocs documentation
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 23s
CI/CD / test-python-dsms-gateway (push) Successful in 19s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s

- New test_policy_templates.py: 67 tests covering all 29 policy types,
  API creation, filtering, placeholders, seed script validation
- Updated test_legal_template_routes.py: fix type count 16→52
- New MKDocs page policy-bibliothek.md with full template reference
- Updated dokumentengenerierung.md and rechtliche-texte.md with cross-refs
- Added policy-bibliothek to mkdocs.yml navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-14 22:50:50 +01:00
parent 0171d611f6
commit a9f291ff49
6 changed files with 838 additions and 5 deletions

View File

@@ -121,7 +121,7 @@ class TestLegalTemplateSchemas:
assert d == {"status": "archived", "title": "Neue DSE"}
def test_valid_document_types_constant(self):
"""VALID_DOCUMENT_TYPES contains all 16 expected types (post-Migration 020)."""
"""VALID_DOCUMENT_TYPES contains all 52 expected types (Migration 020+051+054)."""
# Original types
assert "privacy_policy" in VALID_DOCUMENT_TYPES
assert "terms_of_service" in VALID_DOCUMENT_TYPES
@@ -141,7 +141,20 @@ class TestLegalTemplateSchemas:
assert "cookie_banner" in VALID_DOCUMENT_TYPES
assert "agb" in VALID_DOCUMENT_TYPES
assert "clause" in VALID_DOCUMENT_TYPES
assert len(VALID_DOCUMENT_TYPES) == 16
# Security concepts (Migration 051)
assert "it_security_concept" in VALID_DOCUMENT_TYPES
assert "data_protection_concept" in VALID_DOCUMENT_TYPES
assert "backup_recovery_concept" in VALID_DOCUMENT_TYPES
assert "logging_concept" in VALID_DOCUMENT_TYPES
assert "incident_response_plan" in VALID_DOCUMENT_TYPES
assert "access_control_concept" in VALID_DOCUMENT_TYPES
assert "risk_management_concept" in VALID_DOCUMENT_TYPES
# Policy templates (Migration 054) — spot check
assert "information_security_policy" in VALID_DOCUMENT_TYPES
assert "data_protection_policy" in VALID_DOCUMENT_TYPES
assert "business_continuity_policy" in VALID_DOCUMENT_TYPES
# Total: 16 original + 7 security concepts + 29 policies = 52
assert len(VALID_DOCUMENT_TYPES) == 52
# Old names must NOT be present after rename
assert "data_processing_agreement" not in VALID_DOCUMENT_TYPES
assert "withdrawal_policy" not in VALID_DOCUMENT_TYPES
@@ -488,9 +501,9 @@ class TestLegalTemplateSeed:
class TestLegalTemplateNewTypes:
"""Validate new document types added in Migration 020."""
def test_all_16_types_present(self):
"""VALID_DOCUMENT_TYPES has exactly 16 entries."""
assert len(VALID_DOCUMENT_TYPES) == 16
def test_all_52_types_present(self):
"""VALID_DOCUMENT_TYPES has exactly 52 entries (16 + 7 security + 29 policies)."""
assert len(VALID_DOCUMENT_TYPES) == 52
def test_new_types_are_valid(self):
"""All Migration 020 new types are accepted."""

View File

@@ -0,0 +1,580 @@
"""Tests for policy template types (Migration 054) — 29 policy templates."""
import pytest
from unittest.mock import MagicMock
from fastapi.testclient import TestClient
from fastapi import FastAPI
from datetime import datetime
from compliance.api.legal_template_routes import (
VALID_DOCUMENT_TYPES,
VALID_STATUSES,
router,
)
from compliance.api.db_utils import row_to_dict as _row_to_dict
from classroom_engine.database import get_db
from compliance.api.tenant_utils import get_tenant_id
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
# =============================================================================
# Test App Setup
# =============================================================================
app = FastAPI()
app.include_router(router)
mock_db = MagicMock()
def override_get_db():
yield mock_db
def override_tenant():
return DEFAULT_TENANT_ID
app.dependency_overrides[get_db] = override_get_db
app.dependency_overrides[get_tenant_id] = override_tenant
client = TestClient(app)
# =============================================================================
# Policy type constants (grouped by category)
# =============================================================================
IT_SECURITY_POLICIES = [
"information_security_policy",
"access_control_policy",
"password_policy",
"encryption_policy",
"logging_policy",
"backup_policy",
"incident_response_policy",
"change_management_policy",
"patch_management_policy",
"asset_management_policy",
"cloud_security_policy",
"devsecops_policy",
"secrets_management_policy",
"vulnerability_management_policy",
]
DATA_POLICIES = [
"data_protection_policy",
"data_classification_policy",
"data_retention_policy",
"data_transfer_policy",
"privacy_incident_policy",
]
PERSONNEL_POLICIES = [
"employee_security_policy",
"security_awareness_policy",
"remote_work_policy",
"offboarding_policy",
]
VENDOR_POLICIES = [
"vendor_risk_management_policy",
"third_party_security_policy",
"supplier_security_policy",
]
BCM_POLICIES = [
"business_continuity_policy",
"disaster_recovery_policy",
"crisis_management_policy",
]
ALL_POLICY_TYPES = (
IT_SECURITY_POLICIES
+ DATA_POLICIES
+ PERSONNEL_POLICIES
+ VENDOR_POLICIES
+ BCM_POLICIES
)
# =============================================================================
# Helpers
# =============================================================================
def make_policy_row(doc_type, title="Test Policy", content="# Test", **overrides):
data = {
"id": "policy-001",
"tenant_id": DEFAULT_TENANT_ID,
"document_type": doc_type,
"title": title,
"description": f"Test {doc_type}",
"content": content,
"placeholders": ["{{COMPANY_NAME}}", "{{SECURITY_OFFICER}}", "{{VERSION}}", "{{DATE}}"],
"language": "de",
"jurisdiction": "DE",
"status": "published",
"license_id": "mit",
"license_name": "MIT License",
"source_name": "BreakPilot Compliance",
"attribution_required": False,
"is_complete_document": True,
"version": "1.0.0",
"source_url": None,
"source_repo": None,
"source_file_path": None,
"source_retrieved_at": None,
"attribution_text": None,
"inspiration_sources": [],
"created_at": datetime(2026, 3, 14),
"updated_at": datetime(2026, 3, 14),
}
data.update(overrides)
row = MagicMock()
row._mapping = data
return row
# =============================================================================
# TestPolicyTypeValidation
# =============================================================================
class TestPolicyTypeValidation:
"""Verify all 29 policy types are accepted by VALID_DOCUMENT_TYPES."""
def test_all_29_policy_types_present(self):
"""All 29 policy types from Migration 054 are in VALID_DOCUMENT_TYPES."""
for doc_type in ALL_POLICY_TYPES:
assert doc_type in VALID_DOCUMENT_TYPES, (
f"Policy type '{doc_type}' missing from VALID_DOCUMENT_TYPES"
)
def test_policy_count(self):
"""There are exactly 29 policy template types."""
assert len(ALL_POLICY_TYPES) == 29
def test_it_security_policy_count(self):
"""IT Security category has 14 policy types."""
assert len(IT_SECURITY_POLICIES) == 14
def test_data_policy_count(self):
"""Data category has 5 policy types."""
assert len(DATA_POLICIES) == 5
def test_personnel_policy_count(self):
"""Personnel category has 4 policy types."""
assert len(PERSONNEL_POLICIES) == 4
def test_vendor_policy_count(self):
"""Vendor/Supply Chain category has 3 policy types."""
assert len(VENDOR_POLICIES) == 3
def test_bcm_policy_count(self):
"""BCM category has 3 policy types."""
assert len(BCM_POLICIES) == 3
def test_total_valid_types_count(self):
"""VALID_DOCUMENT_TYPES has 52 entries total (16 original + 7 security + 29 policies)."""
assert len(VALID_DOCUMENT_TYPES) == 52
def test_no_duplicate_policy_types(self):
"""No duplicate entries in the policy type lists."""
assert len(ALL_POLICY_TYPES) == len(set(ALL_POLICY_TYPES))
def test_policies_distinct_from_security_concepts(self):
"""Policy types are distinct from security concept types (Migration 051)."""
security_concepts = [
"it_security_concept", "data_protection_concept",
"backup_recovery_concept", "logging_concept",
"incident_response_plan", "access_control_concept",
"risk_management_concept",
]
for policy_type in ALL_POLICY_TYPES:
assert policy_type not in security_concepts, (
f"Policy type '{policy_type}' clashes with security concept"
)
# =============================================================================
# TestPolicyTemplateCreation
# =============================================================================
class TestPolicyTemplateCreation:
"""Test creating policy templates via API."""
def setup_method(self):
mock_db.reset_mock()
def test_create_information_security_policy(self):
"""POST /legal-templates accepts information_security_policy."""
row = make_policy_row("information_security_policy", "Informationssicherheits-Richtlinie")
mock_db.execute.return_value.fetchone.return_value = row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": "information_security_policy",
"title": "Informationssicherheits-Richtlinie",
"content": "# Informationssicherheits-Richtlinie\n\n## 1. Zweck",
})
assert resp.status_code == 201
def test_create_data_protection_policy(self):
"""POST /legal-templates accepts data_protection_policy."""
row = make_policy_row("data_protection_policy", "Datenschutz-Richtlinie")
mock_db.execute.return_value.fetchone.return_value = row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": "data_protection_policy",
"title": "Datenschutz-Richtlinie",
"content": "# Datenschutz-Richtlinie",
})
assert resp.status_code == 201
def test_create_business_continuity_policy(self):
"""POST /legal-templates accepts business_continuity_policy."""
row = make_policy_row("business_continuity_policy", "Business-Continuity-Richtlinie")
mock_db.execute.return_value.fetchone.return_value = row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": "business_continuity_policy",
"title": "Business-Continuity-Richtlinie",
"content": "# Business-Continuity-Richtlinie",
})
assert resp.status_code == 201
def test_create_vendor_risk_management_policy(self):
"""POST /legal-templates accepts vendor_risk_management_policy."""
row = make_policy_row("vendor_risk_management_policy", "Lieferanten-Risikomanagement")
mock_db.execute.return_value.fetchone.return_value = row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": "vendor_risk_management_policy",
"title": "Lieferanten-Risikomanagement-Richtlinie",
"content": "# Lieferanten-Risikomanagement",
})
assert resp.status_code == 201
def test_create_employee_security_policy(self):
"""POST /legal-templates accepts employee_security_policy."""
row = make_policy_row("employee_security_policy", "Mitarbeiter-Sicherheitsrichtlinie")
mock_db.execute.return_value.fetchone.return_value = row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": "employee_security_policy",
"title": "Mitarbeiter-Sicherheitsrichtlinie",
"content": "# Mitarbeiter-Sicherheitsrichtlinie",
})
assert resp.status_code == 201
@pytest.mark.parametrize("doc_type", ALL_POLICY_TYPES)
def test_all_policy_types_accepted_by_api(self, doc_type):
"""POST /legal-templates accepts every policy type (parametrized)."""
row = make_policy_row(doc_type)
mock_db.execute.return_value.fetchone.return_value = row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": doc_type,
"title": f"Test {doc_type}",
"content": f"# {doc_type}",
})
assert resp.status_code == 201, (
f"Expected 201 for {doc_type}, got {resp.status_code}: {resp.text}"
)
# =============================================================================
# TestPolicyTemplateFilter
# =============================================================================
class TestPolicyTemplateFilter:
"""Verify filtering templates by policy document types."""
def setup_method(self):
mock_db.reset_mock()
@pytest.mark.parametrize("doc_type", [
"information_security_policy",
"data_protection_policy",
"employee_security_policy",
"vendor_risk_management_policy",
"business_continuity_policy",
])
def test_filter_by_policy_type(self, doc_type):
"""GET /legal-templates?document_type={policy} returns 200."""
count_mock = MagicMock()
count_mock.__getitem__ = lambda self, i: 1
first_call = MagicMock()
first_call.fetchone.return_value = count_mock
second_call = MagicMock()
second_call.fetchall.return_value = [make_policy_row(doc_type)]
mock_db.execute.side_effect = [first_call, second_call]
resp = client.get(f"/legal-templates?document_type={doc_type}")
assert resp.status_code == 200
data = resp.json()
assert "templates" in data
# =============================================================================
# TestPolicyTemplatePlaceholders
# =============================================================================
class TestPolicyTemplatePlaceholders:
"""Verify placeholder structure for policy templates."""
def test_information_security_policy_placeholders(self):
"""Information security policy has standard placeholders."""
row = make_policy_row(
"information_security_policy",
placeholders=[
"{{COMPANY_NAME}}", "{{SECURITY_OFFICER}}",
"{{VERSION}}", "{{DATE}}",
"{{SCOPE_DESCRIPTION}}", "{{GF_NAME}}",
],
)
result = _row_to_dict(row)
assert "{{COMPANY_NAME}}" in result["placeholders"]
assert "{{SECURITY_OFFICER}}" in result["placeholders"]
assert "{{GF_NAME}}" in result["placeholders"]
def test_data_protection_policy_placeholders(self):
"""Data protection policy has DSB and DPO placeholders."""
row = make_policy_row(
"data_protection_policy",
placeholders=[
"{{COMPANY_NAME}}", "{{DSB_NAME}}",
"{{DSB_EMAIL}}", "{{VERSION}}", "{{DATE}}",
"{{GF_NAME}}", "{{SCOPE_DESCRIPTION}}",
],
)
result = _row_to_dict(row)
assert "{{DSB_NAME}}" in result["placeholders"]
assert "{{DSB_EMAIL}}" in result["placeholders"]
def test_password_policy_placeholders(self):
"""Password policy has complexity-related placeholders."""
row = make_policy_row(
"password_policy",
placeholders=[
"{{COMPANY_NAME}}", "{{SECURITY_OFFICER}}",
"{{VERSION}}", "{{DATE}}",
"{{MIN_PASSWORD_LENGTH}}", "{{MAX_AGE_DAYS}}",
"{{HISTORY_COUNT}}", "{{GF_NAME}}",
],
)
result = _row_to_dict(row)
assert "{{MIN_PASSWORD_LENGTH}}" in result["placeholders"]
assert "{{MAX_AGE_DAYS}}" in result["placeholders"]
def test_backup_policy_placeholders(self):
"""Backup policy has retention-related placeholders."""
row = make_policy_row(
"backup_policy",
placeholders=[
"{{COMPANY_NAME}}", "{{SECURITY_OFFICER}}",
"{{VERSION}}", "{{DATE}}",
"{{RPO_HOURS}}", "{{RTO_HOURS}}",
"{{BACKUP_RETENTION_DAYS}}", "{{GF_NAME}}",
],
)
result = _row_to_dict(row)
assert "{{RPO_HOURS}}" in result["placeholders"]
assert "{{RTO_HOURS}}" in result["placeholders"]
# =============================================================================
# TestPolicyTemplateStructure
# =============================================================================
class TestPolicyTemplateStructure:
"""Validate structural aspects of policy templates."""
def test_policy_uses_mit_license(self):
"""Policy templates use MIT license."""
row = make_policy_row("information_security_policy")
result = _row_to_dict(row)
assert result["license_id"] == "mit"
assert result["license_name"] == "MIT License"
assert result["attribution_required"] is False
def test_policy_language_de(self):
"""Policy templates default to German language."""
row = make_policy_row("access_control_policy")
result = _row_to_dict(row)
assert result["language"] == "de"
assert result["jurisdiction"] == "DE"
def test_policy_is_complete_document(self):
"""Policy templates are complete documents."""
row = make_policy_row("encryption_policy")
result = _row_to_dict(row)
assert result["is_complete_document"] is True
def test_policy_default_status_published(self):
"""Policy templates default to published status."""
row = make_policy_row("logging_policy")
result = _row_to_dict(row)
assert result["status"] == "published"
def test_policy_row_to_dict_datetime(self):
"""_row_to_dict converts datetime for policy rows."""
row = make_policy_row("patch_management_policy")
result = _row_to_dict(row)
assert result["created_at"] == "2026-03-14T00:00:00"
def test_policy_source_name(self):
"""Policy templates have BreakPilot Compliance as source."""
row = make_policy_row("cloud_security_policy")
result = _row_to_dict(row)
assert result["source_name"] == "BreakPilot Compliance"
# =============================================================================
# TestPolicyTemplateRejection
# =============================================================================
class TestPolicyTemplateRejection:
"""Verify invalid policy types are rejected."""
def setup_method(self):
mock_db.reset_mock()
def test_reject_fake_policy_type(self):
"""POST /legal-templates rejects non-existent policy type."""
resp = client.post("/legal-templates", json={
"document_type": "fake_security_policy",
"title": "Fake Policy",
"content": "# Fake",
})
assert resp.status_code == 400
assert "Invalid document_type" in resp.json()["detail"]
def test_reject_policy_with_typo(self):
"""POST /legal-templates rejects misspelled policy type."""
resp = client.post("/legal-templates", json={
"document_type": "informaton_security_policy",
"title": "Typo Policy",
"content": "# Typo",
})
assert resp.status_code == 400
def test_reject_policy_with_invalid_status(self):
"""POST /legal-templates rejects invalid status for policy."""
resp = client.post("/legal-templates", json={
"document_type": "password_policy",
"title": "Password Policy",
"content": "# Password",
"status": "active",
})
assert resp.status_code == 400
# =============================================================================
# TestPolicySeedScript
# =============================================================================
class TestPolicySeedScript:
"""Validate the seed_policy_templates.py script structure."""
def test_seed_script_exists(self):
"""Seed script file exists."""
import os
path = os.path.join(
os.path.dirname(__file__), "..", "scripts", "seed_policy_templates.py"
)
assert os.path.exists(path), "seed_policy_templates.py not found"
def test_seed_script_importable(self):
"""Seed script can be parsed without errors."""
import importlib.util
import os
path = os.path.join(
os.path.dirname(__file__), "..", "scripts", "seed_policy_templates.py"
)
spec = importlib.util.spec_from_file_location("seed_policy_templates", path)
mod = importlib.util.module_from_spec(spec)
# Don't execute main() — just verify the module parses
# We do this by checking TEMPLATES is defined
try:
spec.loader.exec_module(mod)
except SystemExit:
pass # Script may call sys.exit
except Exception:
pass # Network calls may fail in test env
# Module should define TEMPLATES list
assert hasattr(mod, "TEMPLATES"), "TEMPLATES list not found in seed script"
assert len(mod.TEMPLATES) == 29, f"Expected 29 templates, got {len(mod.TEMPLATES)}"
def test_seed_templates_have_required_fields(self):
"""Each seed template has document_type, title, description, content, placeholders."""
import importlib.util
import os
path = os.path.join(
os.path.dirname(__file__), "..", "scripts", "seed_policy_templates.py"
)
spec = importlib.util.spec_from_file_location("seed_policy_templates", path)
mod = importlib.util.module_from_spec(spec)
try:
spec.loader.exec_module(mod)
except Exception:
pass
required_fields = {"document_type", "title", "description", "content", "placeholders"}
for tmpl in mod.TEMPLATES:
for field in required_fields:
assert field in tmpl, (
f"Template '{tmpl.get('document_type', '?')}' missing field '{field}'"
)
def test_seed_templates_use_valid_types(self):
"""All seed template document_types are in VALID_DOCUMENT_TYPES."""
import importlib.util
import os
path = os.path.join(
os.path.dirname(__file__), "..", "scripts", "seed_policy_templates.py"
)
spec = importlib.util.spec_from_file_location("seed_policy_templates", path)
mod = importlib.util.module_from_spec(spec)
try:
spec.loader.exec_module(mod)
except Exception:
pass
for tmpl in mod.TEMPLATES:
assert tmpl["document_type"] in VALID_DOCUMENT_TYPES, (
f"Seed type '{tmpl['document_type']}' not in VALID_DOCUMENT_TYPES"
)
def test_seed_templates_have_german_content(self):
"""All seed templates have German content (contain common German words)."""
import importlib.util
import os
path = os.path.join(
os.path.dirname(__file__), "..", "scripts", "seed_policy_templates.py"
)
spec = importlib.util.spec_from_file_location("seed_policy_templates", path)
mod = importlib.util.module_from_spec(spec)
try:
spec.loader.exec_module(mod)
except Exception:
pass
german_markers = ["Richtlinie", "Zweck", "Geltungsbereich", "Verantwortlich"]
for tmpl in mod.TEMPLATES:
content = tmpl["content"]
has_german = any(marker in content for marker in german_markers)
assert has_german, (
f"Template '{tmpl['document_type']}' content appears not to be German"
)

View File

@@ -80,3 +80,13 @@ Im Company-Profile-Wizard erscheint nach Abschluss (`is_complete = true`) ein CT
- Alle 5 Template-Generatoren mit verschiedenen Kontext-Variationen
- Regulierungs-Flag-Kombinationen
- Route-Registrierung
---
## Policy-Bibliothek
Neben der automatischen Dokumentengenerierung aus Stammdaten stehen **29 deutsche Richtlinien-Templates**
im Dokumentengenerator als Vorlagen bereit (IT-Sicherheit, Datenschutz, Personal, Lieferanten, BCM).
Siehe [Policy-Bibliothek](policy-bibliothek.md) fuer die vollstaendige Liste aller Templates,
Platzhalter und Kategorien.

View File

@@ -0,0 +1,224 @@
# Policy-Bibliothek (Migration 054)
Die Policy-Bibliothek stellt **29 deutsche Richtlinien-Templates** bereit, die ueber den Dokumentengenerator
als Vorlagen genutzt werden koennen. Alle Templates sind nach deutschen Compliance-Standards strukturiert
und enthalten Platzhalter fuer unternehmensspezifische Anpassung.
---
## Uebersicht
| Kategorie | Anzahl | UI-Pill | Beschreibung |
|-----------|--------|---------|--------------|
| [IT-Sicherheit](#it-sicherheit-policies) | 14 | `IT-Sicherheit Policies` | Informationssicherheit, Zugriffskontrollen, Verschluesselung, Patch-Mgmt. |
| [Daten-Policies](#daten-policies) | 5 | `Daten-Policies` | Datenschutz, Klassifizierung, Aufbewahrung, Transfer |
| [Personal-Policies](#personal-policies) | 4 | `Personal-Policies` | Mitarbeitersicherheit, Awareness, Remote Work, Offboarding |
| [Lieferanten-Policies](#lieferanten-policies) | 3 | `Lieferanten-Policies` | Vendor Risk, Drittanbieter, Lieferanten-Sicherheit |
| [BCM/Notfall](#bcmnotfall) | 3 | `BCM/Notfall` | Business Continuity, Disaster Recovery, Krisenmanagement |
**Gesamt:** 29 Policy-Templates + 7 Sicherheitskonzepte (Migration 051) + 16 Basis-Dokumenttypen = **52 Dokumenttypen**
---
## Template-Struktur
Alle 29 Policy-Templates folgen einer einheitlichen **9-Abschnitte-Struktur:**
1. **Zweck** — Zielsetzung der Richtlinie
2. **Geltungsbereich** — Fuer wen gilt die Richtlinie
3. **Begriffe** — Definitionen
4. **Verantwortlichkeiten** — Rollen und Zustaendigkeiten
5. **Richtlinie** (Kern) — Die eigentlichen Regelungen
6. **Massnahmen** — Konkrete Umsetzungsschritte
7. **Ueberwachung & Audit** — Pruef- und Kontrollmechanismen
8. **Schulung** — Anforderungen an Mitarbeiterschulung
9. **Inkrafttreten** — Gueltigkeitsdatum und Freigabe
### Gemeinsame Platzhalter
| Platzhalter | Beschreibung |
|-------------|--------------|
| `{{COMPANY_NAME}}` | Firmenname |
| `{{SECURITY_OFFICER}}` / `{{ISB_NAME}}` | Informationssicherheitsbeauftragter |
| `{{GF_NAME}}` | Geschaeftsfuehrung (Freigabe) |
| `{{VERSION}}` | Dokumentversion |
| `{{DATE}}` | Erstellungsdatum |
| `{{SCOPE_DESCRIPTION}}` | Geltungsbereich |
| `{{NEXT_REVIEW_DATE}}` | Naechster Prueftermin |
---
## IT-Sicherheit Policies
14 Templates fuer die IT-Sicherheitsorganisation:
| Typ | Titel | Spezifische Platzhalter |
|-----|-------|------------------------|
| `information_security_policy` | Informationssicherheits-Richtlinie | `SCOPE_DESCRIPTION` |
| `access_control_policy` | Zugriffskontrollen-Richtlinie | `REVIEW_INTERVAL_DAYS` |
| `password_policy` | Passwort-Richtlinie | `MIN_PASSWORD_LENGTH`, `MAX_AGE_DAYS`, `HISTORY_COUNT` |
| `encryption_policy` | Verschluesselungs-Richtlinie | `MIN_KEY_LENGTH` |
| `logging_policy` | Logging-Richtlinie | `LOG_RETENTION_DAYS` |
| `backup_policy` | Backup-Richtlinie | `RPO_HOURS`, `RTO_HOURS`, `BACKUP_RETENTION_DAYS` |
| `incident_response_policy` | Incident-Response-Richtlinie | `INCIDENT_HOTLINE`, `NOTIFICATION_HOURS` |
| `change_management_policy` | Change-Management-Richtlinie | `CAB_SCHEDULE` |
| `patch_management_policy` | Patch-Management-Richtlinie | `CRITICAL_PATCH_HOURS`, `PATCH_WINDOW` |
| `asset_management_policy` | Asset-Management-Richtlinie | `INVENTORY_TOOL` |
| `cloud_security_policy` | Cloud-Sicherheits-Richtlinie | `APPROVED_PROVIDERS` |
| `devsecops_policy` | DevSecOps-Richtlinie | `CI_TOOL`, `SAST_TOOL` |
| `secrets_management_policy` | Secrets-Management-Richtlinie | `VAULT_URL`, `ROTATION_DAYS` |
| `vulnerability_management_policy` | Schwachstellenmanagement-Richtlinie | `SCAN_FREQUENCY`, `SCANNER_TOOL` |
---
## Daten-Policies
5 Templates fuer Datenschutz und Datenmanagement:
| Typ | Titel | Spezifische Platzhalter |
|-----|-------|------------------------|
| `data_protection_policy` | Datenschutz-Richtlinie | `DSB_NAME`, `DSB_EMAIL`, `SUPERVISORY_AUTHORITY` |
| `data_classification_policy` | Datenklassifizierungs-Richtlinie | `CLASSIFICATION_TOOL` |
| `data_retention_policy` | Datenaufbewahrungs-Richtlinie | `DEFAULT_RETENTION_YEARS`, `DELETION_TOOL` |
| `data_transfer_policy` | Datentransfer-Richtlinie | `DPO_EMAIL` |
| `privacy_incident_policy` | Datenschutzvorfall-Richtlinie | `DPO_EMAIL`, `NOTIFICATION_HOURS` |
---
## Personal-Policies
4 Templates fuer Mitarbeitersicherheit:
| Typ | Titel | Spezifische Platzhalter |
|-----|-------|------------------------|
| `employee_security_policy` | Mitarbeiter-Sicherheitsrichtlinie | `HR_CONTACT` |
| `security_awareness_policy` | Security-Awareness-Richtlinie | `TRAINING_FREQUENCY`, `LMS_URL` |
| `remote_work_policy` | Remote-Work-Richtlinie | `VPN_TOOL`, `MDM_TOOL` |
| `offboarding_policy` | Offboarding-Richtlinie | `HR_CONTACT`, `IT_CONTACT` |
---
## Lieferanten-Policies
3 Templates fuer die Lieferkette:
| Typ | Titel | Spezifische Platzhalter |
|-----|-------|------------------------|
| `vendor_risk_management_policy` | Lieferanten-Risikomanagement-Richtlinie | `PROCUREMENT_CONTACT`, `REVIEW_FREQUENCY` |
| `third_party_security_policy` | Drittanbieter-Sicherheitsrichtlinie | `SECURITY_CONTACT` |
| `supplier_security_policy` | Lieferanten-Sicherheitsrichtlinie | `PROCUREMENT_CONTACT` |
---
## BCM/Notfall
3 Templates fuer Business Continuity:
| Typ | Titel | Spezifische Platzhalter |
|-----|-------|------------------------|
| `business_continuity_policy` | Business-Continuity-Richtlinie | `RTO_HOURS`, `RPO_HOURS`, `BC_COORDINATOR` |
| `disaster_recovery_policy` | Disaster-Recovery-Richtlinie | `DR_SITE`, `RTO_HOURS`, `RPO_HOURS` |
| `crisis_management_policy` | Krisenmanagement-Richtlinie | `CRISIS_HOTLINE`, `CRISIS_TEAM_LEAD` |
---
## API
Die Policy-Templates werden ueber die bestehende Legal-Templates-API verwaltet:
| Methode | Pfad | Beschreibung |
|---------|------|--------------|
| `GET` | `/api/compliance/legal-templates` | Templates listen (Filter: `document_type`, `status`, `language`) |
| `GET` | `/api/compliance/legal-templates/status` | Anzahl nach Typ und Status |
| `GET` | `/api/compliance/legal-templates/{id}` | Einzelnes Template laden |
| `POST` | `/api/compliance/legal-templates` | Neues Template erstellen |
| `PUT` | `/api/compliance/legal-templates/{id}` | Template aktualisieren |
| `DELETE` | `/api/compliance/legal-templates/{id}` | Template loeschen |
### Beispiel: Policy-Templates nach Kategorie filtern
```bash
# Alle IT-Sicherheit Policies
curl "https://api-dev.breakpilot.ai/api/compliance/legal-templates?document_type=information_security_policy"
# Alle Policy-Templates (mehrere Typen)
curl "https://api-dev.breakpilot.ai/api/compliance/legal-templates/status"
```
### Beispiel: Template erstellen
```bash
curl -X POST "https://api-dev.breakpilot.ai/api/compliance/legal-templates" \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: <tenant-id>" \
-d '{
"document_type": "password_policy",
"title": "Passwort-Richtlinie",
"content": "# Passwort-Richtlinie\n\n...",
"placeholders": ["{{COMPANY_NAME}}", "{{MIN_PASSWORD_LENGTH}}"],
"language": "de",
"jurisdiction": "DE"
}'
```
---
## Frontend
Die Policy-Templates sind im **Dokumentengenerator** (`/sdk/document-generator`) unter 5 neuen Kategorie-Pills erreichbar:
| UI-Pill | Enthaltene Typen |
|---------|-----------------|
| IT-Sicherheit Policies | 14 Typen (information_security_policy bis vulnerability_management_policy) |
| Daten-Policies | 5 Typen (data_protection_policy bis privacy_incident_policy) |
| Personal-Policies | 5 Typen (employee_security_policy, security_awareness_policy, acceptable_use, remote_work_policy, offboarding_policy) |
| Lieferanten-Policies | 3 Typen (vendor_risk_management_policy bis supplier_security_policy) |
| BCM/Notfall | 3 Typen (business_continuity_policy bis crisis_management_policy) |
---
## Seeding
Das Seed-Script `backend-compliance/scripts/seed_policy_templates.py` fuegt alle 29 Templates ueber die API ein:
```bash
python3 backend-compliance/scripts/seed_policy_templates.py
```
Das Script nutzt die Production-API (`https://api-dev.breakpilot.ai`) und benoetigt einen gueltigen
`X-Tenant-Id` Header. Bereits existierende Templates werden nicht dupliziert (Upsert ueber `document_type`).
---
## Tests
- **48 Tests** in `test_policy_templates.py`
- Alle 29 Dokumenttypen gegen `VALID_DOCUMENT_TYPES` validiert
- API-Akzeptanz (POST 201) fuer jeden Typ (parametrized)
- Filterung nach Kategorie (GET 200)
- Platzhalter-Validierung
- Seed-Script-Struktur (29 Templates, Pflichtfelder, deutsche Inhalte)
- Ablehnung ungeltiger Typen (400)
---
## Zusammenspiel mit anderen Modulen
```mermaid
graph LR
A[Company Profile] --> B[Compliance Engine]
B --> C[Policy-Bibliothek]
C --> D[Dokumentengenerator]
D --> E[Change-Requests]
E --> F[Document Workflow]
C --> G[Controls / Mapping-Matrix]
G --> H[Process Manager Tasks]
G --> I[Evidence Checks]
```
Die Policy-Bibliothek bildet die **Vorlage-Ebene** der geplanten Compliance Engine:
1. **CompanyProfile + Scope** → bestimmt welche Regulations/Controls relevant sind
2. **Controls** → verweisen auf relevante **Policies** aus der Bibliothek
3. **Policies** → werden ueber den Dokumentengenerator als Entwuerfe erstellt
4. **Entwuerfe** → durchlaufen den Document Workflow (Review → Freigabe → Veroeffentlichung)

View File

@@ -412,3 +412,8 @@ Die **Einwilligungen** legen fest, welche Datenpunkte einer Einwilligung beduerf
Die **Rechtlichen Vorlagen** erstellen die zugehoerigen Dokumente (DSE, AGB, etc.).
Der **Cookie Banner** konfiguriert das Frontend-Consent-Widget.
Der **Document Workflow** fuhrt alle Dokumente durch den Freigabeprozess vor der Veroeffentlichung.
!!! info "Policy-Bibliothek (Migration 054)"
Zusaetzlich zu den rechtlichen Texten stehen **29 deutsche Richtlinien-Templates** zur Verfuegung
(IT-Sicherheit, Datenschutz, Personal, Lieferanten, BCM). Siehe
[Policy-Bibliothek](policy-bibliothek.md) fuer Details.

View File

@@ -100,6 +100,7 @@ nav:
- Dokument-Versionierung: services/sdk-modules/versionierung.md
- Change-Request System (CP-CR): services/sdk-modules/change-requests.md
- Dokumentengenerierung: services/sdk-modules/dokumentengenerierung.md
- Policy-Bibliothek (29 Richtlinien): services/sdk-modules/policy-bibliothek.md
- Canonical Control Library (CP-CLIB): services/sdk-modules/canonical-control-library.md
- Strategie:
- Wettbewerbsanalyse & Roadmap: strategy/wettbewerbsanalyse.md