"""FRIA template generator — creates Fundamental Rights Impact Assessment from UCCA context. Generates a FRIA (Art. 27 AI Act) based on: - UCCA Assessment result (risk level, triggered rules, domain) - AI Act Decision Tree classification - Company profile Automatically maps domains to affected fundamental rights. """ from typing import Optional # -- Domain → Fundamental Rights Mapping ------------------------------------ DOMAIN_RIGHTS_MAP = { "education": [ {"right": "Recht auf Bildung", "charter": "Art. 14", "gg": "Art. 12", "risk": "Chancengleichheit bei KI-gestuetzter Bewertung oder Auswahl"}, {"right": "Nicht-Diskriminierung", "charter": "Art. 21", "gg": "Art. 3", "risk": "Bias bei Leistungsbewertung nach Herkunft, Sprache oder Geschlecht"}, {"right": "Rechte des Kindes", "charter": "Art. 24", "gg": "Art. 6 Abs. 2", "risk": "Besonderer Schutz Minderjaehriger vor automatisierten Bewertungen"}, ], "hr": [ {"right": "Berufsfreiheit / Recht zu arbeiten", "charter": "Art. 15", "gg": "Art. 12", "risk": "KI-gestuetzte Auswahl kann Zugang zum Arbeitsmarkt einschraenken"}, {"right": "Nicht-Diskriminierung", "charter": "Art. 21", "gg": "Art. 3", "risk": "Bias bei Recruiting, Befoerderung oder Kuendigung"}, {"right": "Schutz personenbezogener Daten", "charter": "Art. 8", "gg": "Art. 2 Abs. 1", "risk": "Umfangreiche Verarbeitung von Beschaeftigtendaten"}, ], "healthcare": [ {"right": "Menschenwuerde", "charter": "Art. 1", "gg": "Art. 1", "risk": "KI-Diagnosen koennen existenzielle Auswirkungen haben"}, {"right": "Schutz personenbezogener Daten", "charter": "Art. 8", "gg": "Art. 2 Abs. 1", "risk": "Gesundheitsdaten sind besondere Kategorien (Art. 9 DSGVO)"}, {"right": "Nicht-Diskriminierung", "charter": "Art. 21", "gg": "Art. 3", "risk": "Bias bei Behandlungsempfehlungen nach Alter, Geschlecht oder Ethnie"}, ], "finance": [ {"right": "Recht auf soziale Sicherheit", "charter": "Art. 34", "gg": "Art. 20", "risk": "Zugang zu Finanzdienstleistungen und Versicherungen"}, {"right": "Nicht-Diskriminierung", "charter": "Art. 21", "gg": "Art. 3", "risk": "Scoring-Bias bei Kreditvergabe oder Versicherungspraemien"}, {"right": "Recht auf wirksamen Rechtsbehelf", "charter": "Art. 47", "gg": "Art. 19 Abs. 4", "risk": "Anfechtbarkeit automatisierter Finanzentscheidungen"}, ], "law_enforcement": [ {"right": "Recht auf Freiheit und Sicherheit", "charter": "Art. 6", "gg": "Art. 2 Abs. 2", "risk": "KI-gestuetzte Ueberwachung oder Vorhersage"}, {"right": "Unschuldsvermutung", "charter": "Art. 48", "gg": "Art. 20 Abs. 3", "risk": "Predictive Policing kann Vorverurteilung erzeugen"}, {"right": "Recht auf Privatsphaere", "charter": "Art. 7", "gg": "Art. 2 Abs. 1", "risk": "Biometrische Identifizierung im oeffentlichen Raum"}, ], "public_sector": [ {"right": "Recht auf eine gute Verwaltung", "charter": "Art. 41", "gg": "Art. 20 Abs. 3", "risk": "Automatisierte Verwaltungsentscheidungen muessen nachvollziehbar sein"}, {"right": "Nicht-Diskriminierung", "charter": "Art. 21", "gg": "Art. 3", "risk": "Gleichbehandlung aller Buerger bei KI-gestuetzten Verwaltungsakten"}, {"right": "Recht auf wirksamen Rechtsbehelf", "charter": "Art. 47", "gg": "Art. 19 Abs. 4", "risk": "Widerspruchsmoeglichkeit gegen KI-gestuetzte Bescheide"}, ], } # Universal rights (always relevant for High-Risk AI) UNIVERSAL_RIGHTS = [ {"right": "Schutz personenbezogener Daten", "charter": "Art. 8", "gg": "Art. 2 Abs. 1 i.V.m. Art. 1 Abs. 1", "risk": "Datenverarbeitung durch KI-System"}, {"right": "Menschenwuerde", "charter": "Art. 1", "gg": "Art. 1", "risk": "KI darf Menschen nicht auf Datenpunkte reduzieren"}, ] # -- Default measures ------------------------------------------------------- DEFAULT_MEASURES = [ "Human-in-the-Loop: Menschliche Ueberpruefung aller KI-Empfehlungen vor Umsetzung", "Transparenz: Betroffene werden ueber den Einsatz von KI informiert", "Erklaerbarkeit: KI-Ergebnisse koennen nachvollzogen und begruendet werden", "Beschwerdemechanismus: Betroffene koennen KI-Entscheidungen anfechten", "Logging: Alle Eingaben und Ausgaben werden fuer Audit-Zwecke protokolliert", "Regelmaessige Bias-Audits: Systematische Pruefung auf Diskriminierung", ] HR_MEASURES = [ "AGG-konforme Gestaltung: Kein Bias bei Geschlecht, Alter, Herkunft, Behinderung", "Betriebsrat gemaess §87 Abs.1 Nr.6 und §95 BetrVG beteiligt", "Keine automatisierte Endentscheidung bei Personalangelegenheiten", ] EDUCATION_MEASURES = [ "Lehrkraft ueberprueft und verantwortet alle KI-generierten Bewertungen", "Chancengleichheit unabhaengig von sozioekonomischem Hintergrund", "Schueler/Eltern koennen KI-gestuetzte Bewertungen anfechten", ] def generate_fria_draft(ctx: dict) -> dict: """Generate a FRIA draft from UCCA assessment context. Args: ctx: Dict with keys: Required: - organisation_name: str - system_name: str - system_description: str - einsatzzweck: str Optional: - organisation_address: str - system_version: str - system_provider: str - domain: str (education, hr, healthcare, finance, etc.) - affected_groups: list[str] - affected_count: str - ai_act_classification: str (high_risk, limited_risk, etc.) - annex_iii_category: str - is_public_entity: bool - has_hr_context: bool - has_education_context: bool - risk_score: int - dpo_name: str - dpo_contact: str - review_interval: str Returns: Dict with placeholder values for template substitution. """ result = {} # Section 1: Basic info result["ORGANISATION_NAME"] = ctx.get("organisation_name", "{{ORGANISATION_NAME}}") result["ORGANISATION_ADRESSE"] = ctx.get("organisation_address", "{{ORGANISATION_ADRESSE}}") result["VERANTWORTLICHER"] = ctx.get("responsible_person", "{{VERANTWORTLICHER}}") result["ERSTELLT_VON"] = ctx.get("created_by", "{{ERSTELLT_VON}}") result["ERSTELLT_AM"] = ctx.get("created_at", "{{ERSTELLT_AM}}") result["SYSTEM_NAME"] = ctx.get("system_name", "{{SYSTEM_NAME}}") result["SYSTEM_VERSION"] = ctx.get("system_version", "1.0") result["SYSTEM_BESCHREIBUNG"] = ctx.get("system_description", "{{SYSTEM_BESCHREIBUNG}}") result["SYSTEM_ANBIETER"] = ctx.get("system_provider", "{{SYSTEM_ANBIETER}}") result["EINSATZZWECK"] = ctx.get("einsatzzweck", "{{EINSATZZWECK}}") result["EINSATZKONTEXT"] = ctx.get("einsatzkontext", "{{EINSATZKONTEXT}}") result["AI_ACT_KLASSIFIKATION"] = ctx.get("ai_act_classification", "High-Risk") result["ANNEX_III_KATEGORIE"] = ctx.get("annex_iii_category", "") result["DSB_NAME"] = ctx.get("dpo_name", "{{DSB_NAME}}") result["DSB_KONTAKT"] = ctx.get("dpo_contact", "{{DSB_KONTAKT}}") # Section 1.5: Affected groups groups = ctx.get("affected_groups", []) result["BETROFFENE_GRUPPEN"] = _bullet_list(groups) if groups else "{{BETROFFENE_GRUPPEN}}" result["BETROFFENE_ANZAHL"] = ctx.get("affected_count", "{{BETROFFENE_ANZAHL}}") # Section 2: Fundamental rights mapping domain = ctx.get("domain", "") rights = list(UNIVERSAL_RIGHTS) if domain in DOMAIN_RIGHTS_MAP: rights.extend(DOMAIN_RIGHTS_MAP[domain]) rights_table = [] for i, r in enumerate(rights, 1): rights_table.append( f"| {i} | {r['right']} | {r['charter']} | {r['gg']} | Ja | {r['risk']} |" ) result["GRUNDRECHTE_ANALYSE"] = "\n".join(rights_table) if rights_table else "{{GRUNDRECHTE_ANALYSE}}" # Section 3: Risk matrix risk_rows = [] risk_score = ctx.get("risk_score", 0) base_likelihood = min(3, 1 + risk_score // 30) for r in rights: severity = 3 if "Diskriminierung" in r["risk"] or "existenz" in r["risk"].lower() else 2 likelihood = base_likelihood level = _risk_level(likelihood * severity) risk_rows.append( f"| {r['right']} | {r['risk']} | {likelihood} | {severity} | {level} | Basierend auf Systemanalyse |" ) result["RISIKOMATRIX"] = "\n".join(risk_rows) if risk_rows else "{{RISIKOMATRIX}}" # Section 4: Measures measures = list(DEFAULT_MEASURES) if ctx.get("has_hr_context") or domain == "hr": measures.extend(HR_MEASURES) if ctx.get("has_education_context") or domain == "education": measures.extend(EDUCATION_MEASURES) result["MASSNAHMEN_LISTE"] = _bullet_list(measures) result["HUMAN_OVERSIGHT_BESCHREIBUNG"] = ctx.get("human_oversight", "Das System unterstuetzt menschliche Entscheidungen, trifft jedoch keine eigenstaendigen Entscheidungen. " "Alle KI-generierten Empfehlungen werden von qualifiziertem Personal geprueft.") result["TRANSPARENZ_MASSNAHMEN"] = ctx.get("transparency_measures", "Betroffene Personen werden ueber den Einsatz des KI-Systems informiert. " "KI-generierte Ergebnisse werden als solche gekennzeichnet.") # Section 5: Consultation result["KONSULTATION_ERGEBNISSE"] = ctx.get("consultation_results", "Konsultation steht aus — bitte vor Freigabe durchfuehren.") # Section 6: Approval result["GENEHMIGT_VON"] = ctx.get("approved_by", "{{GENEHMIGT_VON}}") result["GENEHMIGT_AM"] = ctx.get("approved_at", "{{GENEHMIGT_AM}}") # Section 7: Monitoring result["NAECHSTE_UEBERPRUEFUNG"] = ctx.get("review_interval", "12 Monate nach Inbetriebnahme") # Conditional flags result["BILDUNGSKONTEXT"] = ctx.get("has_education_context", False) or domain == "education" result["HR_KONTEXT"] = ctx.get("has_hr_context", False) or domain == "hr" result["OEFFENTLICHE_STELLE"] = ctx.get("is_public_entity", False) return result def _risk_level(score: int) -> str: """Map risk score to level label.""" if score <= 6: return "Niedrig" elif score <= 12: return "Mittel" elif score <= 19: return "Hoch" else: return "Kritisch" def _bullet_list(items: list) -> str: """Format a list as markdown bullet points.""" return "\n".join(f"- {item}" for item in items)