Spaces:
Running
Running
| """ | |
| Multi-Framework Regulatory Harmonization Crosswalk. | |
| Projects EU AI Act (Regulation EU 2024/1689) conformity findings onto: | |
| - NIST AI RMF 1.0 (GOVERN, MAP, MEASURE, MANAGE) | |
| - ISO/IEC 42001:2023 (Clauses & Annex A Controls) | |
| - GDPR (Regulation EU 2016/679) | |
| """ | |
| import json | |
| from pathlib import Path | |
| from typing import Dict, List, Any, Optional | |
| from pydantic import BaseModel, Field | |
| from src.core.config import BENCHMARKS_DIR | |
| from src.core.models import ValidationViolation | |
| class FrameworkControlStatus(BaseModel): | |
| control_id: str | |
| control_name: str | |
| target_framework: str | |
| status: str # "SATISFIED", "NON_COMPLIANT", "NOT_EVALUATED" | |
| eu_ai_act_article: str | |
| relationship_type: str | |
| semantic_rationale: str | |
| audit_guidance: str | |
| class FrameworkSummary(BaseModel): | |
| total_mapped_controls: int | |
| satisfied_controls_count: int | |
| non_compliant_controls_count: int | |
| conformity_percentage: float | |
| controls: List[FrameworkControlStatus] = Field(default_factory=list) | |
| class MultiFrameworkCrosswalkResult(BaseModel): | |
| frameworks: Dict[str, FrameworkSummary] = Field(default_factory=dict) | |
| high_level_summary: str = "" | |
| class MultiFrameworkCrosswalk: | |
| def __init__(self, mappings_path: Optional[Path] = None): | |
| self.mappings_file = mappings_path or (BENCHMARKS_DIR / "rules" / "cross_regulatory_frameworks.json") | |
| self.mappings: List[Dict[str, Any]] = [] | |
| self._load_mappings() | |
| def _load_mappings(self) -> None: | |
| if self.mappings_file.exists(): | |
| with open(self.mappings_file, "r", encoding="utf-8") as f: | |
| data = json.load(f) | |
| self.mappings = data.get("mappings", []) | |
| else: | |
| self.mappings = [] | |
| def harmonize( | |
| self, | |
| violations: List[ValidationViolation], | |
| all_evaluated_articles: Optional[List[str]] = None, | |
| ) -> MultiFrameworkCrosswalkResult: | |
| """ | |
| Projects EU AI Act conformity assessment results across target frameworks. | |
| """ | |
| violation_articles = set(v.regulatory_article.strip() for v in violations) | |
| # Normalize: e.g. "Article 9(2)" -> "Article 9" prefix match | |
| def is_article_violated(article_name: str) -> bool: | |
| for v_art in violation_articles: | |
| if article_name.startswith(v_art) or v_art.startswith(article_name): | |
| return True | |
| return False | |
| framework_controls: Dict[str, List[FrameworkControlStatus]] = { | |
| "NIST AI RMF 1.0": [], | |
| "ISO/IEC 42001:2023": [], | |
| "GDPR (EU 2016/679)": [], | |
| } | |
| for m in self.mappings: | |
| target_fw = m.get("target_framework", "Unknown") | |
| eu_art = m.get("eu_ai_act_article", "") | |
| has_violation = is_article_violated(eu_art) | |
| status = "NON_COMPLIANT" if has_violation else "SATISFIED" | |
| ctrl_status = FrameworkControlStatus( | |
| control_id=m.get("target_control_id", ""), | |
| control_name=m.get("target_control_name", ""), | |
| target_framework=target_fw, | |
| status=status, | |
| eu_ai_act_article=eu_art, | |
| relationship_type=m.get("relationship_type", "EXACT_EQUIVALENT"), | |
| semantic_rationale=m.get("semantic_rationale", ""), | |
| audit_guidance=m.get("audit_guidance", ""), | |
| ) | |
| if target_fw in framework_controls: | |
| framework_controls[target_fw].append(ctrl_status) | |
| else: | |
| framework_controls.setdefault(target_fw, []).append(ctrl_status) | |
| framework_summaries: Dict[str, FrameworkSummary] = {} | |
| total_satisfied = 0 | |
| total_controls = 0 | |
| for fw_name, ctrls in framework_controls.items(): | |
| tot = len(ctrls) | |
| sat = sum(1 for c in ctrls if c.status == "SATISFIED") | |
| non = sum(1 for c in ctrls if c.status == "NON_COMPLIANT") | |
| pct = round((sat / tot * 100.0), 1) if tot > 0 else 100.0 | |
| total_satisfied += sat | |
| total_controls += tot | |
| framework_summaries[fw_name] = FrameworkSummary( | |
| total_mapped_controls=tot, | |
| satisfied_controls_count=sat, | |
| non_compliant_controls_count=non, | |
| conformity_percentage=pct, | |
| controls=ctrls, | |
| ) | |
| overall_pct = round((total_satisfied / total_controls * 100.0), 1) if total_controls > 0 else 100.0 | |
| summary_text = ( | |
| f"Multi-framework crosswalk mapped across {len(framework_summaries)} international frameworks: " | |
| f"{total_satisfied}/{total_controls} controls satisfied ({overall_pct}% alignment). " | |
| f"NIST AI RMF: {framework_summaries.get('NIST AI RMF 1.0', FrameworkSummary(total_mapped_controls=0, satisfied_controls_count=0, non_compliant_controls_count=0, conformity_percentage=0.0)).conformity_percentage}%, " | |
| f"ISO 42001: {framework_summaries.get('ISO/IEC 42001:2023', FrameworkSummary(total_mapped_controls=0, satisfied_controls_count=0, non_compliant_controls_count=0, conformity_percentage=0.0)).conformity_percentage}%, " | |
| f"GDPR: {framework_summaries.get('GDPR (EU 2016/679)', FrameworkSummary(total_mapped_controls=0, satisfied_controls_count=0, non_compliant_controls_count=0, conformity_percentage=0.0)).conformity_percentage}%." | |
| ) | |
| return MultiFrameworkCrosswalkResult( | |
| frameworks=framework_summaries, | |
| high_level_summary=summary_text, | |
| ) | |