Erweiterte Compliance-Vorlagen fuer den Document Generator: - DSFA V2: Schwellwertanalyse (9 WP248-Kriterien), SDM-basierte TOM, strukturierte Risikobewertung, KI-Modul (AI Act), Art.36-Pruefung - TOM V2: 7 SDM-Gewaehrleistungsziele, Sektor-Erweiterungen, NIS2/ISO27001/AI Act Varianten - VVT V2: 6 Branchen-Muster (IT/SaaS, Gesundheit, Handel, Handwerk, Bildung, Beratung) + allgemeine Art.30-Vorlage - AVV V2: Vollstaendiger Art.28-Vertrag mit TOM-Anlage - Verpflichtungserklaerung: Mitarbeiter-Vertraulichkeit - Art.13/14 Informationspflichten-Muster Enthalt SQL-Migrations (compliance_legal_templates), Python-Generatoren und Qdrant-Cleanup-Skript. Feature-Branch fuer spaetere Integration in breakpilot-compliance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
394 lines
19 KiB
Python
394 lines
19 KiB
Python
"""VVT template generator V2 — sector-specific VVT activity drafts.
|
|
|
|
Generates Art. 30 DS-GVO compliant VVT entries with sector-specific
|
|
standard processing activities inspired by BayLDA patterns.
|
|
"""
|
|
|
|
from typing import Optional
|
|
|
|
# -- Sector activity catalogs ------------------------------------------------
|
|
|
|
SECTOR_ACTIVITIES = {
|
|
"it_saas": [
|
|
{
|
|
"name": "SaaS-Plattformbetrieb",
|
|
"purposes": ["Bereitstellung und Betrieb der SaaS-Plattform"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO (Vertragserfullung)"],
|
|
"data_subject_categories": ["Kunden", "Endnutzer"],
|
|
"personal_data_categories": ["Stammdaten", "Nutzungsdaten", "Inhaltsdaten", "Logdaten"],
|
|
"recipient_categories": ["Hosting-Anbieter (AVV)", "Support-Dienstleister (AVV)"],
|
|
"retention_period": "90 Tage nach Vertragsende + gesetzl. Aufbewahrung",
|
|
"tom_description": "Mandantentrennung, Verschluesselung, RBAC",
|
|
"dpia_required": True,
|
|
},
|
|
{
|
|
"name": "Kundenverwaltung / CRM",
|
|
"purposes": ["Verwaltung von Kundenbeziehungen, Vertragsmanagement"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Kunden", "Ansprechpartner", "Interessenten"],
|
|
"personal_data_categories": ["Kontaktdaten", "Vertragsdaten", "Kommunikationshistorie"],
|
|
"recipient_categories": ["CRM-Anbieter (AVV)"],
|
|
"retention_period": "3 Jahre nach letztem Kontakt, 10 Jahre Rechnungsdaten",
|
|
"tom_description": "Zugriffsbeschraenkung Vertrieb/Support, Protokollierung",
|
|
},
|
|
{
|
|
"name": "E-Mail-Marketing / Newsletter",
|
|
"purposes": ["Versand von Produkt-Updates und Marketing-Newsletter"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. a DS-GVO (Einwilligung)", "UWG §7"],
|
|
"data_subject_categories": ["Newsletter-Abonnenten"],
|
|
"personal_data_categories": ["E-Mail-Adresse", "Name", "Oeffnungs-/Klickverhalten"],
|
|
"recipient_categories": ["E-Mail-Dienstleister (AVV)"],
|
|
"retention_period": "Unverzueglich nach Widerruf",
|
|
"tom_description": "Double-Opt-In, einfache Abmeldefunktion",
|
|
},
|
|
{
|
|
"name": "Webanalyse",
|
|
"purposes": ["Analyse der Website-Nutzung zur Verbesserung"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. a DS-GVO (Einwilligung via Cookie-Banner)"],
|
|
"data_subject_categories": ["Website-Besucher"],
|
|
"personal_data_categories": ["IP-Adresse (anonymisiert)", "Seitenaufrufe", "Geraeteinformationen"],
|
|
"recipient_categories": ["Analyse-Anbieter (AVV)"],
|
|
"retention_period": "14 Monate",
|
|
"tom_description": "IP-Anonymisierung, Cookie-Consent (TDDDG §25)",
|
|
},
|
|
{
|
|
"name": "Bewerbermanagement",
|
|
"purposes": ["Bearbeitung von Bewerbungen"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO i.V.m. §26 BDSG"],
|
|
"data_subject_categories": ["Bewerber"],
|
|
"personal_data_categories": ["Kontaktdaten", "Lebenslauf", "Qualifikationen"],
|
|
"recipient_categories": ["Fachabteilung"],
|
|
"retention_period": "6 Monate nach Verfahrensabschluss (AGG)",
|
|
"tom_description": "Zugriffsschutz Bewerbungsportal, verschluesselte Uebertragung",
|
|
},
|
|
{
|
|
"name": "Mitarbeiterverwaltung / HR",
|
|
"purposes": ["Personalverwaltung, Lohnabrechnung, Arbeitszeiterfassung"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b/c DS-GVO i.V.m. §26 BDSG"],
|
|
"data_subject_categories": ["Beschaeftigte"],
|
|
"personal_data_categories": ["Stammdaten", "Vertragsdaten", "Bankverbindung", "Arbeitszeiten"],
|
|
"recipient_categories": ["Lohnbuero (AVV)", "Finanzamt", "Sozialversicherungstraeger"],
|
|
"retention_period": "10 Jahre nach Austritt",
|
|
"tom_description": "Besonderer Zugriffsschutz (nur HR), verschluesselte Speicherung",
|
|
},
|
|
{
|
|
"name": "Support-Ticketing",
|
|
"purposes": ["Bearbeitung von Kundenanfragen und Stoerungsmeldungen"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Kunden", "Endnutzer"],
|
|
"personal_data_categories": ["Kontaktdaten", "Ticket-Inhalt", "Systemlogs"],
|
|
"recipient_categories": ["Support-Tool-Anbieter (AVV)"],
|
|
"retention_period": "2 Jahre nach Ticket-Schliessung",
|
|
"tom_description": "Rollenbasierter Zugriff, Pseudonymisierung in Reports",
|
|
},
|
|
{
|
|
"name": "Logging und Monitoring",
|
|
"purposes": ["Sicherheitsueberwachung, Fehleranalyse"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. f DS-GVO (berechtigtes Interesse: IT-Sicherheit)"],
|
|
"data_subject_categories": ["Plattform-Nutzer", "Administratoren"],
|
|
"personal_data_categories": ["IP-Adressen", "Zugriffszeitpunkte", "Fehlerprotokolle"],
|
|
"recipient_categories": ["Log-Management-Anbieter (AVV)"],
|
|
"retention_period": "30 Tage Anwendungslogs, 90 Tage Sicherheitslogs",
|
|
"tom_description": "Zugriffsschutz Logdaten, automatische Rotation",
|
|
},
|
|
],
|
|
"gesundheitswesen": [
|
|
{
|
|
"name": "Patientenverwaltung",
|
|
"purposes": ["Patientenakte, Behandlungsdokumentation"],
|
|
"legal_bases": ["Art. 9 Abs. 2 lit. h DS-GVO i.V.m. §630f BGB"],
|
|
"data_subject_categories": ["Patienten"],
|
|
"personal_data_categories": ["Stammdaten", "Versicherung", "Diagnosen", "Befunde (Art. 9)"],
|
|
"recipient_categories": ["PVS-Anbieter (AVV)", "Labor (AVV)", "ueberweisende Aerzte"],
|
|
"retention_period": "10 Jahre nach letzter Behandlung (§630f BGB)",
|
|
"tom_description": "Verschluesselung Patientenakte, Notfallzugriff",
|
|
"dpia_required": True,
|
|
},
|
|
{
|
|
"name": "Abrechnung (KV/PKV)",
|
|
"purposes": ["Abrechnung aerztlicher Leistungen"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. c DS-GVO", "Art. 9 Abs. 2 lit. h"],
|
|
"data_subject_categories": ["Patienten"],
|
|
"personal_data_categories": ["Stammdaten", "Versicherung", "Diagnosen (ICD)", "Leistungsziffern"],
|
|
"recipient_categories": ["KV", "PKV", "Abrechnungsstelle (AVV)"],
|
|
"retention_period": "10 Jahre (AO)",
|
|
"tom_description": "Verschluesselte Uebermittlung (KV-Connect/KIM)",
|
|
},
|
|
],
|
|
"handel": [
|
|
{
|
|
"name": "Bestellabwicklung",
|
|
"purposes": ["Bestellannahme, Versand, Rechnungsstellung"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Kunden (Besteller)"],
|
|
"personal_data_categories": ["Kontaktdaten", "Lieferadresse", "Bestelldaten", "Rechnungsdaten"],
|
|
"recipient_categories": ["Versanddienstleister", "Zahlungsanbieter (AVV)"],
|
|
"retention_period": "10 Jahre Rechnungen, 3 Jahre Bestelldaten",
|
|
"tom_description": "Verschluesselte Uebertragung, Zugriffsschutz",
|
|
},
|
|
{
|
|
"name": "Kundenkonto",
|
|
"purposes": ["Bereitstellung Kundenkonto (optional)"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. a/b DS-GVO"],
|
|
"data_subject_categories": ["Registrierte Kunden"],
|
|
"personal_data_categories": ["Stammdaten", "Passwort (gehasht)", "Bestellhistorie"],
|
|
"recipient_categories": ["Shop-Plattform (AVV)"],
|
|
"retention_period": "Sofort nach Kontoloesch-Anfrage, Rechnungen 10 Jahre",
|
|
"tom_description": "MFA-Option, bcrypt Passwortspeicherung, Gastzugang-Alternative",
|
|
},
|
|
{
|
|
"name": "Zahlungsabwicklung",
|
|
"purposes": ["Abwicklung von Zahlungsvorgaengen"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Zahlende Kunden"],
|
|
"personal_data_categories": ["Zahlungsart", "Transaktionsdaten"],
|
|
"recipient_categories": ["Payment-Service-Provider"],
|
|
"retention_period": "10 Jahre (AO)",
|
|
"tom_description": "PCI-DSS, Tokenisierung, keine direkte Kartenspeicherung",
|
|
},
|
|
],
|
|
"handwerk": [
|
|
{
|
|
"name": "Kundenauftraege und Angebotserstellung",
|
|
"purposes": ["Angebotserstellung, Auftragsabwicklung, Rechnungsstellung"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Kunden (Privat/Gewerbe)"],
|
|
"personal_data_categories": ["Kontaktdaten", "Objektadresse", "Auftrag", "Rechnungsdaten"],
|
|
"recipient_categories": ["Steuerberater", "ggf. Subunternehmer"],
|
|
"retention_period": "10 Jahre Rechnungen, 5 Jahre Gewaehrleistung",
|
|
"tom_description": "Zugriffskontrolle Auftragssystem",
|
|
},
|
|
{
|
|
"name": "Baustellendokumentation",
|
|
"purposes": ["Dokumentation Baufortschritt, Maengelprotokoll"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b/f DS-GVO"],
|
|
"data_subject_categories": ["Kunden", "Mitarbeitende"],
|
|
"personal_data_categories": ["Fotos", "Protokolle", "Abnahmedokumente"],
|
|
"recipient_categories": ["Auftraggeber", "Architekten"],
|
|
"retention_period": "5 Jahre nach Abnahme",
|
|
"tom_description": "Projektordner mit Zugriffsbeschraenkung",
|
|
},
|
|
],
|
|
"bildung": [
|
|
{
|
|
"name": "Schueler-/Studierendenverwaltung",
|
|
"purposes": ["Verwaltung von Schueler-/Studierendendaten"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. c/e DS-GVO i.V.m. Schulgesetz"],
|
|
"data_subject_categories": ["Schueler/Studierende (ggf. Minderjaehrige)", "Erziehungsberechtigte"],
|
|
"personal_data_categories": ["Stammdaten", "Kontaktdaten Erziehungsberechtigte"],
|
|
"recipient_categories": ["Schulverwaltungssoftware (AVV)", "Schulbehoerde"],
|
|
"retention_period": "Gemaess Schulgesetz (i.d.R. 5 Jahre nach Abgang)",
|
|
"tom_description": "Besonderer Zugriffsschutz, Einwilligung Erziehungsberechtigte",
|
|
"dpia_required": True,
|
|
},
|
|
{
|
|
"name": "Notenverarbeitung",
|
|
"purposes": ["Leistungsbewertung, Zeugniserstellung"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. c/e DS-GVO i.V.m. Schulgesetz"],
|
|
"data_subject_categories": ["Schueler/Studierende"],
|
|
"personal_data_categories": ["Noten", "Leistungsbewertungen", "Pruefungsergebnisse"],
|
|
"recipient_categories": ["Lehrkraefte", "Schulleitung"],
|
|
"retention_period": "Zeugniskopien 50 Jahre, Einzelnoten 2 Jahre",
|
|
"tom_description": "Zugriffsbeschraenkung auf Fachlehrkraft, verschluesselt",
|
|
},
|
|
],
|
|
"beratung": [
|
|
{
|
|
"name": "Mandantenverwaltung",
|
|
"purposes": ["Verwaltung von Mandantenbeziehungen"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Mandanten", "Ansprechpartner"],
|
|
"personal_data_categories": ["Kontaktdaten", "Vertragsdaten", "Korrespondenz"],
|
|
"recipient_categories": ["Kanzleisoftware (AVV)", "Steuerberater"],
|
|
"retention_period": "10 Jahre Rechnungen, 5 Jahre Handakten",
|
|
"tom_description": "Mandantengeheimnis, Need-to-know-Prinzip",
|
|
},
|
|
{
|
|
"name": "Projektmanagement",
|
|
"purposes": ["Planung und Steuerung von Beratungsprojekten"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b/f DS-GVO"],
|
|
"data_subject_categories": ["Projektbeteiligte"],
|
|
"personal_data_categories": ["Projektdaten", "Aufgaben", "Zeiterfassung"],
|
|
"recipient_categories": ["PM-Tool (AVV)", "Mandant"],
|
|
"retention_period": "2 Jahre nach Projektabschluss",
|
|
"tom_description": "Projektspezifische Zugriffsrechte, Mandantentrennung",
|
|
},
|
|
{
|
|
"name": "Zeiterfassung und Abrechnung",
|
|
"purposes": ["Stundenerfassung, Abrechnung gegenueber Mandanten"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO"],
|
|
"data_subject_categories": ["Berater/Mitarbeitende", "Mandanten"],
|
|
"personal_data_categories": ["Arbeitszeiten", "Taetigkeitsbeschreibungen", "Stundensaetze"],
|
|
"recipient_categories": ["Abrechnungssystem (AVV)", "Buchhaltung"],
|
|
"retention_period": "10 Jahre (AO)",
|
|
"tom_description": "Zugriff nur eigene Zeiten + Projektleitung",
|
|
},
|
|
],
|
|
}
|
|
|
|
# Industry -> Sector mapping
|
|
INDUSTRY_SECTOR_MAP = {
|
|
"technologie": "it_saas", "it": "it_saas", "saas": "it_saas", "software": "it_saas",
|
|
"it dienstleistungen": "it_saas",
|
|
"gesundheit": "gesundheitswesen", "pharma": "gesundheitswesen",
|
|
"e-commerce": "handel", "handel": "handel", "einzelhandel": "handel",
|
|
"handwerk": "handwerk", "bau": "handwerk", "kfz": "handwerk",
|
|
"bildung": "bildung", "schule": "bildung", "hochschule": "bildung",
|
|
"beratung": "beratung", "consulting": "beratung", "kanzlei": "beratung",
|
|
"recht": "beratung",
|
|
}
|
|
|
|
|
|
def generate_vvt_drafts(ctx: dict) -> list[dict]:
|
|
"""Generate VVT activity drafts, sector-specific if possible.
|
|
|
|
Args:
|
|
ctx: Flat dict from company-profile/template-context.
|
|
|
|
Returns:
|
|
List of VVT activity dicts ready for creation.
|
|
"""
|
|
company = ctx.get("company_name", "Unbekannt")
|
|
dpo = ctx.get("dpo_name", "")
|
|
sector = _detect_sector(ctx)
|
|
|
|
# Use sector-specific activities if available, else generate from systems
|
|
if sector and sector in SECTOR_ACTIVITIES:
|
|
activities = _generate_sector_vvt(ctx, sector, company, dpo)
|
|
else:
|
|
activities = _generate_system_vvt(ctx, company, dpo)
|
|
|
|
# Always add standard HR activity if not already present
|
|
has_hr = any("mitarbeiter" in a.get("name", "").lower() or "hr" in a.get("name", "").lower()
|
|
for a in activities)
|
|
if not has_hr and len(activities) > 0:
|
|
activities.append(_build_hr_activity(len(activities) + 1, company, dpo))
|
|
|
|
return activities
|
|
|
|
|
|
def _detect_sector(ctx: dict) -> Optional[str]:
|
|
industry = (ctx.get("industry") or "").lower().strip()
|
|
for keyword, sector in INDUSTRY_SECTOR_MAP.items():
|
|
if keyword in industry:
|
|
return sector
|
|
return None
|
|
|
|
|
|
def _generate_sector_vvt(ctx: dict, sector: str, company: str, dpo: str) -> list[dict]:
|
|
activities = []
|
|
sector_data = SECTOR_ACTIVITIES[sector]
|
|
|
|
for i, template in enumerate(sector_data, 1):
|
|
activity = {
|
|
"vvt_id": f"VVT-{sector.upper()[:3]}-{i:03d}",
|
|
"name": template["name"],
|
|
"description": f"Automatisch generierter VVT-Eintrag: {template['name']}",
|
|
"purposes": template["purposes"],
|
|
"legal_bases": template["legal_bases"],
|
|
"data_subject_categories": template["data_subject_categories"],
|
|
"personal_data_categories": template["personal_data_categories"],
|
|
"recipient_categories": template["recipient_categories"],
|
|
"third_country_transfers": _assess_third_country(ctx),
|
|
"retention_period": {"default": template["retention_period"]},
|
|
"tom_description": template["tom_description"],
|
|
"business_function": _infer_business_function(template["name"]),
|
|
"systems": [],
|
|
"protection_level": "HIGH" if template.get("dpia_required") else "MEDIUM",
|
|
"dpia_required": template.get("dpia_required", False),
|
|
"status": "DRAFT",
|
|
"responsible": dpo or company,
|
|
"source_sector": sector,
|
|
}
|
|
activities.append(activity)
|
|
|
|
return activities
|
|
|
|
|
|
def _generate_system_vvt(ctx: dict, company: str, dpo: str) -> list[dict]:
|
|
"""Fallback: generate VVT per processing system (original approach)."""
|
|
systems = ctx.get("processing_systems", [])
|
|
activities = []
|
|
|
|
for i, system in enumerate(systems, 1):
|
|
name = system.get("name", f"System {i}")
|
|
vendor = system.get("vendor", "")
|
|
hosting = system.get("hosting", "on-premise")
|
|
categories = system.get("personal_data_categories", [])
|
|
|
|
activity = {
|
|
"vvt_id": f"VVT-SYS-{i:03d}",
|
|
"name": f"Verarbeitung in {name}",
|
|
"description": f"VVT-Eintrag fuer System '{name}'"
|
|
+ (f" (Anbieter: {vendor})" if vendor else ""),
|
|
"purposes": [f"Datenverarbeitung via {name}"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b DS-GVO (Vertragserfullung)"],
|
|
"data_subject_categories": [],
|
|
"personal_data_categories": categories,
|
|
"recipient_categories": [vendor] if vendor else [],
|
|
"third_country_transfers": _assess_third_country_hosting(hosting),
|
|
"retention_period": {"default": "Gemaess Loeschfristenkatalog"},
|
|
"tom_description": f"Siehe TOM-Katalog fuer {name}",
|
|
"business_function": "IT",
|
|
"systems": [name],
|
|
"deployment_model": hosting,
|
|
"protection_level": "HIGH" if len(categories) > 3 else "MEDIUM",
|
|
"dpia_required": len(categories) > 3,
|
|
"status": "DRAFT",
|
|
"responsible": dpo or company,
|
|
}
|
|
activities.append(activity)
|
|
|
|
return activities
|
|
|
|
|
|
def _build_hr_activity(index: int, company: str, dpo: str) -> dict:
|
|
return {
|
|
"vvt_id": f"VVT-STD-{index:03d}",
|
|
"name": "Mitarbeiterverwaltung / HR",
|
|
"description": "Standard-Verarbeitungstaetigkeit Personalverwaltung",
|
|
"purposes": ["Personalverwaltung, Lohnabrechnung, Arbeitszeiterfassung"],
|
|
"legal_bases": ["Art. 6 Abs. 1 lit. b/c DS-GVO i.V.m. §26 BDSG"],
|
|
"data_subject_categories": ["Beschaeftigte"],
|
|
"personal_data_categories": ["Stammdaten", "Vertragsdaten", "Bankverbindung", "Arbeitszeiten"],
|
|
"recipient_categories": ["Lohnbuero (AVV)", "Finanzamt", "Sozialversicherungstraeger"],
|
|
"third_country_transfers": [],
|
|
"retention_period": {"default": "10 Jahre nach Austritt"},
|
|
"tom_description": "Besonderer Zugriffsschutz (nur HR), verschluesselte Speicherung",
|
|
"business_function": "HR",
|
|
"systems": [],
|
|
"protection_level": "HIGH",
|
|
"dpia_required": False,
|
|
"status": "DRAFT",
|
|
"responsible": dpo or company,
|
|
}
|
|
|
|
|
|
def _assess_third_country(ctx: dict) -> list:
|
|
if ctx.get("third_country_transfer"):
|
|
return [{"country": "Abhaengig von Dienstleister", "mechanism": "Pruefung erforderlich"}]
|
|
return []
|
|
|
|
|
|
def _assess_third_country_hosting(hosting: str) -> list:
|
|
if hosting in ("us-cloud", "international"):
|
|
return [{"country": "USA", "mechanism": "EU-US Data Privacy Framework"}]
|
|
return []
|
|
|
|
|
|
def _infer_business_function(name: str) -> str:
|
|
name_lower = name.lower()
|
|
if any(kw in name_lower for kw in ["mitarbeiter", "hr", "personal", "bewerbung"]):
|
|
return "HR"
|
|
if any(kw in name_lower for kw in ["abrechnung", "rechnung", "zahlung", "buchhaltung"]):
|
|
return "Finanzen"
|
|
if any(kw in name_lower for kw in ["marketing", "newsletter", "webanalyse", "crm", "akquise"]):
|
|
return "Marketing/Vertrieb"
|
|
if any(kw in name_lower for kw in ["support", "ticket", "kundenservice"]):
|
|
return "Support"
|
|
if any(kw in name_lower for kw in ["patient", "befund", "labor", "termin"]):
|
|
return "Medizin"
|
|
if any(kw in name_lower for kw in ["schueler", "noten", "lernplattform"]):
|
|
return "Paedagogik"
|
|
return "IT"
|