feat: Rollenkonzept backend + SOP template (Phase 1-3)
- Migration 111: 3 new tables (org_roles, document_reviews, document_role_mapping) with seed data mapping all 71 doc types to 7 compliance roles - org_role_routes.py: CRUD for roles, seed defaults, test email, mapping API - document_review_routes.py: Review lifecycle (create→send→approve/reject) with approval notification to all affected roles - Migration 112: SOP template (ISO 9001 structure, 21 placeholders) - Added standard_operating_procedure to TemplateType, doc-labels, presets [migration-approved] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
-- Migration 111: Organizational Compliance Roles + Document Review Workflow
|
||||
-- Creates tables for:
|
||||
-- 1. compliance_org_roles — role assignments per project (DSB, GF, IT-Leiter, etc.)
|
||||
-- 2. compliance_document_reviews — review tracking for generated documents
|
||||
-- 3. compliance_document_role_mapping — which roles review which document types
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- =============================================================================
|
||||
-- Table 1: Organizational Compliance Roles
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS compliance_org_roles (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
project_id UUID,
|
||||
role_key VARCHAR(50) NOT NULL,
|
||||
role_label VARCHAR(200) NOT NULL,
|
||||
person_name VARCHAR(300),
|
||||
person_email VARCHAR(300),
|
||||
department VARCHAR(200),
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(tenant_id, project_id, role_key)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_org_roles_tenant ON compliance_org_roles(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_org_roles_project ON compliance_org_roles(tenant_id, project_id);
|
||||
|
||||
-- =============================================================================
|
||||
-- Table 2: Document Reviews
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS compliance_document_reviews (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
project_id UUID,
|
||||
document_type VARCHAR(100) NOT NULL,
|
||||
document_title VARCHAR(500) NOT NULL,
|
||||
document_content_hash VARCHAR(64),
|
||||
reviewer_role_key VARCHAR(50) NOT NULL,
|
||||
reviewer_name VARCHAR(300),
|
||||
reviewer_email VARCHAR(300),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending', 'in_review', 'approved', 'rejected')),
|
||||
submitted_at TIMESTAMPTZ,
|
||||
submitted_by VARCHAR(200),
|
||||
reviewed_at TIMESTAMPTZ,
|
||||
review_comment TEXT,
|
||||
review_link TEXT,
|
||||
email_sent BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
email_sent_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_doc_reviews_tenant ON compliance_document_reviews(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_doc_reviews_status ON compliance_document_reviews(tenant_id, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_doc_reviews_doctype ON compliance_document_reviews(document_type);
|
||||
|
||||
-- =============================================================================
|
||||
-- Table 3: Document-to-Role Mapping (seed defaults)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS compliance_document_role_mapping (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
document_type VARCHAR(100) NOT NULL,
|
||||
role_key VARCHAR(50) NOT NULL,
|
||||
is_primary BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(tenant_id, document_type, role_key)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_role_mapping_tenant ON compliance_document_role_mapping(tenant_id);
|
||||
|
||||
-- =============================================================================
|
||||
-- Seed: Default document-to-role mapping (tenant_id = '__default__')
|
||||
-- Every document type has at least one primary reviewer.
|
||||
-- Tenants get a copy on first use; editable per tenant.
|
||||
-- =============================================================================
|
||||
|
||||
-- DSB — Datenschutzbeauftragter
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'privacy_policy', 'dsb'), ('__default__', 'vvt_register', 'dsb'),
|
||||
('__default__', 'tom_documentation', 'dsb'), ('__default__', 'dsfa', 'dsb'),
|
||||
('__default__', 'loeschkonzept', 'dsb'), ('__default__', 'dpa', 'dsb'),
|
||||
('__default__', 'pflichtenregister', 'dsb'), ('__default__', 'data_protection_concept', 'dsb'),
|
||||
('__default__', 'data_protection_policy', 'dsb'), ('__default__', 'data_retention_policy', 'dsb'),
|
||||
('__default__', 'data_transfer_policy', 'dsb'), ('__default__', 'data_classification_policy', 'dsb'),
|
||||
('__default__', 'privacy_incident_policy', 'dsb'), ('__default__', 'informationspflichten', 'dsb'),
|
||||
('__default__', 'verpflichtungserklaerung', 'dsb'), ('__default__', 'consent_texts', 'dsb'),
|
||||
('__default__', 'dsr_process_art15', 'dsb'), ('__default__', 'dsr_process_art16', 'dsb'),
|
||||
('__default__', 'dsr_process_art17', 'dsb'), ('__default__', 'dsr_process_art18', 'dsb'),
|
||||
('__default__', 'dsr_process_art19', 'dsb'), ('__default__', 'dsr_process_art20', 'dsb'),
|
||||
('__default__', 'dsr_process_art21', 'dsb')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- GF — Geschaeftsfuehrung
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'agb', 'gf'), ('__default__', 'terms_of_use', 'gf'),
|
||||
('__default__', 'nda', 'gf'), ('__default__', 'sla', 'gf'),
|
||||
('__default__', 'impressum', 'gf'), ('__default__', 'widerruf', 'gf'),
|
||||
('__default__', 'whistleblower_policy', 'gf'),
|
||||
('__default__', 'cloud_service_agreement', 'gf'),
|
||||
('__default__', 'standard_operating_procedure', 'gf'),
|
||||
('__default__', 'data_usage_clause', 'gf')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- IT-Leiter / CISO
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'it_security_concept', 'it_leiter'),
|
||||
('__default__', 'isms_manual', 'it_leiter'),
|
||||
('__default__', 'backup_recovery_concept', 'it_leiter'),
|
||||
('__default__', 'logging_concept', 'it_leiter'),
|
||||
('__default__', 'incident_response_plan', 'it_leiter'),
|
||||
('__default__', 'access_control_concept', 'it_leiter'),
|
||||
('__default__', 'risk_management_concept', 'it_leiter'),
|
||||
('__default__', 'information_security_policy', 'it_leiter'),
|
||||
('__default__', 'access_control_policy', 'it_leiter'),
|
||||
('__default__', 'password_policy', 'it_leiter'),
|
||||
('__default__', 'encryption_policy', 'it_leiter'),
|
||||
('__default__', 'logging_policy', 'it_leiter'),
|
||||
('__default__', 'backup_policy', 'it_leiter'),
|
||||
('__default__', 'incident_response_policy', 'it_leiter'),
|
||||
('__default__', 'change_management_policy', 'it_leiter'),
|
||||
('__default__', 'patch_management_policy', 'it_leiter'),
|
||||
('__default__', 'asset_management_policy', 'it_leiter'),
|
||||
('__default__', 'cloud_security_policy', 'it_leiter'),
|
||||
('__default__', 'devsecops_policy', 'it_leiter'),
|
||||
('__default__', 'secrets_management_policy', 'it_leiter'),
|
||||
('__default__', 'vulnerability_management_policy', 'it_leiter'),
|
||||
('__default__', 'cybersecurity_policy', 'it_leiter'),
|
||||
('__default__', 'business_continuity_policy', 'it_leiter'),
|
||||
('__default__', 'disaster_recovery_policy', 'it_leiter'),
|
||||
('__default__', 'crisis_management_policy', 'it_leiter')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- HR-Leitung
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'employee_dsi', 'hr_leitung'),
|
||||
('__default__', 'applicant_dsi', 'hr_leitung'),
|
||||
('__default__', 'employee_security_policy', 'hr_leitung'),
|
||||
('__default__', 'security_awareness_policy', 'hr_leitung'),
|
||||
('__default__', 'remote_work_policy', 'hr_leitung'),
|
||||
('__default__', 'offboarding_policy', 'hr_leitung'),
|
||||
('__default__', 'byod_policy', 'hr_leitung')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Marketing-Leitung
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'cookie_banner', 'marketing_leitung'),
|
||||
('__default__', 'cookie_policy', 'marketing_leitung'),
|
||||
('__default__', 'social_media_dsi', 'marketing_leitung'),
|
||||
('__default__', 'community_guidelines', 'marketing_leitung'),
|
||||
('__default__', 'acceptable_use', 'marketing_leitung'),
|
||||
('__default__', 'media_content_policy', 'marketing_leitung'),
|
||||
('__default__', 'copyright_policy', 'marketing_leitung'),
|
||||
('__default__', 'video_conference_dsi', 'marketing_leitung')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Compliance-Beauftragter
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'ai_usage_policy', 'compliance_beauftragter')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Einkauf / Vendor Management
|
||||
INSERT INTO compliance_document_role_mapping (tenant_id, document_type, role_key) VALUES
|
||||
('__default__', 'vendor_risk_management_policy', 'einkauf'),
|
||||
('__default__', 'third_party_security_policy', 'einkauf'),
|
||||
('__default__', 'supplier_security_policy', 'einkauf'),
|
||||
('__default__', 'transfer_impact_assessment', 'einkauf'),
|
||||
('__default__', 'scc_companion', 'einkauf')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,137 @@
|
||||
-- Migration 112: Standard Operating Procedure (SOP) Template
|
||||
-- ISO 9001-konforme Struktur, eigene Formulierung (kein Normtext)
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
tenant_id, document_type, template_type, language, jurisdiction,
|
||||
document_title, description, version, status,
|
||||
text, placeholders,
|
||||
license_id, license_name, source_name, attribution_required
|
||||
) VALUES (
|
||||
'__default__',
|
||||
'standard_operating_procedure',
|
||||
'standard_operating_procedure',
|
||||
'de',
|
||||
'DE',
|
||||
'Standard Operating Procedure (SOP)',
|
||||
'Vorlage fuer standardisierte Verfahrensanweisungen mit Rollen-Matrix, Ablaufbeschreibung und Freigabeprozess',
|
||||
'1.0',
|
||||
'published',
|
||||
$template$# Standard Operating Procedure (SOP)
|
||||
|
||||
**{{COMPANY_NAME}}** | SOP-Nr.: {{SOP_NUMBER}} | Version {{DOCUMENT_VERSION}} | Stand: {{VERSION_DATE}}
|
||||
|
||||
---
|
||||
|
||||
## 1. Zweck
|
||||
|
||||
{{SOP_PURPOSE}}
|
||||
|
||||
## 2. Geltungsbereich
|
||||
|
||||
{{SOP_SCOPE}}
|
||||
|
||||
## 3. Verantwortlichkeiten
|
||||
|
||||
| Rolle | Verantwortung | Name |
|
||||
|-------|---------------|------|
|
||||
| Ersteller | Erstellung und Pflege dieser SOP | {{SOP_AUTHOR_NAME}} |
|
||||
| Pruefer/in | Fachliche Pruefung auf Richtigkeit | {{SOP_REVIEWER_NAME}} |
|
||||
| Freigebende/r | Formale Freigabe und Inkraftsetzung | {{SOP_APPROVER_NAME}} |
|
||||
| Durchfuehrende/r | Operative Umsetzung des Verfahrens | {{SOP_EXECUTOR_NAME}} |
|
||||
|
||||
### Zusaetzliche Rollen
|
||||
|
||||
{{#IF HAS_ADDITIONAL_ROLES}}
|
||||
| Rolle | Verantwortung | Kontakt |
|
||||
|-------|---------------|---------|
|
||||
{{SOP_ADDITIONAL_ROLES}}
|
||||
{{/IF}}
|
||||
|
||||
## 4. Begriffe und Abkuerzungen
|
||||
|
||||
{{SOP_DEFINITIONS}}
|
||||
|
||||
## 5. Ablaufbeschreibung
|
||||
|
||||
### 5.1 Voraussetzungen
|
||||
|
||||
{{SOP_PREREQUISITES}}
|
||||
|
||||
### 5.2 Durchfuehrung
|
||||
|
||||
{{SOP_PROCEDURE_STEPS}}
|
||||
|
||||
### 5.3 Nachbereitung und Qualitaetskontrolle
|
||||
|
||||
{{SOP_POST_STEPS}}
|
||||
|
||||
### 5.4 Eskalation
|
||||
|
||||
{{#IF HAS_ESCALATION}}
|
||||
Bei Abweichungen vom Standardprozess gilt folgender Eskalationsweg:
|
||||
|
||||
{{SOP_ESCALATION_PATH}}
|
||||
{{/IF}}
|
||||
{{#IF_NOT HAS_ESCALATION}}
|
||||
Abweichungen sind dem/der Freigebenden ({{SOP_APPROVER_NAME}}) unverzueglich zu melden.
|
||||
{{/IF_NOT}}
|
||||
|
||||
## 6. Dokumentation und Nachweise
|
||||
|
||||
{{SOP_DOCUMENTATION_REQUIREMENTS}}
|
||||
|
||||
**Aufbewahrungsfrist:** {{SOP_RETENTION_PERIOD}}
|
||||
|
||||
**Speicherort:** {{SOP_STORAGE_LOCATION}}
|
||||
|
||||
## 7. Abweichungsbehandlung
|
||||
|
||||
{{SOP_DEVIATION_HANDLING}}
|
||||
|
||||
## 8. Referenzen
|
||||
|
||||
{{SOP_REFERENCES}}
|
||||
|
||||
## 9. Revisionshistorie
|
||||
|
||||
| Version | Datum | Autor | Aenderungen |
|
||||
|---------|-------|-------|-------------|
|
||||
| {{DOCUMENT_VERSION}} | {{VERSION_DATE}} | {{SOP_AUTHOR_NAME}} | Erstversion |
|
||||
|
||||
## 10. Freigabe
|
||||
|
||||
| Rolle | Name | Datum | Unterschrift |
|
||||
|-------|------|-------|-------------|
|
||||
| Erstellt von | {{SOP_AUTHOR_NAME}} | {{VERSION_DATE}} | _______________ |
|
||||
| Geprueft von | {{SOP_REVIEWER_NAME}} | | _______________ |
|
||||
| Freigegeben von | {{SOP_APPROVER_NAME}} | | _______________ |
|
||||
|
||||
---
|
||||
|
||||
*Dieses Dokument wurde mit dem BreakPilot Compliance SDK erstellt.*
|
||||
$template$,
|
||||
'[
|
||||
{"key": "{{COMPANY_NAME}}", "label": "Firmenname", "required": true, "section": "PROVIDER"},
|
||||
{"key": "{{SOP_NUMBER}}", "label": "SOP-Nummer (z.B. SOP-DS-001)", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{DOCUMENT_VERSION}}", "label": "Version (z.B. 1.0)", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{VERSION_DATE}}", "label": "Datum (YYYY-MM-DD)", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_PURPOSE}}", "label": "Zweck der SOP", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_SCOPE}}", "label": "Geltungsbereich", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_AUTHOR_NAME}}", "label": "Ersteller (Name)", "required": true, "section": "PROVIDER"},
|
||||
{"key": "{{SOP_REVIEWER_NAME}}", "label": "Pruefer/in (Name)", "required": true, "section": "PROVIDER"},
|
||||
{"key": "{{SOP_APPROVER_NAME}}", "label": "Freigebende/r (Name)", "required": true, "section": "PROVIDER"},
|
||||
{"key": "{{SOP_EXECUTOR_NAME}}", "label": "Durchfuehrende/r (Name)", "required": true, "section": "PROVIDER"},
|
||||
{"key": "{{SOP_ADDITIONAL_ROLES}}", "label": "Weitere Rollen (Markdown-Tabelle)", "required": false, "section": "PROVIDER"},
|
||||
{"key": "{{SOP_DEFINITIONS}}", "label": "Begriffe und Abkuerzungen", "required": false, "section": "LEGAL"},
|
||||
{"key": "{{SOP_PREREQUISITES}}", "label": "Voraussetzungen", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_PROCEDURE_STEPS}}", "label": "Ablaufbeschreibung (Schritte)", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_POST_STEPS}}", "label": "Nachbereitung / QS", "required": false, "section": "LEGAL"},
|
||||
{"key": "{{SOP_ESCALATION_PATH}}", "label": "Eskalationsweg", "required": false, "section": "LEGAL"},
|
||||
{"key": "{{SOP_DOCUMENTATION_REQUIREMENTS}}", "label": "Dokumentationspflichten", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_RETENTION_PERIOD}}", "label": "Aufbewahrungsfrist", "required": false, "section": "LEGAL"},
|
||||
{"key": "{{SOP_STORAGE_LOCATION}}", "label": "Speicherort", "required": false, "section": "LEGAL"},
|
||||
{"key": "{{SOP_DEVIATION_HANDLING}}", "label": "Abweichungsbehandlung", "required": true, "section": "LEGAL"},
|
||||
{"key": "{{SOP_REFERENCES}}", "label": "Referenzen / Normen", "required": false, "section": "LEGAL"}
|
||||
]'::jsonb,
|
||||
'mit', 'MIT License', 'BreakPilot Compliance', false
|
||||
) ON CONFLICT DO NOTHING;
|
||||
Reference in New Issue
Block a user