feat: Legal Templates — Attribution-Tracking + 6 neue Templates (DE/EN)
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 47s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 23s
CI / test-python-dsms-gateway (push) Successful in 18s
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 47s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 23s
CI / test-python-dsms-gateway (push) Successful in 18s
Migration 019: 5 neue Herkunftsspalten (source_url, source_repo,
source_file_path, source_retrieved_at, attribution_text, inspiration_sources)
ermöglichen lückenlosen Nachweis jeder Template-Quelle.
Neue Templates:
DE: AVV (Art. 28 DSGVO), Widerrufsbelehrung (EGBGB Anlage 1, §5 UrhG),
Cookie-Richtlinie (TTDSG §25)
EN: Privacy Policy (GDPR), Terms of Service (EU Directive 2011/83),
Data Processing Agreement (GDPR Art. 28)
Gesamt: 9 Templates — 5 DE, 4 EN | 6 document_type-Werte
- VALID_DOCUMENT_TYPES um 3 neue Typen erweitert
- Create/Update-Schemas: attribution fields ergänzt
- Status-Endpoint: alle 6 Typen in by_type
- Tests: 34/34 — alle grün
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,14 @@ router = APIRouter(prefix="/legal-templates", tags=["legal-templates"])
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
|
||||
VALID_DOCUMENT_TYPES = {"privacy_policy", "terms_of_service", "impressum"}
|
||||
VALID_DOCUMENT_TYPES = {
|
||||
"privacy_policy",
|
||||
"terms_of_service",
|
||||
"impressum",
|
||||
"data_processing_agreement",
|
||||
"withdrawal_policy",
|
||||
"cookie_policy",
|
||||
}
|
||||
VALID_STATUSES = {"published", "draft", "archived"}
|
||||
|
||||
|
||||
@@ -54,6 +61,12 @@ class LegalTemplateCreate(BaseModel):
|
||||
is_complete_document: bool = True
|
||||
version: str = "1.0.0"
|
||||
status: str = "published"
|
||||
# Attribution / source traceability
|
||||
source_url: Optional[str] = None
|
||||
source_repo: Optional[str] = None
|
||||
source_file_path: Optional[str] = None
|
||||
attribution_text: Optional[str] = None
|
||||
inspiration_sources: Optional[List[Any]] = None
|
||||
|
||||
|
||||
class LegalTemplateUpdate(BaseModel):
|
||||
@@ -71,6 +84,12 @@ class LegalTemplateUpdate(BaseModel):
|
||||
is_complete_document: Optional[bool] = None
|
||||
version: Optional[str] = None
|
||||
status: Optional[str] = None
|
||||
# Attribution / source traceability
|
||||
source_url: Optional[str] = None
|
||||
source_repo: Optional[str] = None
|
||||
source_file_path: Optional[str] = None
|
||||
attribution_text: Optional[str] = None
|
||||
inspiration_sources: Optional[List[Any]] = None
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -173,7 +192,10 @@ async def get_templates_status(
|
||||
COUNT(*) FILTER (WHERE status = 'archived') AS archived,
|
||||
COUNT(*) FILTER (WHERE document_type = 'privacy_policy') AS privacy_policy,
|
||||
COUNT(*) FILTER (WHERE document_type = 'terms_of_service') AS terms_of_service,
|
||||
COUNT(*) FILTER (WHERE document_type = 'impressum') AS impressum
|
||||
COUNT(*) FILTER (WHERE document_type = 'impressum') AS impressum,
|
||||
COUNT(*) FILTER (WHERE document_type = 'data_processing_agreement') AS data_processing_agreement,
|
||||
COUNT(*) FILTER (WHERE document_type = 'withdrawal_policy') AS withdrawal_policy,
|
||||
COUNT(*) FILTER (WHERE document_type = 'cookie_policy') AS cookie_policy
|
||||
FROM compliance_legal_templates
|
||||
WHERE tenant_id = :tenant_id
|
||||
"""), {"tenant_id": tenant_id}).fetchone()
|
||||
@@ -192,6 +214,9 @@ async def get_templates_status(
|
||||
"privacy_policy": counts["privacy_policy"],
|
||||
"terms_of_service": counts["terms_of_service"],
|
||||
"impressum": counts["impressum"],
|
||||
"data_processing_agreement": counts["data_processing_agreement"],
|
||||
"withdrawal_policy": counts["withdrawal_policy"],
|
||||
"cookie_policy": counts["cookie_policy"],
|
||||
},
|
||||
}
|
||||
return {"total": 0, "by_status": {}, "by_type": {}}
|
||||
@@ -251,18 +276,23 @@ async def create_legal_template(
|
||||
)
|
||||
|
||||
placeholders_json = json.dumps(payload.placeholders or [])
|
||||
inspiration_json = json.dumps(payload.inspiration_sources or [])
|
||||
|
||||
row = db.execute(text("""
|
||||
INSERT INTO compliance_legal_templates (
|
||||
tenant_id, document_type, title, description, content,
|
||||
placeholders, language, jurisdiction,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
:tenant_id, :document_type, :title, :description, :content,
|
||||
CAST(:placeholders AS jsonb), :language, :jurisdiction,
|
||||
:license_id, :license_name, :source_name,
|
||||
:attribution_required, :is_complete_document, :version, :status
|
||||
:attribution_required, :is_complete_document, :version, :status,
|
||||
:source_url, :source_repo, :source_file_path, :source_retrieved_at,
|
||||
:attribution_text, CAST(:inspiration_sources AS jsonb)
|
||||
) RETURNING *
|
||||
"""), {
|
||||
"tenant_id": tenant_id,
|
||||
@@ -280,6 +310,12 @@ async def create_legal_template(
|
||||
"is_complete_document": payload.is_complete_document,
|
||||
"version": payload.version,
|
||||
"status": payload.status,
|
||||
"source_url": payload.source_url,
|
||||
"source_repo": payload.source_repo,
|
||||
"source_file_path": payload.source_file_path,
|
||||
"source_retrieved_at": None,
|
||||
"attribution_text": payload.attribution_text,
|
||||
"inspiration_sources": inspiration_json,
|
||||
}).fetchone()
|
||||
db.commit()
|
||||
return _row_to_dict(row)
|
||||
@@ -311,8 +347,9 @@ async def update_legal_template(
|
||||
"updated_at": datetime.utcnow(),
|
||||
}
|
||||
|
||||
jsonb_fields = {"placeholders", "inspiration_sources"}
|
||||
for field, value in updates.items():
|
||||
if field == "placeholders":
|
||||
if field in jsonb_fields:
|
||||
params[field] = json.dumps(value if value is not None else [])
|
||||
set_clauses.append(f"{field} = CAST(:{field} AS jsonb)")
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,728 @@
|
||||
-- Migration 019: Legal Templates — Attribution Tracking + New Templates
|
||||
--
|
||||
-- Adds 5 source-traceability columns to compliance_legal_templates so every
|
||||
-- template can be audited for its origin (required for commercial use proof).
|
||||
--
|
||||
-- New document_type values: data_processing_agreement, withdrawal_policy,
|
||||
-- cookie_policy (extend the existing privacy_policy | terms_of_service | impressum)
|
||||
--
|
||||
-- 6 new templates:
|
||||
-- DE: AVV (Art. 28 DSGVO), Widerrufsbelehrung, Cookie-Banner-Text
|
||||
-- EN: Privacy Policy (GDPR), Terms of Service (EU), DPA (GDPR Art. 28)
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. Schema extension: attribution tracking
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE compliance_legal_templates
|
||||
ADD COLUMN IF NOT EXISTS source_url TEXT,
|
||||
ADD COLUMN IF NOT EXISTS source_repo TEXT,
|
||||
ADD COLUMN IF NOT EXISTS source_file_path TEXT,
|
||||
ADD COLUMN IF NOT EXISTS source_retrieved_at TIMESTAMPTZ,
|
||||
ADD COLUMN IF NOT EXISTS attribution_text TEXT,
|
||||
ADD COLUMN IF NOT EXISTS inspiration_sources JSONB NOT NULL DEFAULT '[]'::jsonb;
|
||||
|
||||
COMMENT ON COLUMN compliance_legal_templates.source_url
|
||||
IS 'Direct URL to the original source file (NULL if self-authored)';
|
||||
COMMENT ON COLUMN compliance_legal_templates.source_repo
|
||||
IS 'GitHub / repository URL of the source project';
|
||||
COMMENT ON COLUMN compliance_legal_templates.source_file_path
|
||||
IS 'Relative path within the source repository';
|
||||
COMMENT ON COLUMN compliance_legal_templates.source_retrieved_at
|
||||
IS 'Timestamp when the source was fetched / reviewed';
|
||||
COMMENT ON COLUMN compliance_legal_templates.attribution_text
|
||||
IS 'Human-readable citation for legal proof of origin';
|
||||
COMMENT ON COLUMN compliance_legal_templates.inspiration_sources
|
||||
IS 'JSONB array of {source, url, license, author, retrieved_at} objects';
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. Backfill: attribution for the 3 existing self-authored templates
|
||||
-- =============================================================================
|
||||
|
||||
UPDATE compliance_legal_templates
|
||||
SET
|
||||
source_url = NULL,
|
||||
source_repo = NULL,
|
||||
source_file_path = NULL,
|
||||
source_retrieved_at = NULL,
|
||||
attribution_text = 'Self-authored by BreakPilot Compliance. License: MIT. '
|
||||
'Original content created 2026-03-04. '
|
||||
'Structural reference: DSGVO Art. 13/14 (DSE), '
|
||||
'DDG §5 (Impressum), BGB §305ff. (AGB).',
|
||||
inspiration_sources = '[{"source":"Self-authored","license":"MIT","author":"BreakPilot Compliance","created":"2026-03-04","legal_basis":"DSGVO Art. 13/14, DDG §5, BGB §305ff."}]'::jsonb
|
||||
WHERE document_type IN ('privacy_policy', 'impressum', 'terms_of_service')
|
||||
AND source_name = 'BreakPilot Compliance'
|
||||
AND attribution_text IS NULL;
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. New Template: Auftragsverarbeitungsvertrag / AVV (DE)
|
||||
-- document_type: data_processing_agreement | language: de
|
||||
-- Self-authored MIT. Legal basis: DSGVO Art. 28.
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
document_type, title, description, language, jurisdiction,
|
||||
placeholders, content,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
'data_processing_agreement',
|
||||
'Auftragsverarbeitungsvertrag (AVV) gemäß DSGVO Art. 28',
|
||||
'Vollständiger AVV für Auftragsverarbeiter nach Art. 28 DSGVO mit Pflichtinhalt, TOMs und Sub-AV-Regelung.',
|
||||
'de', 'DE',
|
||||
'["{{CONTROLLER_NAME}}", "{{CONTROLLER_ADDRESS}}", "{{CONTROLLER_CITY}}", "{{PROCESSOR_NAME}}", "{{PROCESSOR_ADDRESS}}", "{{PROCESSOR_CITY}}", "{{SERVICE_DESCRIPTION}}", "{{DATA_CATEGORIES}}", "{{DATA_SUBJECTS}}", "{{CONTRACT_DATE}}", "{{SUPERVISORY_AUTHORITY}}"]'::jsonb,
|
||||
$template$# Auftragsverarbeitungsvertrag (AVV)
|
||||
gemäß Art. 28 Datenschutz-Grundverordnung (DSGVO)
|
||||
|
||||
Abgeschlossen am {{CONTRACT_DATE}} zwischen:
|
||||
|
||||
**Verantwortlichem (Controller):**
|
||||
{{CONTROLLER_NAME}}, {{CONTROLLER_ADDRESS}}, {{CONTROLLER_CITY}}
|
||||
(nachfolgend „Verantwortlicher")
|
||||
|
||||
und
|
||||
|
||||
**Auftragsverarbeiter (Processor):**
|
||||
{{PROCESSOR_NAME}}, {{PROCESSOR_ADDRESS}}, {{PROCESSOR_CITY}}
|
||||
(nachfolgend „Auftragsverarbeiter")
|
||||
|
||||
---
|
||||
|
||||
## § 1 Gegenstand und Dauer der Verarbeitung
|
||||
|
||||
(1) Der Auftragsverarbeiter verarbeitet personenbezogene Daten im Auftrag des Verantwortlichen zur Erbringung folgender Leistungen: {{SERVICE_DESCRIPTION}}
|
||||
|
||||
(2) Die Verarbeitung erfolgt für die Dauer des zugrundeliegenden Hauptvertrags zwischen den Parteien.
|
||||
|
||||
## § 2 Art und Zweck der Verarbeitung
|
||||
|
||||
**Verarbeitete Datenkategorien:** {{DATA_CATEGORIES}}
|
||||
|
||||
**Betroffene Personen:** {{DATA_SUBJECTS}}
|
||||
|
||||
**Zweck der Verarbeitung:** Erbringung der unter § 1 genannten Leistungen im Auftrag des Verantwortlichen.
|
||||
|
||||
## § 3 Weisungsgebundenheit
|
||||
|
||||
(1) Der Auftragsverarbeiter verarbeitet personenbezogene Daten ausschließlich auf dokumentierte Weisung des Verantwortlichen.
|
||||
|
||||
(2) Ist der Auftragsverarbeiter der Ansicht, dass eine Weisung gegen die DSGVO oder andere Datenschutzvorschriften verstößt, informiert er den Verantwortlichen unverzüglich.
|
||||
|
||||
(3) Weisungen sind schriftlich zu erteilen und zu dokumentieren.
|
||||
|
||||
## § 4 Vertraulichkeit
|
||||
|
||||
Der Auftragsverarbeiter stellt sicher, dass sich die zur Verarbeitung der personenbezogenen Daten befugten Personen zur Vertraulichkeit verpflichtet haben oder einer angemessenen gesetzlichen Verschwiegenheitspflicht unterliegen.
|
||||
|
||||
## § 5 Technisch-organisatorische Maßnahmen (TOMs)
|
||||
|
||||
Der Auftragsverarbeiter trifft alle nach Art. 32 DSGVO erforderlichen technisch-organisatorischen Maßnahmen, insbesondere:
|
||||
|
||||
- **Zutrittskontrolle:** Physischer Zugang zu Datenverarbeitungsanlagen nur für befugte Personen
|
||||
- **Zugangskontrolle:** Authentifizierungsverfahren (Passwort-Policy, MFA wo anwendbar)
|
||||
- **Zugriffskontrolle:** Need-to-know-Prinzip, rollenbasierte Zugriffsrechte (RBAC)
|
||||
- **Trennungskontrolle:** Logische Trennung der Daten verschiedener Auftraggeber
|
||||
- **Verschlüsselung:** TLS 1.3 für Datenübertragung, Verschlüsselung sensibler Daten at rest
|
||||
- **Pseudonymisierung:** Wo technisch möglich und angemessen
|
||||
- **Belastbarkeit:** Regelmäßige Datensicherungen, getestete Wiederherstellungsverfahren
|
||||
- **Überprüfungsverfahren:** Regelmäßige Tests und Bewertungen der Wirksamkeit der TOMs
|
||||
|
||||
## § 6 Unterauftragsverarbeiter
|
||||
|
||||
(1) Der Auftragsverarbeiter darf Unterauftragsverarbeiter nur mit schriftlicher Genehmigung des Verantwortlichen einsetzen.
|
||||
|
||||
(2) Der Auftragsverarbeiter schließt mit Unterauftragsverarbeitern Verträge ab, die den Anforderungen des Art. 28 DSGVO entsprechen.
|
||||
|
||||
(3) Eine Liste der aktuell eingesetzten Unterauftragsverarbeiter wird dem Verantwortlichen auf Anfrage zur Verfügung gestellt.
|
||||
|
||||
## § 7 Unterstützung des Verantwortlichen
|
||||
|
||||
Der Auftragsverarbeiter unterstützt den Verantwortlichen angemessen bei:
|
||||
|
||||
- der Beantwortung von Anfragen betroffener Personen (Art. 15–22 DSGVO)
|
||||
- der Erfüllung von Pflichten nach Art. 32–36 DSGVO (Datensicherheit, DSFA, Meldepflichten)
|
||||
|
||||
## § 8 Löschung und Rückgabe nach Vertragsende
|
||||
|
||||
Nach Abschluss der Verarbeitungsleistungen löscht der Auftragsverarbeiter alle personenbezogenen Daten des Verantwortlichen oder gibt sie zurück, sofern keine gesetzliche Aufbewahrungspflicht entgegensteht.
|
||||
|
||||
## § 9 Datenpannen und Meldepflichten
|
||||
|
||||
Der Auftragsverarbeiter informiert den Verantwortlichen unverzüglich (innerhalb von 24 Stunden), wenn ihm eine Verletzung des Schutzes personenbezogener Daten bekannt wird. Die Meldung enthält mindestens die in Art. 33 Abs. 3 DSGVO genannten Angaben.
|
||||
|
||||
## § 10 Nachweise und Kontrollen
|
||||
|
||||
(1) Der Auftragsverarbeiter stellt dem Verantwortlichen alle erforderlichen Informationen zum Nachweis der Einhaltung der Pflichten aus Art. 28 DSGVO zur Verfügung.
|
||||
|
||||
(2) Der Verantwortliche oder ein von ihm beauftragter Prüfer ist berechtigt, Überprüfungen und Inspektionen durchzuführen. Der Auftragsverarbeiter leistet dabei angemessene Unterstützung.
|
||||
|
||||
## § 11 Haftung
|
||||
|
||||
Die Haftung der Parteien für Datenschutzverstöße richtet sich nach Art. 82 DSGVO sowie den Regelungen des zugrundeliegenden Hauptvertrags.
|
||||
|
||||
## § 12 Anwendbares Recht und Gerichtsstand
|
||||
|
||||
Für diesen Vertrag gilt deutsches Recht. Gerichtsstand ist {{CONTROLLER_CITY}}.
|
||||
|
||||
**Zuständige Aufsichtsbehörde:** {{SUPERVISORY_AUTHORITY}}
|
||||
$template$,
|
||||
'mit', 'MIT License', 'BreakPilot Compliance',
|
||||
FALSE, TRUE, '1.0.0', 'published',
|
||||
NULL, NULL, NULL, NULL,
|
||||
'Self-authored by BreakPilot Compliance (MIT License, 2026-03-04). '
|
||||
'Legal basis: DSGVO Art. 28, Art. 32, Art. 33, Art. 82. '
|
||||
'Structural reference: EU Commission standard contractual clauses for controllers and processors (Public Domain). '
|
||||
'No third-party text copied.',
|
||||
'[{"source":"Self-authored","license":"MIT","author":"BreakPilot Compliance","created":"2026-03-04","legal_basis":"DSGVO Art. 28"},{"source":"EU Commission SCCs","url":"https://eur-lex.europa.eu/legal-content/DE/TXT/?uri=CELEX%3A32021D0914","license":"Public Domain (EU legislative text)","note":"Structure reference only, no text copied"}]'::jsonb
|
||||
) ON CONFLICT DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 4. New Template: Widerrufsbelehrung (DE)
|
||||
-- document_type: withdrawal_policy | language: de
|
||||
-- Basis: Amtliche Musterwiderrufsbelehrung EGBGB Anlage 1 (§5 UrhG, gemeinfreilich)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
document_type, title, description, language, jurisdiction,
|
||||
placeholders, content,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
'withdrawal_policy',
|
||||
'Widerrufsbelehrung & Widerrufsformular',
|
||||
'Gesetzeskonforme Widerrufsbelehrung für Fernabsatzverträge nach BGB §355, §356 und EGBGB Anlage 1 Muster. Inkl. Widerrufsformular.',
|
||||
'de', 'DE',
|
||||
'["{{COMPANY_NAME}}", "{{COMPANY_ADDRESS}}", "{{COMPANY_CITY}}", "{{CONTACT_EMAIL}}", "{{COMPANY_PHONE}}", "{{WEBSITE_URL}}", "{{SERVICE_TYPE}}"]'::jsonb,
|
||||
$template$# Widerrufsbelehrung
|
||||
|
||||
## Widerrufsrecht
|
||||
|
||||
Sie haben das Recht, binnen vierzehn Tagen ohne Angabe von Gründen diesen Vertrag zu widerrufen.
|
||||
|
||||
Die Widerrufsfrist beträgt vierzehn Tage ab dem Tag des Vertragsabschlusses.
|
||||
|
||||
Um Ihr Widerrufsrecht auszuüben, müssen Sie uns
|
||||
|
||||
**{{COMPANY_NAME}}**
|
||||
{{COMPANY_ADDRESS}}
|
||||
{{COMPANY_CITY}}
|
||||
E-Mail: {{CONTACT_EMAIL}}
|
||||
Telefon: {{COMPANY_PHONE}}
|
||||
|
||||
mittels einer eindeutigen Erklärung (z. B. ein mit der Post versandter Brief oder eine E-Mail) über Ihren Entschluss, diesen Vertrag zu widerrufen, informieren. Sie können dafür das beigefügte Muster-Widerrufsformular verwenden, das jedoch nicht vorgeschrieben ist.
|
||||
|
||||
Zur Wahrung der Widerrufsfrist reicht es aus, dass Sie die Mitteilung über die Ausübung des Widerrufsrechts vor Ablauf der Widerrufsfrist absenden.
|
||||
|
||||
## Folgen des Widerrufs
|
||||
|
||||
Wenn Sie diesen Vertrag widerrufen, haben wir Ihnen alle Zahlungen, die wir von Ihnen erhalten haben, einschließlich der Lieferkosten (mit Ausnahme der zusätzlichen Kosten, die sich daraus ergeben, dass Sie eine andere Art der Lieferung als die von uns angebotene, günstigste Standardlieferung gewählt haben), unverzüglich und spätestens binnen vierzehn Tagen ab dem Tag zurückzuzahlen, an dem die Mitteilung über Ihren Widerruf dieses Vertrags bei uns eingegangen ist. Für diese Rückzahlung verwenden wir dasselbe Zahlungsmittel, das Sie bei der ursprünglichen Transaktion eingesetzt haben, es sei denn, mit Ihnen wurde ausdrücklich etwas anderes vereinbart; in keinem Fall werden Ihnen wegen dieser Rückzahlung Entgelte berechnet.
|
||||
|
||||
## Erlöschen des Widerrufsrechts bei digitalen Inhalten
|
||||
|
||||
Bei einem Vertrag über die Lieferung von nicht auf einem körperlichen Datenträger befindlichen digitalen Inhalten erlischt das Widerrufsrecht, wenn wir mit der Ausführung des Vertrags begonnen haben, nachdem Sie:
|
||||
|
||||
- ausdrücklich zugestimmt haben, dass wir mit der Ausführung des Vertrags vor Ablauf der Widerrufsfrist beginnen, und
|
||||
- Ihre Kenntnis davon bestätigt haben, dass Sie durch Ihre Zustimmung mit Beginn der Ausführung des Vertrags Ihr Widerrufsrecht verlieren.
|
||||
|
||||
## Ausnahmen vom Widerrufsrecht
|
||||
|
||||
Das Widerrufsrecht besteht nicht bei Verträgen über die Lieferung von Waren, die schnell verderben können, über die Lieferung versiegelter Waren, die aus Gründen des Gesundheitsschutzes oder der Hygiene nicht zur Rückgabe geeignet sind, und weiteren in § 312g Abs. 2 BGB genannten Ausnahmen.
|
||||
|
||||
---
|
||||
|
||||
## Muster-Widerrufsformular
|
||||
|
||||
*(Wenn Sie den Vertrag widerrufen wollen, dann füllen Sie bitte dieses Formular aus und senden Sie es zurück.)*
|
||||
|
||||
An:
|
||||
**{{COMPANY_NAME}}**
|
||||
{{COMPANY_ADDRESS}}
|
||||
{{COMPANY_CITY}}
|
||||
E-Mail: {{CONTACT_EMAIL}}
|
||||
|
||||
Hiermit widerrufe(n) ich/wir (*) den von mir/uns (*) abgeschlossenen Vertrag über den Kauf der folgenden Waren (*) / die Erbringung der folgenden Dienstleistung (*)
|
||||
|
||||
Bestellt am (*) / erhalten am (*)
|
||||
|
||||
Name des/der Verbraucher(s)
|
||||
|
||||
Anschrift des/der Verbraucher(s)
|
||||
|
||||
Unterschrift des/der Verbraucher(s) (nur bei Mitteilung auf Papier)
|
||||
|
||||
Datum
|
||||
|
||||
(*) Unzutreffendes streichen.
|
||||
$template$,
|
||||
'public_domain', 'Public Domain / Gemeinfrei', 'BreakPilot Compliance',
|
||||
FALSE, TRUE, '1.0.0', 'published',
|
||||
'https://www.gesetze-im-internet.de/egbgb/anlage_1.html',
|
||||
'https://www.gesetze-im-internet.de/egbgb/',
|
||||
'Anlage 1 (zu Art. 246a § 1 Abs. 2 Satz 2 EGBGB)',
|
||||
NOW(),
|
||||
'Basiert auf der amtlichen Musterwiderrufsbelehrung gemäß EGBGB Anlage 1 (zu Art. 246a § 1 Abs. 2 Satz 2). '
|
||||
'Gesetzestexte sind gemäß § 5 UrhG gemeinfrei (kein Urheberrechtsschutz). '
|
||||
'Quelle: https://www.gesetze-im-internet.de/egbgb/anlage_1.html (Bundesministerium der Justiz). '
|
||||
'Anpassungen und Formatierung: BreakPilot Compliance (MIT License, 2026-03-04).',
|
||||
'[{"source":"Amtliche Musterwiderrufsbelehrung EGBGB Anlage 1","url":"https://www.gesetze-im-internet.de/egbgb/anlage_1.html","license":"Public Domain gemäß §5 UrhG (Gesetzestext)","author":"Bundesministerium der Justiz / Bundesministerium für Wirtschaft","retrieved_at":"2026-03-04","legal_basis":"Art. 246a §1 Abs. 2 Satz 2 EGBGB, §355 BGB, §356 BGB"}]'::jsonb
|
||||
) ON CONFLICT DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 5. New Template: Cookie-Banner-Text / Cookie Policy (DE)
|
||||
-- document_type: cookie_policy | language: de
|
||||
-- Self-authored MIT. Reference: TTDSG §25, DSGVO Art. 6 Abs. 1a.
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
document_type, title, description, language, jurisdiction,
|
||||
placeholders, content,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
'cookie_policy',
|
||||
'Cookie-Richtlinie & Einwilligungstext (TTDSG/DSGVO)',
|
||||
'Vollständige Cookie-Richtlinie nach TTDSG §25 und DSGVO Art. 6 Abs. 1a. Inkl. Texte für Cookie-Banner (Einwilligung, Ablehnen, Einstellungen).',
|
||||
'de', 'DE',
|
||||
'["{{COMPANY_NAME}}", "{{CONTACT_EMAIL}}", "{{PRIVACY_POLICY_URL}}", "{{WEBSITE_URL}}", "{{VERSION_DATE}}"]'::jsonb,
|
||||
$template$# Cookie-Richtlinie
|
||||
|
||||
*Stand: {{VERSION_DATE}} | {{WEBSITE_URL}}*
|
||||
|
||||
## Was sind Cookies?
|
||||
|
||||
Cookies sind kleine Textdateien, die von Websites auf Ihrem Endgerät (Computer, Smartphone, Tablet) gespeichert werden. Sie ermöglichen es Websites, Einstellungen zu merken, Nutzer wiederzuerkennen und das Nutzungserlebnis zu verbessern.
|
||||
|
||||
## Rechtsgrundlage
|
||||
|
||||
Der Einsatz von Cookies, die nicht technisch zwingend notwendig sind, setzt nach § 25 TTDSG (Telekommunikation-Telemedien-Datenschutz-Gesetz) und Art. 6 Abs. 1 lit. a DSGVO Ihre ausdrückliche Einwilligung voraus. Technisch notwendige Cookies werden auf Grundlage von § 25 Abs. 2 Nr. 2 TTDSG und Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse) eingesetzt.
|
||||
|
||||
## Kategorien von Cookies
|
||||
|
||||
### 1. Notwendige Cookies (immer aktiv)
|
||||
|
||||
Diese Cookies sind für den technischen Betrieb der Website unbedingt erforderlich. Ohne sie können grundlegende Funktionen wie Seitennavigation und Sicherheit nicht gewährleistet werden.
|
||||
|
||||
| Name | Zweck | Speicherdauer |
|
||||
|------|-------|---------------|
|
||||
| session | Session-Verwaltung | Browser-Session |
|
||||
| csrf_token | CSRF-Schutz | Browser-Session |
|
||||
| cookie_consent | Speicherung Ihrer Cookie-Einstellungen | 12 Monate |
|
||||
|
||||
### 2. Analyse-Cookies (mit Einwilligung)
|
||||
|
||||
Diese Cookies helfen uns zu verstehen, wie Besucher unsere Website nutzen. Alle Daten werden anonymisiert erhoben.
|
||||
|
||||
| Name | Anbieter | Zweck | Speicherdauer |
|
||||
|------|---------|-------|---------------|
|
||||
| _ga | Google Analytics | Nutzer-Unterscheidung | 2 Jahre |
|
||||
| _gid | Google Analytics | Sitzungs-Unterscheidung | 24 Stunden |
|
||||
|
||||
### 3. Marketing-Cookies (mit Einwilligung)
|
||||
|
||||
Diese Cookies werden eingesetzt, um Ihnen personalisierte Werbung anzuzeigen.
|
||||
|
||||
| Name | Anbieter | Zweck | Speicherdauer |
|
||||
|------|---------|-------|---------------|
|
||||
| _fbp | Meta (Facebook) | Conversion-Tracking | 90 Tage |
|
||||
|
||||
## Cookie-Einstellungen verwalten
|
||||
|
||||
Sie können Ihre Cookie-Einstellungen jederzeit ändern:
|
||||
|
||||
1. **Auf unserer Website:** Klicken Sie auf das Cookie-Symbol in der Fußzeile.
|
||||
2. **In Ihrem Browser:** Alle gängigen Browser bieten Einstellungen zur Cookie-Verwaltung. Anleitungen finden Sie in der Hilfe Ihres Browsers.
|
||||
3. **Opt-out-Links:** Google Analytics: [https://tools.google.com/dlpage/gaoptout](https://tools.google.com/dlpage/gaoptout)
|
||||
|
||||
## Widerruf der Einwilligung
|
||||
|
||||
Sie können Ihre Einwilligung jederzeit mit Wirkung für die Zukunft widerrufen, ohne dass die Rechtmäßigkeit der bis zum Widerruf erfolgten Verarbeitung berührt wird.
|
||||
|
||||
## Weitere Informationen
|
||||
|
||||
Unsere vollständige Datenschutzerklärung finden Sie unter: {{PRIVACY_POLICY_URL}}
|
||||
|
||||
Bei Fragen zur Cookie-Richtlinie: {{CONTACT_EMAIL}}
|
||||
|
||||
---
|
||||
|
||||
## Cookie-Banner-Texte (für Implementierung)
|
||||
|
||||
### Haupt-Banner-Text
|
||||
> Diese Website verwendet Cookies. Einige davon sind technisch notwendig, andere helfen uns, die Website zu verbessern und Ihnen ein besseres Nutzungserlebnis zu bieten.
|
||||
|
||||
### Einwilligung-Button
|
||||
> Alle akzeptieren
|
||||
|
||||
### Ablehnen-Button
|
||||
> Nur notwendige
|
||||
|
||||
### Einstellungen-Button
|
||||
> Einstellungen
|
||||
|
||||
### Einwilligungs-Bestätigung
|
||||
> Ich willige in die Verarbeitung meiner Daten durch Cookies gemäß der Cookie-Richtlinie ein. Diese Einwilligung kann ich jederzeit widerrufen.
|
||||
$template$,
|
||||
'mit', 'MIT License', 'BreakPilot Compliance',
|
||||
FALSE, TRUE, '1.0.0', 'published',
|
||||
NULL, NULL, NULL, NULL,
|
||||
'Self-authored by BreakPilot Compliance (MIT License, 2026-03-04). '
|
||||
'Legal basis: TTDSG §25, DSGVO Art. 6 Abs. 1a, Art. 6 Abs. 1f. '
|
||||
'No third-party text copied. '
|
||||
'Structural reference: opr.vc Cookie-Consent-Textbausteine (CC0-1.0, https://opr.vc/).',
|
||||
'[{"source":"Self-authored","license":"MIT","author":"BreakPilot Compliance","created":"2026-03-04","legal_basis":"TTDSG §25, DSGVO Art. 6"},{"source":"opr.vc Cookie-Consent-Textbausteine","url":"https://opr.vc/","license":"CC0-1.0","note":"Structural reference only, no text copied"}]'::jsonb
|
||||
) ON CONFLICT DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 6. New Template: Privacy Policy GDPR (EN)
|
||||
-- document_type: privacy_policy | language: en | jurisdiction: EU
|
||||
-- Self-authored MIT.
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
document_type, title, description, language, jurisdiction,
|
||||
placeholders, content,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
'privacy_policy',
|
||||
'Privacy Policy (GDPR-compliant, EU)',
|
||||
'Complete GDPR-compliant Privacy Policy for EU/international websites and SaaS products. Covers Articles 13 & 14 mandatory disclosures.',
|
||||
'en', 'EU',
|
||||
'["{{COMPANY_NAME}}", "{{COMPANY_ADDRESS}}", "{{COMPANY_CITY}}", "{{CONTACT_EMAIL}}", "{{DPO_NAME}}", "{{DPO_EMAIL}}", "{{SUPERVISORY_AUTHORITY}}", "{{VERSION_DATE}}", "{{WEBSITE_URL}}"]'::jsonb,
|
||||
$template$# Privacy Policy
|
||||
|
||||
*Last updated: {{VERSION_DATE}} | {{WEBSITE_URL}}*
|
||||
|
||||
## 1. Controller
|
||||
|
||||
The controller responsible for data processing within the meaning of the General Data Protection Regulation (GDPR) is:
|
||||
|
||||
**{{COMPANY_NAME}}**
|
||||
{{COMPANY_ADDRESS}}
|
||||
{{COMPANY_CITY}}
|
||||
|
||||
Email: {{CONTACT_EMAIL}}
|
||||
|
||||
## 2. Data Protection Officer
|
||||
|
||||
Our Data Protection Officer can be reached at:
|
||||
|
||||
Name: {{DPO_NAME}}
|
||||
Email: {{DPO_EMAIL}}
|
||||
|
||||
## 3. Data We Collect and Why
|
||||
|
||||
### 3.1 Server Log Files
|
||||
|
||||
When you visit our website, our web server automatically records:
|
||||
|
||||
- IP address (anonymised after 7 days)
|
||||
- Date and time of access
|
||||
- URL requested
|
||||
- Referring URL
|
||||
- Browser type and operating system
|
||||
|
||||
**Legal basis:** Art. 6(1)(f) GDPR — legitimate interest in operating a secure and stable service.
|
||||
**Retention:** 7 days, then automatically deleted.
|
||||
|
||||
### 3.2 Contact Enquiries
|
||||
|
||||
When you contact us by email or contact form, we process your email address and any other information you provide in order to respond to your enquiry.
|
||||
|
||||
**Legal basis:** Art. 6(1)(b) GDPR (contract performance or pre-contractual steps) or Art. 6(1)(f) GDPR (legitimate interest in handling enquiries).
|
||||
**Retention:** Until the enquiry is fully resolved; longer where statutory retention obligations apply.
|
||||
|
||||
### 3.3 Account Data (if applicable)
|
||||
|
||||
If you register for an account, we process name, email address, and password (stored as a hashed value). We use this data to provide the service and for account security.
|
||||
|
||||
**Legal basis:** Art. 6(1)(b) GDPR (performance of a contract).
|
||||
**Retention:** For the duration of the contractual relationship plus any applicable statutory retention periods.
|
||||
|
||||
## 4. Recipients of Personal Data
|
||||
|
||||
We use service providers who process personal data on our behalf as data processors within the meaning of Art. 28 GDPR. We have concluded Data Processing Agreements (DPAs) with all such processors. No data is shared with third parties beyond these processors unless we are legally required to do so.
|
||||
|
||||
## 5. Transfers to Third Countries
|
||||
|
||||
Data is only transferred to countries outside the EU/EEA where this is necessary for contract performance or where you have given your explicit consent. In such cases, we ensure an adequate level of protection through appropriate safeguards (e.g., EU Standard Contractual Clauses, Art. 46 GDPR).
|
||||
|
||||
## 6. Your Rights as a Data Subject
|
||||
|
||||
Under the GDPR, you have the following rights:
|
||||
|
||||
- **Right of access** (Art. 15 GDPR): You may request information about the personal data we hold about you.
|
||||
- **Right to rectification** (Art. 16 GDPR): You may request correction of inaccurate data.
|
||||
- **Right to erasure** (Art. 17 GDPR): You may request deletion of your data under certain conditions.
|
||||
- **Right to restriction** (Art. 18 GDPR): You may request restriction of processing.
|
||||
- **Right to data portability** (Art. 20 GDPR): You may receive your data in a machine-readable format.
|
||||
- **Right to object** (Art. 21 GDPR): You may object to processing based on legitimate interests.
|
||||
- **Right to withdraw consent** (Art. 7(3) GDPR): Where processing is based on consent, you may withdraw it at any time without affecting the lawfulness of prior processing.
|
||||
|
||||
To exercise your rights, contact us at: {{CONTACT_EMAIL}}
|
||||
|
||||
## 7. Right to Lodge a Complaint
|
||||
|
||||
You have the right to lodge a complaint with the supervisory authority responsible for us:
|
||||
|
||||
{{SUPERVISORY_AUTHORITY}}
|
||||
|
||||
You may also contact the supervisory authority in the EU Member State where you live or work.
|
||||
|
||||
## 8. Automated Decision-Making
|
||||
|
||||
We do not use automated decision-making, including profiling, which produces legal or similarly significant effects, unless we have obtained your explicit consent or are legally required to do so.
|
||||
|
||||
## 9. Changes to This Policy
|
||||
|
||||
We may update this Privacy Policy from time to time. The current version is always available at {{WEBSITE_URL}}. The date of the most recent revision is shown at the top of this page.
|
||||
$template$,
|
||||
'mit', 'MIT License', 'BreakPilot Compliance',
|
||||
FALSE, TRUE, '1.0.0', 'published',
|
||||
NULL, NULL, NULL, NULL,
|
||||
'Self-authored by BreakPilot Compliance (MIT License, 2026-03-04). '
|
||||
'Legal basis: GDPR Articles 13, 14, 15–22. '
|
||||
'Structural reference: github/site-policy (CC0-1.0, https://github.com/github/site-policy) and '
|
||||
'fortrabbit/legal (Public Domain, https://github.com/fortrabbit/legal). '
|
||||
'No third-party text copied verbatim.',
|
||||
'[{"source":"Self-authored","license":"MIT","author":"BreakPilot Compliance","created":"2026-03-04","legal_basis":"GDPR Art. 13, 14, 15-22"},{"source":"github/site-policy","url":"https://github.com/github/site-policy","license":"CC0-1.0","note":"Structural reference only"},{"source":"fortrabbit/legal","url":"https://github.com/fortrabbit/legal","license":"Public Domain (do what you want)","note":"Structural reference only"}]'::jsonb
|
||||
) ON CONFLICT DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 7. New Template: Terms of Service — EU (EN)
|
||||
-- document_type: terms_of_service | language: en | jurisdiction: EU
|
||||
-- Self-authored MIT. Includes EU consumer rights (Directive 2011/83/EU).
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
document_type, title, description, language, jurisdiction,
|
||||
placeholders, content,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
'terms_of_service',
|
||||
'Terms of Service (EU-compliant)',
|
||||
'Terms of Service for EU/international SaaS and online services. Includes EU consumer rights (Directive 2011/83/EU), GDPR reference, and withdrawal rights for consumers.',
|
||||
'en', 'EU',
|
||||
'["{{COMPANY_NAME}}", "{{SERVICE_DESCRIPTION}}", "{{PRICING_SECTION}}", "{{PAYMENT_TERMS}}", "{{COMPANY_CITY}}", "{{PRIVACY_POLICY_URL}}", "{{VERSION_DATE}}", "{{CONTACT_EMAIL}}", "{{WEBSITE_URL}}"]'::jsonb,
|
||||
$template$# Terms of Service
|
||||
|
||||
**{{COMPANY_NAME}}**
|
||||
*Effective: {{VERSION_DATE}} | {{WEBSITE_URL}}*
|
||||
|
||||
---
|
||||
|
||||
## 1. Scope
|
||||
|
||||
1.1 These Terms of Service ("Terms") govern all contracts between **{{COMPANY_NAME}}** ("Provider", "we", "us") and the customer ("you") for use of the services offered.
|
||||
|
||||
1.2 Deviating terms and conditions of the customer are not recognised unless the Provider expressly agrees to them in writing.
|
||||
|
||||
1.3 These Terms apply to both business customers (B2B) and consumers (B2C) unless stated otherwise. Where these Terms differentiate between the two, the applicable definition is that of the relevant national law of the EU Member State where you are resident.
|
||||
|
||||
## 2. Services
|
||||
|
||||
2.1 The Provider offers the following services: {{SERVICE_DESCRIPTION}}
|
||||
|
||||
2.2 The Provider is entitled to have services performed by third parties (sub-processors).
|
||||
|
||||
2.3 The exact scope of services is set out in the applicable product description or individual offer.
|
||||
|
||||
## 3. Conclusion of Contract
|
||||
|
||||
3.1 The presentation of services on the Provider's website does not constitute a binding offer but an invitation to place an order.
|
||||
|
||||
3.2 You place a binding order by completing the checkout process or accepting a written offer.
|
||||
|
||||
3.3 The Provider may accept your order within 5 business days. Acceptance is effected by an explicit order confirmation or by provision of the service.
|
||||
|
||||
## 4. Prices and Payment
|
||||
|
||||
{{PRICING_SECTION}}
|
||||
|
||||
**Payment terms:** {{PAYMENT_TERMS}}
|
||||
|
||||
All prices are exclusive of applicable VAT unless expressly stated as gross prices.
|
||||
|
||||
In the event of late payment, we reserve the right to charge statutory interest on arrears in accordance with the applicable law of your EU Member State.
|
||||
|
||||
## 5. Right of Withdrawal for Consumers (EU)
|
||||
|
||||
If you are a consumer within the meaning of the applicable EU consumer law, you have the right to withdraw from this contract within **14 days** without giving any reason.
|
||||
|
||||
The withdrawal period expires 14 days from the day of conclusion of the contract.
|
||||
|
||||
To exercise the right of withdrawal, you must inform us ({{COMPANY_NAME}}, {{CONTACT_EMAIL}}) of your decision to withdraw from this contract by an unequivocal statement (e.g., a letter sent by post or an email).
|
||||
|
||||
**Exception for digital content:** The right of withdrawal expires for contracts for the supply of digital content not on a tangible medium if we have begun performance of the contract after you have given your explicit prior consent that we begin performance before the expiry of the withdrawal period, and you acknowledged that you thereby lose your right of withdrawal.
|
||||
|
||||
## 6. Warranty and Liability
|
||||
|
||||
6.1 We are liable without limitation for damages arising from injury to life, limb or health, and for damages caused by our wilful misconduct or gross negligence.
|
||||
|
||||
6.2 For any other damages, we are liable only for breach of a fundamental contractual obligation (cardinal obligation). In the event of slight negligence, liability is limited to the foreseeable damage typical for this type of contract.
|
||||
|
||||
6.3 The above limitations do not apply where we have given a guarantee or where claims arise under applicable product liability law.
|
||||
|
||||
6.4 For loss of data, our liability is limited to the damage that would have arisen even if you had carried out proper and regular data backups.
|
||||
|
||||
## 7. Data Protection
|
||||
|
||||
We process personal data in accordance with our Privacy Policy, available at {{PRIVACY_POLICY_URL}}. The Privacy Policy forms part of these Terms.
|
||||
|
||||
## 8. Governing Law and Jurisdiction
|
||||
|
||||
8.1 These Terms are governed by the laws of the Federal Republic of Germany, excluding the UN Convention on Contracts for the International Sale of Goods (CISG). Where you are a consumer, this choice of law does not deprive you of the protection afforded by mandatory provisions of the law of the country where you have your habitual residence.
|
||||
|
||||
8.2 For disputes with business customers, the exclusive place of jurisdiction is {{COMPANY_CITY}}.
|
||||
|
||||
8.3 The European Commission provides a platform for online dispute resolution (ODR): [https://ec.europa.eu/consumers/odr](https://ec.europa.eu/consumers/odr). Our email address for ODR purposes: {{CONTACT_EMAIL}}. We are not obliged to participate in dispute resolution proceedings before a consumer arbitration board.
|
||||
|
||||
## 9. Severability
|
||||
|
||||
If any provision of these Terms is or becomes invalid, the validity of the remaining provisions shall not be affected. The invalid provision shall be replaced by a valid provision that comes closest to the economic purpose of the invalid one.
|
||||
$template$,
|
||||
'mit', 'MIT License', 'BreakPilot Compliance',
|
||||
FALSE, TRUE, '1.0.0', 'published',
|
||||
NULL, NULL, NULL, NULL,
|
||||
'Self-authored by BreakPilot Compliance (MIT License, 2026-03-04). '
|
||||
'Legal basis: EU Consumer Rights Directive (2011/83/EU), GDPR, BGB §305ff. '
|
||||
'Structural reference: fortrabbit/legal terms-en.md (Public Domain, https://github.com/fortrabbit/legal) and '
|
||||
'github/site-policy (CC0-1.0, https://github.com/github/site-policy). '
|
||||
'No third-party text copied verbatim.',
|
||||
'[{"source":"Self-authored","license":"MIT","author":"BreakPilot Compliance","created":"2026-03-04","legal_basis":"EU Directive 2011/83/EU, GDPR, BGB §305ff."},{"source":"fortrabbit/legal (terms-en.md)","url":"https://github.com/fortrabbit/legal/blob/master/terms-en.md","license":"Public Domain (do what you want)","note":"Structural reference only"},{"source":"github/site-policy","url":"https://github.com/github/site-policy","license":"CC0-1.0","note":"Structural reference only"}]'::jsonb
|
||||
) ON CONFLICT DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 8. New Template: Data Processing Agreement — GDPR Art. 28 (EN)
|
||||
-- document_type: data_processing_agreement | language: en | jurisdiction: EU
|
||||
-- Self-authored MIT.
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO compliance_legal_templates (
|
||||
document_type, title, description, language, jurisdiction,
|
||||
placeholders, content,
|
||||
license_id, license_name, source_name,
|
||||
attribution_required, is_complete_document, version, status,
|
||||
source_url, source_repo, source_file_path, source_retrieved_at,
|
||||
attribution_text, inspiration_sources
|
||||
) VALUES (
|
||||
'data_processing_agreement',
|
||||
'Data Processing Agreement (GDPR Art. 28)',
|
||||
'Complete Data Processing Agreement (DPA) for EU/international services. Compliant with GDPR Article 28 requirements including TOMs, sub-processor management, and breach notification.',
|
||||
'en', 'EU',
|
||||
'["{{CONTROLLER_NAME}}", "{{CONTROLLER_ADDRESS}}", "{{CONTROLLER_CITY}}", "{{PROCESSOR_NAME}}", "{{PROCESSOR_ADDRESS}}", "{{PROCESSOR_CITY}}", "{{SERVICE_DESCRIPTION}}", "{{DATA_CATEGORIES}}", "{{DATA_SUBJECTS}}", "{{CONTRACT_DATE}}", "{{SUPERVISORY_AUTHORITY}}"]'::jsonb,
|
||||
$template$# Data Processing Agreement (DPA)
|
||||
|
||||
*Pursuant to Art. 28 of the General Data Protection Regulation (GDPR)*
|
||||
|
||||
Concluded on {{CONTRACT_DATE}} between:
|
||||
|
||||
**Controller:**
|
||||
{{CONTROLLER_NAME}}, {{CONTROLLER_ADDRESS}}, {{CONTROLLER_CITY}}
|
||||
(hereinafter "Controller")
|
||||
|
||||
and
|
||||
|
||||
**Processor:**
|
||||
{{PROCESSOR_NAME}}, {{PROCESSOR_ADDRESS}}, {{PROCESSOR_CITY}}
|
||||
(hereinafter "Processor")
|
||||
|
||||
---
|
||||
|
||||
## 1. Subject Matter and Duration
|
||||
|
||||
1.1 The Processor processes personal data on behalf of the Controller in connection with the following services: {{SERVICE_DESCRIPTION}}
|
||||
|
||||
1.2 Processing shall take place for the duration of the underlying main service agreement between the parties.
|
||||
|
||||
## 2. Nature and Purpose of Processing
|
||||
|
||||
**Categories of personal data:** {{DATA_CATEGORIES}}
|
||||
|
||||
**Categories of data subjects:** {{DATA_SUBJECTS}}
|
||||
|
||||
**Purpose of processing:** To provide the services described in clause 1 on behalf of the Controller.
|
||||
|
||||
## 3. Instructions
|
||||
|
||||
3.1 The Processor shall process personal data only on documented instructions from the Controller.
|
||||
|
||||
3.2 If the Processor is of the opinion that an instruction infringes the GDPR or other applicable data protection law, the Processor shall immediately inform the Controller.
|
||||
|
||||
3.3 Instructions shall be issued in writing and documented by both parties.
|
||||
|
||||
## 4. Confidentiality
|
||||
|
||||
The Processor shall ensure that persons authorised to process personal data have committed themselves to confidentiality or are subject to an appropriate statutory obligation of confidentiality.
|
||||
|
||||
## 5. Technical and Organisational Measures (TOMs)
|
||||
|
||||
The Processor shall implement all measures required under Art. 32 GDPR, including at minimum:
|
||||
|
||||
- **Physical access control:** Preventing unauthorised physical access to data processing systems
|
||||
- **System access control:** Authentication mechanisms (password policy, MFA where applicable)
|
||||
- **Data access control:** Need-to-know principle, role-based access control (RBAC)
|
||||
- **Separation control:** Logical separation of data belonging to different controllers
|
||||
- **Encryption:** TLS 1.3 for data in transit; encryption of sensitive data at rest
|
||||
- **Pseudonymisation:** Applied where technically feasible and appropriate
|
||||
- **Resilience:** Regular backups; tested restoration procedures
|
||||
- **Review procedures:** Regular testing and evaluation of the effectiveness of TOMs
|
||||
|
||||
## 6. Sub-processors
|
||||
|
||||
6.1 The Processor shall not engage sub-processors without prior written authorisation of the Controller.
|
||||
|
||||
6.2 Where the Controller grants general authorisation, the Processor shall inform the Controller of any intended changes concerning the addition or replacement of sub-processors, thereby giving the Controller the opportunity to object to such changes.
|
||||
|
||||
6.3 The Processor shall impose the same data protection obligations on any sub-processor as set out in this DPA.
|
||||
|
||||
## 7. Assistance to the Controller
|
||||
|
||||
The Processor shall assist the Controller, taking into account the nature of the processing, by appropriate technical and organisational measures, insofar as possible, in fulfilling the Controller's obligations to:
|
||||
|
||||
- respond to requests from data subjects exercising their rights (Arts. 15–22 GDPR)
|
||||
- comply with obligations under Arts. 32–36 GDPR (security, DPIA, breach notification)
|
||||
|
||||
## 8. Deletion and Return of Data
|
||||
|
||||
Upon termination or expiry of this agreement, the Processor shall, at the Controller's choice, delete or return all personal data and delete existing copies, unless EU or Member State law requires storage.
|
||||
|
||||
## 9. Personal Data Breaches
|
||||
|
||||
The Processor shall notify the Controller without undue delay (and within 24 hours of becoming aware) of any personal data breach. The notification shall include at minimum the information required under Art. 33(3) GDPR.
|
||||
|
||||
## 10. Audit Rights
|
||||
|
||||
10.1 The Processor shall make available to the Controller all information necessary to demonstrate compliance with obligations under Art. 28 GDPR.
|
||||
|
||||
10.2 The Processor shall allow for and contribute to audits, including inspections, conducted by the Controller or an auditor mandated by the Controller.
|
||||
|
||||
## 11. Liability
|
||||
|
||||
The liability of both parties for breaches of this DPA and the GDPR shall be governed by Art. 82 GDPR and the provisions of the underlying main service agreement.
|
||||
|
||||
## 12. Governing Law
|
||||
|
||||
This DPA is governed by the law of the country of the Controller's establishment, subject to mandatory GDPR requirements. The competent supervisory authority is: {{SUPERVISORY_AUTHORITY}}
|
||||
$template$,
|
||||
'mit', 'MIT License', 'BreakPilot Compliance',
|
||||
FALSE, TRUE, '1.0.0', 'published',
|
||||
NULL, NULL, NULL, NULL,
|
||||
'Self-authored by BreakPilot Compliance (MIT License, 2026-03-04). '
|
||||
'Legal basis: GDPR Art. 28, Art. 32, Art. 33, Art. 82. '
|
||||
'Structural reference: fortrabbit/legal data-processing-en.md (Public Domain, https://github.com/fortrabbit/legal) and '
|
||||
'EU Commission Standard Contractual Clauses (Public Domain, https://eur-lex.europa.eu). '
|
||||
'No third-party text copied verbatim.',
|
||||
'[{"source":"Self-authored","license":"MIT","author":"BreakPilot Compliance","created":"2026-03-04","legal_basis":"GDPR Art. 28"},{"source":"fortrabbit/legal (data-processing-en.md)","url":"https://github.com/fortrabbit/legal","license":"Public Domain (do what you want)","note":"Structural reference only"},{"source":"EU Commission SCCs","url":"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32021D0914","license":"Public Domain (EU legislative text)","note":"Structure reference only, no text copied"}]'::jsonb
|
||||
) ON CONFLICT DO NOTHING;
|
||||
@@ -55,6 +55,13 @@ def make_template_row(overrides=None):
|
||||
"status": "published",
|
||||
"created_at": datetime(2024, 1, 1),
|
||||
"updated_at": datetime(2024, 1, 1),
|
||||
# Attribution columns (Migration 019)
|
||||
"source_url": None,
|
||||
"source_repo": None,
|
||||
"source_file_path": None,
|
||||
"source_retrieved_at": None,
|
||||
"attribution_text": "Self-authored by BreakPilot Compliance (MIT License, 2026-03-04).",
|
||||
"inspiration_sources": [{"source": "Self-authored", "license": "MIT"}],
|
||||
}
|
||||
if overrides:
|
||||
data.update(overrides)
|
||||
@@ -114,11 +121,39 @@ class TestLegalTemplateSchemas:
|
||||
assert d == {"status": "archived", "title": "Neue DSE"}
|
||||
|
||||
def test_valid_document_types_constant(self):
|
||||
"""VALID_DOCUMENT_TYPES contains the 3 expected types."""
|
||||
"""VALID_DOCUMENT_TYPES contains all 6 expected types."""
|
||||
assert "privacy_policy" in VALID_DOCUMENT_TYPES
|
||||
assert "terms_of_service" in VALID_DOCUMENT_TYPES
|
||||
assert "impressum" in VALID_DOCUMENT_TYPES
|
||||
assert len(VALID_DOCUMENT_TYPES) == 3
|
||||
assert "data_processing_agreement" in VALID_DOCUMENT_TYPES
|
||||
assert "withdrawal_policy" in VALID_DOCUMENT_TYPES
|
||||
assert "cookie_policy" in VALID_DOCUMENT_TYPES
|
||||
assert len(VALID_DOCUMENT_TYPES) == 6
|
||||
|
||||
def test_create_schema_attribution_fields(self):
|
||||
"""LegalTemplateCreate accepts attribution fields."""
|
||||
payload = LegalTemplateCreate(
|
||||
document_type="data_processing_agreement",
|
||||
title="AVV Test",
|
||||
content="# AVV\n{{CONTROLLER_NAME}}",
|
||||
source_url="https://github.com/example/legal",
|
||||
source_repo="https://github.com/example/legal",
|
||||
source_file_path="dpa-de.md",
|
||||
attribution_text="Self-authored MIT.",
|
||||
inspiration_sources=[{"source": "test", "license": "MIT"}],
|
||||
)
|
||||
assert payload.source_url == "https://github.com/example/legal"
|
||||
assert payload.attribution_text == "Self-authored MIT."
|
||||
assert len(payload.inspiration_sources) == 1
|
||||
|
||||
def test_update_schema_inspiration_sources(self):
|
||||
"""LegalTemplateUpdate accepts inspiration_sources list."""
|
||||
payload = LegalTemplateUpdate(
|
||||
inspiration_sources=[{"source": "Self-authored", "license": "MIT"}]
|
||||
)
|
||||
d = payload.model_dump(exclude_unset=True)
|
||||
assert "inspiration_sources" in d
|
||||
assert d["inspiration_sources"][0]["license"] == "MIT"
|
||||
|
||||
def test_valid_statuses_constant(self):
|
||||
"""VALID_STATUSES contains expected values."""
|
||||
@@ -267,19 +302,23 @@ class TestLegalTemplateSearch:
|
||||
assert res.status_code == 404
|
||||
|
||||
def test_status_endpoint_returns_200(self):
|
||||
"""GET /legal-templates/status returns count structure."""
|
||||
"""GET /legal-templates/status returns count structure with all 6 types."""
|
||||
row = MagicMock()
|
||||
row._mapping = {
|
||||
"total": 3, "published": 3, "draft": 0, "archived": 0,
|
||||
"privacy_policy": 1, "terms_of_service": 1, "impressum": 1
|
||||
"total": 9, "published": 9, "draft": 0, "archived": 0,
|
||||
"privacy_policy": 2, "terms_of_service": 2, "impressum": 1,
|
||||
"data_processing_agreement": 2, "withdrawal_policy": 1, "cookie_policy": 1,
|
||||
}
|
||||
self.db.execute.return_value.fetchone.return_value = row
|
||||
res = self.client.get("/legal-templates/status")
|
||||
assert res.status_code == 200
|
||||
data = res.json()
|
||||
assert data["total"] == 3
|
||||
assert data["total"] == 9
|
||||
assert "by_type" in data
|
||||
assert "by_status" in data
|
||||
assert "data_processing_agreement" in data["by_type"]
|
||||
assert "withdrawal_policy" in data["by_type"]
|
||||
assert "cookie_policy" in data["by_type"]
|
||||
|
||||
def test_sources_endpoint_returns_list(self):
|
||||
"""GET /legal-templates/sources returns sources list."""
|
||||
@@ -353,3 +392,73 @@ class TestLegalTemplateSeed:
|
||||
assert result["license_name"] == "MIT License"
|
||||
assert result["attribution_required"] is False
|
||||
assert result["is_complete_document"] is True
|
||||
|
||||
def test_dpa_template_has_controller_processor_placeholders(self):
|
||||
"""AVV/DPA template has CONTROLLER_NAME and PROCESSOR_NAME placeholders."""
|
||||
row = make_template_row({
|
||||
"document_type": "data_processing_agreement",
|
||||
"placeholders": [
|
||||
"{{CONTROLLER_NAME}}", "{{CONTROLLER_ADDRESS}}", "{{CONTROLLER_CITY}}",
|
||||
"{{PROCESSOR_NAME}}", "{{PROCESSOR_ADDRESS}}", "{{PROCESSOR_CITY}}",
|
||||
"{{SERVICE_DESCRIPTION}}", "{{DATA_CATEGORIES}}", "{{DATA_SUBJECTS}}",
|
||||
"{{CONTRACT_DATE}}", "{{SUPERVISORY_AUTHORITY}}"
|
||||
]
|
||||
})
|
||||
result = _row_to_dict(row)
|
||||
assert "{{CONTROLLER_NAME}}" in result["placeholders"]
|
||||
assert "{{PROCESSOR_NAME}}" in result["placeholders"]
|
||||
assert "{{DATA_CATEGORIES}}" in result["placeholders"]
|
||||
|
||||
def test_withdrawal_policy_has_public_domain_license(self):
|
||||
"""Widerrufsbelehrung uses Public Domain license (based on §5 UrhG source)."""
|
||||
row = make_template_row({
|
||||
"document_type": "withdrawal_policy",
|
||||
"license_id": "public_domain",
|
||||
"license_name": "Public Domain / Gemeinfrei",
|
||||
"source_url": "https://www.gesetze-im-internet.de/egbgb/anlage_1.html",
|
||||
"attribution_text": "Basiert auf der amtlichen Musterwiderrufsbelehrung.",
|
||||
"inspiration_sources": [{"source": "EGBGB Anlage 1", "license": "Public Domain gemäß §5 UrhG"}],
|
||||
})
|
||||
result = _row_to_dict(row)
|
||||
assert result["document_type"] == "withdrawal_policy"
|
||||
assert result["license_id"] == "public_domain"
|
||||
assert result["source_url"] == "https://www.gesetze-im-internet.de/egbgb/anlage_1.html"
|
||||
assert result["attribution_text"] is not None
|
||||
|
||||
def test_attribution_text_stored_in_row(self):
|
||||
"""attribution_text and inspiration_sources are returned in _row_to_dict."""
|
||||
row = make_template_row({
|
||||
"attribution_text": "Self-authored by BreakPilot Compliance (MIT License, 2026-03-04).",
|
||||
"inspiration_sources": [{"source": "Self-authored", "license": "MIT"}],
|
||||
"source_url": None,
|
||||
"source_repo": None,
|
||||
"source_file_path": None,
|
||||
"source_retrieved_at": None,
|
||||
})
|
||||
result = _row_to_dict(row)
|
||||
assert "Self-authored" in result["attribution_text"]
|
||||
assert result["inspiration_sources"][0]["license"] == "MIT"
|
||||
|
||||
def test_english_privacy_policy_eu_jurisdiction(self):
|
||||
"""EN Privacy Policy template uses EU jurisdiction."""
|
||||
row = make_template_row({
|
||||
"document_type": "privacy_policy",
|
||||
"language": "en",
|
||||
"jurisdiction": "EU",
|
||||
"title": "Privacy Policy (GDPR-compliant, EU)",
|
||||
})
|
||||
result = _row_to_dict(row)
|
||||
assert result["language"] == "en"
|
||||
assert result["jurisdiction"] == "EU"
|
||||
|
||||
def test_cookie_policy_type_valid(self):
|
||||
"""cookie_policy is accepted as valid document_type."""
|
||||
assert "cookie_policy" in VALID_DOCUMENT_TYPES
|
||||
|
||||
def test_withdrawal_policy_type_valid(self):
|
||||
"""withdrawal_policy is accepted as valid document_type."""
|
||||
assert "withdrawal_policy" in VALID_DOCUMENT_TYPES
|
||||
|
||||
def test_dpa_type_valid(self):
|
||||
"""data_processing_agreement is accepted as valid document_type."""
|
||||
assert "data_processing_agreement" in VALID_DOCUMENT_TYPES
|
||||
|
||||
15
scripts/apply_legal_templates_attribution_migration.sh
Executable file
15
scripts/apply_legal_templates_attribution_migration.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Applying Migration 019: Legal Templates Attribution + 6 new templates..."
|
||||
/usr/local/bin/docker exec bp-compliance-backend python3 -c "
|
||||
import psycopg2, os
|
||||
conn = psycopg2.connect(os.getenv('DATABASE_URL'))
|
||||
cur = conn.cursor()
|
||||
with open('/app/migrations/019_legal_templates_attribution.sql') as f:
|
||||
cur.execute(f.read())
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
print('Migration 019 applied successfully')
|
||||
"
|
||||
echo "Done."
|
||||
Reference in New Issue
Block a user