gitmodelmujtaba commited on
Commit
99102a1
·
verified ·
1 Parent(s): 5be6ff1

Deploy ReguAI: Neuro-Symbolic AI GRC & Automated Conformity Assessment Engine

Browse files
api.py CHANGED
@@ -43,6 +43,14 @@ CERTIFICATE_CACHE: Dict[str, ConformityReport] = {}
43
  class AuditRequest(BaseModel):
44
  specification_text: str = Field(..., description="Markdown model card, YAML spec, or JSON system document.")
45
  auditor_id: Optional[str] = Field("ci_cd_automated_pipeline", description="Identifier of the executing pipeline or auditor.")
 
 
 
 
 
 
 
 
46
 
47
 
48
  class TripletFeedbackRequest(BaseModel):
@@ -63,6 +71,45 @@ def health_check():
63
  }
64
 
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  @app.post("/api/v1/audit/evaluate", response_model=Dict[str, Any], tags=["Conformity Assessment"])
67
  def evaluate_specification(request: AuditRequest):
68
  """
@@ -72,7 +119,12 @@ def evaluate_specification(request: AuditRequest):
72
  raise HTTPException(status_code=400, detail="Specification text cannot be empty.")
73
 
74
  try:
75
- report = engine.evaluate_system(request.specification_text, auditor_id=request.auditor_id)
 
 
 
 
 
76
  token = report.provenance.digital_signature
77
  CERTIFICATE_CACHE[token] = report
78
 
@@ -97,6 +149,8 @@ def evaluate_specification(request: AuditRequest):
97
  "claims_extracted_count": len(report.claims_analyzed),
98
  "borderline_claims_count": len(report.borderline_claims),
99
  "executive_summary": report.executive_summary,
 
 
100
  "provenance": {
101
  "source_doc_sha256": report.provenance.input_doc_sha256,
102
  "graph_sha256": report.provenance.graph_triples_sha256,
 
43
  class AuditRequest(BaseModel):
44
  specification_text: str = Field(..., description="Markdown model card, YAML spec, or JSON system document.")
45
  auditor_id: Optional[str] = Field("ci_cd_automated_pipeline", description="Identifier of the executing pipeline or auditor.")
46
+ annual_turnover_eur: Optional[float] = Field(0.0, description="Annual corporate worldwide turnover in EUR for fine exposure modeling.")
47
+ is_sme: Optional[bool] = Field(False, description="Whether the organization qualifies as an SME/startup under Article 99(6).")
48
+
49
+
50
+ class PenaltyCalculationRequest(BaseModel):
51
+ violations: List[str] = Field(default_factory=list, description="List of violated articles, e.g. ['Article 5(1)(c)', 'Article 14'].")
52
+ annual_turnover_eur: float = Field(0.0, description="Annual corporate turnover in EUR.")
53
+ is_sme: bool = Field(False, description="SME cap flag under Article 99(6).")
54
 
55
 
56
  class TripletFeedbackRequest(BaseModel):
 
71
  }
72
 
73
 
74
+ @app.get("/api/v1/frameworks/crosswalk", tags=["Harmonization"])
75
+ def get_regulatory_crosswalk():
76
+ """
77
+ Returns the complete bidirectional regulatory ontology crosswalk linking
78
+ EU AI Act Articles to NIST AI RMF 1.0, ISO/IEC 42001:2023, and GDPR.
79
+ """
80
+ return {
81
+ "total_mappings": len(engine.crosswalk.mappings),
82
+ "mappings": engine.crosswalk.mappings,
83
+ }
84
+
85
+
86
+ @app.post("/api/v1/penalties/calculate", tags=["Penalties"])
87
+ def calculate_penalties(request: PenaltyCalculationRequest):
88
+ """
89
+ Calculates statutory fine liability and financial balance sheet risk under Article 99.
90
+ """
91
+ from src.core.models import ValidationViolation
92
+ mock_violations = [
93
+ ValidationViolation(
94
+ focus_node="MockNode",
95
+ result_path="MockPath",
96
+ source_constraint_component="MockComponent",
97
+ message="Violated constraint",
98
+ severity="Violation",
99
+ regulatory_article=art,
100
+ normative_reference=art,
101
+ remediation_guidance="Remediate constraint",
102
+ )
103
+ for art in request.violations
104
+ ]
105
+ estimate = engine.fine_calculator.calculate_exposure(
106
+ violations=mock_violations,
107
+ annual_turnover_eur=request.annual_turnover_eur,
108
+ is_sme=request.is_sme,
109
+ )
110
+ return estimate.model_dump()
111
+
112
+
113
  @app.post("/api/v1/audit/evaluate", response_model=Dict[str, Any], tags=["Conformity Assessment"])
114
  def evaluate_specification(request: AuditRequest):
115
  """
 
119
  raise HTTPException(status_code=400, detail="Specification text cannot be empty.")
120
 
121
  try:
122
+ report = engine.evaluate_system(
123
+ request.specification_text,
124
+ auditor_id=request.auditor_id,
125
+ annual_turnover_eur=request.annual_turnover_eur or 0.0,
126
+ is_sme=request.is_sme or False,
127
+ )
128
  token = report.provenance.digital_signature
129
  CERTIFICATE_CACHE[token] = report
130
 
 
149
  "claims_extracted_count": len(report.claims_analyzed),
150
  "borderline_claims_count": len(report.borderline_claims),
151
  "executive_summary": report.executive_summary,
152
+ "fine_exposure": report.fine_exposure,
153
+ "harmonized_frameworks": report.harmonized_frameworks,
154
  "provenance": {
155
  "source_doc_sha256": report.provenance.input_doc_sha256,
156
  "graph_sha256": report.provenance.graph_triples_sha256,
app.py CHANGED
@@ -39,7 +39,7 @@ def load_sample_content(sample_name: str) -> str:
39
  return ""
40
 
41
 
42
- def run_assessment(doc_text: str, auditor_id: str):
43
  if not doc_text or not doc_text.strip():
44
  return (
45
  "⚠️ Please enter model card text or select a pre-loaded sample.",
@@ -52,9 +52,16 @@ def run_assessment(doc_text: str, auditor_id: str):
52
  "",
53
  "<div>No certificate generated.</div>",
54
  [],
 
 
55
  )
56
 
57
- report = engine.evaluate_system(doc_text, auditor_id=auditor_id or "auditor_01")
 
 
 
 
 
58
 
59
  # 1. Executive Summary HTML
60
  status_color = "#10b981" if report.overall_conforms else "#ef4444"
@@ -131,7 +138,49 @@ def run_assessment(doc_text: str, auditor_id: str):
131
  b.evidence_quote[:100],
132
  ])
133
 
134
- # 6. Cryptographic Ledger Proofs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  prov = report.provenance
136
  cert_token = prov.digital_signature
137
  hash_summary = (
@@ -144,7 +193,7 @@ def run_assessment(doc_text: str, auditor_id: str):
144
  f"| Conformity Assessment Digest | `{prov.certificate_sha256}` |\n"
145
  )
146
 
147
- # 7. Annex IV Markdown, JSON-LD & Styled HTML Certificate
148
  md_report = engine.report_generator.generate_markdown_report(report)
149
  json_ld_cert = json.dumps(engine.report_generator.generate_json_ld(report), indent=2)
150
  raw_cert_html = engine.report_generator.generate_html_certificate(report)
@@ -164,6 +213,8 @@ def run_assessment(doc_text: str, auditor_id: str):
164
  md_report,
165
  cert_iframe_html,
166
  borderline_data,
 
 
167
  )
168
 
169
 
@@ -435,7 +486,7 @@ button:not(.primary):not([variant="primary"]) {
435
  }
436
  """
437
 
438
- with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, theme=gr.themes.Soft()) as demo:
439
  gr.Markdown(
440
  """
441
  # 🏛️ ReguAI: Deterministic Neuro-Symbolic AI GRC & Conformity Engine
@@ -446,9 +497,9 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, the
446
  <div style="display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap;">
447
  <span class="header-badge">🇪🇺 EU AI Act High-Risk (Arts. 9-15)</span>
448
  <span class="header-badge">📐 W3C SHACL Deterministic Proofs</span>
449
- <span class="header-badge">🌐 Interactive Knowledge Graph</span>
 
450
  <span class="header-badge">🔗 W3C PROV-O Audit Ledger</span>
451
- <span class="header-badge">🛡️ Zero-Hallucination Guarantee</span>
452
  <span class="header-badge">👤 Auditor-in-the-Loop Active Learning</span>
453
  </div>
454
  """
@@ -472,6 +523,18 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, the
472
  value="lead_compliance_auditor_01",
473
  placeholder="e.g. auditor@enterprise.org",
474
  )
 
 
 
 
 
 
 
 
 
 
 
 
475
  assess_btn = gr.Button("⚡ Run Deterministic Conformity Assessment", variant="primary", size="lg")
476
 
477
  with gr.Column(scale=7):
@@ -488,6 +551,17 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, the
488
  label="Mathematical Proof: Non-Conformities Found",
489
  )
490
 
 
 
 
 
 
 
 
 
 
 
 
491
  with gr.TabItem("🔍 Extracted Regulatory Claims"):
492
  claims_table = gr.Dataframe(
493
  headers=["Claim ID", "Category", "Status", "Confidence", "Target Article", "Evidence Span"],
@@ -531,7 +605,7 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, the
531
 
532
  assess_btn.click(
533
  fn=run_assessment,
534
- inputs=[spec_input, auditor_input],
535
  outputs=[
536
  exec_output,
537
  violations_table,
@@ -543,6 +617,8 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, the
543
  report_markdown,
544
  cert_html_output,
545
  borderline_table,
 
 
546
  ],
547
  )
548
 
@@ -553,4 +629,4 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, the
553
  )
554
 
555
  if __name__ == "__main__":
556
- demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
39
  return ""
40
 
41
 
42
+ def run_assessment(doc_text: str, auditor_id: str, annual_turnover: float = 50000000.0, is_sme: bool = False):
43
  if not doc_text or not doc_text.strip():
44
  return (
45
  "⚠️ Please enter model card text or select a pre-loaded sample.",
 
52
  "",
53
  "<div>No certificate generated.</div>",
54
  [],
55
+ [],
56
+ "<div style='padding:15px;'>No fine liability evaluated.</div>",
57
  )
58
 
59
+ report = engine.evaluate_system(
60
+ doc_text,
61
+ auditor_id=auditor_id or "auditor_01",
62
+ annual_turnover_eur=float(annual_turnover or 0.0),
63
+ is_sme=bool(is_sme),
64
+ )
65
 
66
  # 1. Executive Summary HTML
67
  status_color = "#10b981" if report.overall_conforms else "#ef4444"
 
138
  b.evidence_quote[:100],
139
  ])
140
 
141
+ # 6. Multi-Framework Harmonization Data Table
142
+ frameworks_data = []
143
+ if report.harmonized_frameworks:
144
+ fw_dict = report.harmonized_frameworks.get("frameworks", {})
145
+ for fw_name, fw_info in fw_dict.items():
146
+ for ctrl in fw_info.get("controls", []):
147
+ stat_badge = "🟢 SATISFIED" if ctrl.get("status") == "SATISFIED" else "🔴 NON-COMPLIANT"
148
+ frameworks_data.append([
149
+ fw_name,
150
+ ctrl.get("control_id"),
151
+ ctrl.get("control_name"),
152
+ stat_badge,
153
+ ctrl.get("eu_ai_act_article"),
154
+ ctrl.get("audit_guidance"),
155
+ ])
156
+
157
+ # 7. Article 99 Fine Liability Scorecard HTML
158
+ fine = report.fine_exposure or {}
159
+ ceiling = fine.get("applicable_ceiling_eur", 0.0)
160
+ tier_name = fine.get("highest_tier_triggered", "NONE")
161
+ color = "#10b981" if ceiling == 0.0 else ("#ef4444" if "PROHIBITED" in tier_name else "#f59e0b")
162
+ bg = "#f0fdf4" if ceiling == 0.0 else "#fff7ed"
163
+ border = "#bbf7d0" if ceiling == 0.0 else "#fed7aa"
164
+
165
+ fine_html = f"""
166
+ <div style="background: {bg}; border: 1px solid {border}; padding: 20px; border-radius: 8px; margin-bottom: 15px;">
167
+ <div style="font-size: 13px; font-weight: 700; color: {color}; text-transform: uppercase; letter-spacing: 0.5px;">Regulation (EU) 2024/1689 Article 99 Corporate Fine Exposure</div>
168
+ <div style="font-size: 32px; font-weight: 800; color: {color}; margin: 8px 0;">
169
+ €{ceiling:,.2f}
170
+ </div>
171
+ <div style="display: flex; gap: 25px; font-size: 13px; color: #475569; margin-bottom: 14px; flex-wrap: wrap;">
172
+ <div><strong>Penalty Tier:</strong> <code>{tier_name}</code></div>
173
+ <div><strong>Turnover Percentage:</strong> {fine.get('turnover_percentage', 0)}% of global annual turnover</div>
174
+ <div><strong>SME Discount (Art. 99(6)):</strong> {'✓ Active' if fine.get('is_sme_discount_applied') else '✗ Inactive (Standard Enterprise)'}</div>
175
+ <div><strong>Simulated Turnover:</strong> €{float(annual_turnover):,.2f}</div>
176
+ </div>
177
+ <div style="font-size: 13px; color: #1e293b; line-height: 1.6; background: rgba(255,255,255,0.85); padding: 12px 16px; border-radius: 6px; border: 1px solid #e2e8f0;">
178
+ <strong>Statutory Basis & Remediations:</strong> {fine.get('executive_liability_summary', '')}
179
+ </div>
180
+ </div>
181
+ """
182
+
183
+ # 8. Cryptographic Ledger Proofs
184
  prov = report.provenance
185
  cert_token = prov.digital_signature
186
  hash_summary = (
 
193
  f"| Conformity Assessment Digest | `{prov.certificate_sha256}` |\n"
194
  )
195
 
196
+ # 9. Annex IV Markdown, JSON-LD & Styled HTML Certificate
197
  md_report = engine.report_generator.generate_markdown_report(report)
198
  json_ld_cert = json.dumps(engine.report_generator.generate_json_ld(report), indent=2)
199
  raw_cert_html = engine.report_generator.generate_html_certificate(report)
 
213
  md_report,
214
  cert_iframe_html,
215
  borderline_data,
216
+ frameworks_data,
217
+ fine_html,
218
  )
219
 
220
 
 
486
  }
487
  """
488
 
489
+ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
490
  gr.Markdown(
491
  """
492
  # 🏛️ ReguAI: Deterministic Neuro-Symbolic AI GRC & Conformity Engine
 
497
  <div style="display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap;">
498
  <span class="header-badge">🇪🇺 EU AI Act High-Risk (Arts. 9-15)</span>
499
  <span class="header-badge">📐 W3C SHACL Deterministic Proofs</span>
500
+ <span class="header-badge">🌐 Multi-Framework Crosswalk (NIST & ISO)</span>
501
+ <span class="header-badge">💰 Article 99 Statutory Fine Modeling</span>
502
  <span class="header-badge">🔗 W3C PROV-O Audit Ledger</span>
 
503
  <span class="header-badge">👤 Auditor-in-the-Loop Active Learning</span>
504
  </div>
505
  """
 
523
  value="lead_compliance_auditor_01",
524
  placeholder="e.g. auditor@enterprise.org",
525
  )
526
+ with gr.Accordion("💰 Article 99 Corporate Fine Modeling", open=False):
527
+ turnover_input = gr.Number(
528
+ label="Worldwide Annual Turnover (EUR)",
529
+ value=50000000.0,
530
+ step=5000000.0,
531
+ info="Used to calculate maximum turnover percentage ceilings under Article 99"
532
+ )
533
+ is_sme_input = gr.Checkbox(
534
+ label="SME / Startup Status (Article 99(6) Special Ceiling)",
535
+ value=False,
536
+ info="Applies lower of fixed amount or turnover percentage"
537
+ )
538
  assess_btn = gr.Button("⚡ Run Deterministic Conformity Assessment", variant="primary", size="lg")
539
 
540
  with gr.Column(scale=7):
 
551
  label="Mathematical Proof: Non-Conformities Found",
552
  )
553
 
554
+ with gr.TabItem("🌐 Multi-Framework Crosswalk"):
555
+ gr.Markdown("### 🇪🇺 EU AI Act ⟷ NIST AI RMF 1.0 ⟷ ISO/IEC 42001:2023 ⟷ GDPR")
556
+ frameworks_table = gr.Dataframe(
557
+ headers=["Target Framework", "Control ID", "Control Name", "Status", "Linked AI Act Article", "Audit Guidance"],
558
+ datatype=["str", "str", "str", "str", "str", "str"],
559
+ label="Automated Cross-Regulatory Control Status",
560
+ )
561
+
562
+ with gr.TabItem("💰 Article 99 Fine Liability"):
563
+ fine_liability_output = gr.HTML(label="Corporate Balance Sheet Exposure")
564
+
565
  with gr.TabItem("🔍 Extracted Regulatory Claims"):
566
  claims_table = gr.Dataframe(
567
  headers=["Claim ID", "Category", "Status", "Confidence", "Target Article", "Evidence Span"],
 
605
 
606
  assess_btn.click(
607
  fn=run_assessment,
608
+ inputs=[spec_input, auditor_input, turnover_input, is_sme_input],
609
  outputs=[
610
  exec_output,
611
  violations_table,
 
617
  report_markdown,
618
  cert_html_output,
619
  borderline_table,
620
+ frameworks_table,
621
+ fine_liability_output,
622
  ],
623
  )
624
 
 
629
  )
630
 
631
  if __name__ == "__main__":
632
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False, theme=gr.themes.Soft(), css=CUSTOM_CSS)
data/active_learning_triplets.jsonl CHANGED
@@ -4,3 +4,6 @@
4
  {"timestamp": "2026-09-20T19:21:17.032615+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
5
  {"timestamp": "2026-09-20T19:25:13.983379+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
6
  {"timestamp": "2026-09-20T19:29:16.657657+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
 
 
 
 
4
  {"timestamp": "2026-09-20T19:21:17.032615+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
5
  {"timestamp": "2026-09-20T19:25:13.983379+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
6
  {"timestamp": "2026-09-20T19:29:16.657657+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
7
+ {"timestamp": "2026-09-20T19:34:57.435307+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
8
+ {"timestamp": "2026-09-20T19:37:14.849175+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
9
+ {"timestamp": "2026-09-20T19:38:35.112557+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
src/core/models.py CHANGED
@@ -101,3 +101,5 @@ class ConformityReport(BaseModel):
101
  provenance: AuditProvenance
102
  generated_at_utc: str
103
  executive_summary: str
 
 
 
101
  provenance: AuditProvenance
102
  generated_at_utc: str
103
  executive_summary: str
104
+ fine_exposure: Optional[Dict[str, Any]] = None
105
+ harmonized_frameworks: Optional[Dict[str, Any]] = None
src/engine.py CHANGED
@@ -19,6 +19,8 @@ from src.reasoning.shacl_engine import DeterministicSHACLEngine
19
  from src.ledger.provenance import ProvenanceLedger
20
  from src.triage.active_learning import ActiveLearningTriageQueue
21
  from src.triage.report_generator import ConformityReportGenerator
 
 
22
 
23
 
24
  class ReguAIEngine:
@@ -30,11 +32,15 @@ class ReguAIEngine:
30
  self.ledger = ProvenanceLedger()
31
  self.triage_queue = ActiveLearningTriageQueue()
32
  self.report_generator = ConformityReportGenerator()
 
 
33
 
34
  def evaluate_system(
35
  self,
36
  input_data: Union[str, Path, Dict[str, Any]],
37
  auditor_id: str = "reguai_lead_auditor",
 
 
38
  ) -> ConformityReport:
39
  """
40
  Executes full deterministic conformity assessment pipeline:
@@ -43,7 +49,9 @@ class ReguAIEngine:
43
  3. Construct RDF normative graph
44
  4. Run deterministic W3C SHACL shape validation
45
  5. Generate cryptographic W3C PROV-O audit ledger
46
- 6. Generate comprehensive ConformityReport
 
 
47
  """
48
  # 1. Parsing
49
  if isinstance(input_data, Path):
@@ -77,7 +85,15 @@ class ReguAIEngine:
77
  auditor_id=auditor_id,
78
  )
79
 
80
- # 6. Build Conformity Report
 
 
 
 
 
 
 
 
81
  total_reqs = len(violations) + len(warnings) + 6
82
  passed_reqs = max(0, total_reqs - len(violations))
83
  now_utc = datetime.now(timezone.utc).isoformat()
@@ -94,7 +110,8 @@ class ReguAIEngine:
94
  summary = (
95
  f"The AI system '{spec.metadata.name}' fails mandatory EU AI Act Chapter III high-risk requirements. "
96
  f"Formal W3C SHACL constraint validation discovered {len(violations)} non-conformities affecting {violation_articles}. "
97
- f"Remediation is required before deployment into high-impact environments."
 
98
  )
99
 
100
  report = ConformityReport(
@@ -111,6 +128,8 @@ class ReguAIEngine:
111
  provenance=provenance,
112
  generated_at_utc=now_utc,
113
  executive_summary=summary,
 
 
114
  )
115
 
116
  return report
 
19
  from src.ledger.provenance import ProvenanceLedger
20
  from src.triage.active_learning import ActiveLearningTriageQueue
21
  from src.triage.report_generator import ConformityReportGenerator
22
+ from src.reasoning.framework_crosswalk import MultiFrameworkCrosswalk
23
+ from src.reasoning.fine_calculator import FineLiabilityCalculator
24
 
25
 
26
  class ReguAIEngine:
 
32
  self.ledger = ProvenanceLedger()
33
  self.triage_queue = ActiveLearningTriageQueue()
34
  self.report_generator = ConformityReportGenerator()
35
+ self.crosswalk = MultiFrameworkCrosswalk()
36
+ self.fine_calculator = FineLiabilityCalculator()
37
 
38
  def evaluate_system(
39
  self,
40
  input_data: Union[str, Path, Dict[str, Any]],
41
  auditor_id: str = "reguai_lead_auditor",
42
+ annual_turnover_eur: float = 0.0,
43
+ is_sme: bool = False,
44
  ) -> ConformityReport:
45
  """
46
  Executes full deterministic conformity assessment pipeline:
 
49
  3. Construct RDF normative graph
50
  4. Run deterministic W3C SHACL shape validation
51
  5. Generate cryptographic W3C PROV-O audit ledger
52
+ 6. Compute Multi-Framework Harmonization Crosswalk (NIST / ISO / GDPR)
53
+ 7. Calculate Article 99 Statutory Fine Liability
54
+ 8. Generate comprehensive ConformityReport
55
  """
56
  # 1. Parsing
57
  if isinstance(input_data, Path):
 
85
  auditor_id=auditor_id,
86
  )
87
 
88
+ # 6. Multi-Framework Harmonization & Article 99 Liability
89
+ crosswalk_res = self.crosswalk.harmonize(violations=violations)
90
+ fine_res = self.fine_calculator.calculate_exposure(
91
+ violations=violations,
92
+ annual_turnover_eur=annual_turnover_eur,
93
+ is_sme=is_sme,
94
+ )
95
+
96
+ # 7. Build Conformity Report
97
  total_reqs = len(violations) + len(warnings) + 6
98
  passed_reqs = max(0, total_reqs - len(violations))
99
  now_utc = datetime.now(timezone.utc).isoformat()
 
110
  summary = (
111
  f"The AI system '{spec.metadata.name}' fails mandatory EU AI Act Chapter III high-risk requirements. "
112
  f"Formal W3C SHACL constraint validation discovered {len(violations)} non-conformities affecting {violation_articles}. "
113
+ f"Remediation is required before deployment into high-impact environments. "
114
+ f"{fine_res.executive_liability_summary}"
115
  )
116
 
117
  report = ConformityReport(
 
128
  provenance=provenance,
129
  generated_at_utc=now_utc,
130
  executive_summary=summary,
131
+ fine_exposure=fine_res.model_dump(),
132
+ harmonized_frameworks=crosswalk_res.model_dump(),
133
  )
134
 
135
  return report
src/extraction/assertion_triage.py CHANGED
@@ -25,8 +25,10 @@ class AssertionTriage:
25
  self.planned_patterns = [
26
  r"\b(planned|planning|roadmap|scheduled|targeted|proposed)\b",
27
  r"\b(will\s+be|to\s+be\s+implemented|in\s+development|in\s+progress)\b",
28
- r"\b(future\s+(?:release|version|iteration|work))\b",
29
  r"\b(under\s+(?:consideration|evaluation|review))\b",
 
 
30
  r"\b(q[1-4]\s*202[0-9])\b",
31
  ]
32
 
 
25
  self.planned_patterns = [
26
  r"\b(planned|planning|roadmap|scheduled|targeted|proposed)\b",
27
  r"\b(will\s+be|to\s+be\s+implemented|in\s+development|in\s+progress)\b",
28
+ r"\b(future\s+(?:releases?|versions?|iterations?|work))\b",
29
  r"\b(under\s+(?:consideration|evaluation|review))\b",
30
+ r"\b(might\s+be\s+considered|could\s+be\s+considered|considered\s+for)\b",
31
+ r"\b(if\s+budget\s+permits|pending\s+approval)\b",
32
  r"\b(q[1-4]\s*202[0-9])\b",
33
  ]
34
 
src/extraction/gliner_extractor.py CHANGED
@@ -24,6 +24,13 @@ class RegulatoryClaimExtractor:
24
 
25
  # Domain Regex & Semantic Keywords for Regulatory Concepts
26
  self.category_patterns: Dict[EntityCategory, Dict[str, Any]] = {
 
 
 
 
 
 
 
27
  EntityCategory.HUMAN_OVERSIGHT: {
28
  "article": "Article 14",
29
  "keywords": [
@@ -32,13 +39,6 @@ class RegulatoryClaimExtractor:
32
  r"\b(two-person\s+rule|dual\s+authorization|doctor\s+approval)\b",
33
  ],
34
  },
35
- EntityCategory.FAIL_SAFE: {
36
- "article": "Article 14(4)(e) / Art 15",
37
- "keywords": [
38
- r"\b(emergency\s+stop|kill\s+switch|fail-safe|fallback\s+mechanism)\b",
39
- r"\b(graceful\s+degradation|circuit\s+breaker|safe\s+shutdown)\b",
40
- ],
41
- },
42
  EntityCategory.DATA_GOVERNANCE: {
43
  "article": "Article 10",
44
  "keywords": [
@@ -88,8 +88,8 @@ class RegulatoryClaimExtractor:
88
  EntityCategory.CYBERSECURITY: {
89
  "article": "Article 15(4)",
90
  "keywords": [
91
- r"\b(cybersecurity|adversarial\s+robustness|adversarial\s+attack)\b",
92
- r"\b(prompt\s+injection\s+defense|data\s+poisoning|model\s+inversion)\b",
93
  r"\b(input\s+sanitization|model\s+extraction\s+defense)\b",
94
  ],
95
  },
 
24
 
25
  # Domain Regex & Semantic Keywords for Regulatory Concepts
26
  self.category_patterns: Dict[EntityCategory, Dict[str, Any]] = {
27
+ EntityCategory.FAIL_SAFE: {
28
+ "article": "Article 14(4)(e) / Art 15",
29
+ "keywords": [
30
+ r"\b(emergency\s+stop|kill\s+switch|fail-safe|fallback\s+mechanism)\b",
31
+ r"\b(graceful\s+degradation|circuit\s+breaker|safe\s+shutdown)\b",
32
+ ],
33
+ },
34
  EntityCategory.HUMAN_OVERSIGHT: {
35
  "article": "Article 14",
36
  "keywords": [
 
39
  r"\b(two-person\s+rule|dual\s+authorization|doctor\s+approval)\b",
40
  ],
41
  },
 
 
 
 
 
 
 
42
  EntityCategory.DATA_GOVERNANCE: {
43
  "article": "Article 10",
44
  "keywords": [
 
88
  EntityCategory.CYBERSECURITY: {
89
  "article": "Article 15(4)",
90
  "keywords": [
91
+ r"\b(cybersecurity|adversarial\s+(?:robustness|attack|testing)|adversarial)\b",
92
+ r"\b(prompt\s+injection(?:\s+defense)?|data\s+poisoning|model\s+inversion)\b",
93
  r"\b(input\s+sanitization|model\s+extraction\s+defense)\b",
94
  ],
95
  },
src/reasoning/fine_calculator.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Article 99 Statutory Fine Liability & SME Exposure Calculator.
3
+ Calculates maximum corporate balance sheet exposure under Regulation (EU) 2024/1689:
4
+ - Tier 1 (Article 5 Prohibitions): Up to 35M€ or 7% global turnover
5
+ - Tier 2 (Chapter III High-Risk Obligations): Up to 15M€ or 3% global turnover
6
+ - Tier 3 (Misinformation / Notified Body Requests): Up to 7.5M€ or 1.5% global turnover
7
+ - Article 99(6) Special Cap: Fines on SMEs/startups use min(fixed, percentage)
8
+ """
9
+
10
+ import json
11
+ from pathlib import Path
12
+ from typing import List, Optional, Dict, Any
13
+ from pydantic import BaseModel, Field
14
+
15
+ from src.core.config import BENCHMARKS_DIR
16
+ from src.core.models import ValidationViolation
17
+
18
+
19
+ class FineExposureEstimate(BaseModel):
20
+ is_non_compliant: bool
21
+ highest_tier_triggered: str
22
+ statutory_legal_basis: str
23
+ maximum_fine_eur: float
24
+ turnover_percentage: float
25
+ applicable_ceiling_eur: float
26
+ is_sme_discount_applied: bool
27
+ assumed_annual_turnover_eur: float
28
+ affected_articles: List[str] = Field(default_factory=list)
29
+ executive_liability_summary: str
30
+
31
+
32
+ class FineLiabilityCalculator:
33
+ def __init__(self, guidelines_path: Optional[Path] = None):
34
+ self.guidelines_file = guidelines_path or (BENCHMARKS_DIR / "rules" / "ai_act_fine_guidelines.json")
35
+ self.guidelines: Dict[str, Any] = {}
36
+ self._load_guidelines()
37
+
38
+ def _load_guidelines(self) -> None:
39
+ if self.guidelines_file.exists():
40
+ with open(self.guidelines_file, "r", encoding="utf-8") as f:
41
+ self.guidelines = json.load(f)
42
+ else:
43
+ # Standard statutory default fallbacks under Article 99
44
+ self.guidelines = {
45
+ "tiers": [
46
+ {"tier": "TIER_1_PROHIBITED_AI", "maximum_fine_eur": 35000000, "maximum_turnover_pct": 7.0, "legal_basis": "Article 99(3)"},
47
+ {"tier": "TIER_2_HIGH_RISK_OBLIGATIONS", "maximum_fine_eur": 15000000, "maximum_turnover_pct": 3.0, "legal_basis": "Article 99(4)"},
48
+ {"tier": "TIER_3_MISINFORMATION_NOTIFICATION", "maximum_fine_eur": 7500000, "maximum_turnover_pct": 1.5, "legal_basis": "Article 99(5)"},
49
+ ]
50
+ }
51
+
52
+ def calculate_exposure(
53
+ self,
54
+ violations: List[ValidationViolation],
55
+ annual_turnover_eur: float = 0.0,
56
+ is_sme: bool = False,
57
+ ) -> FineExposureEstimate:
58
+ """
59
+ Calculates maximum fine liability exposure according to Article 99 rules.
60
+ """
61
+ if not violations:
62
+ return FineExposureEstimate(
63
+ is_non_compliant=False,
64
+ highest_tier_triggered="NONE",
65
+ statutory_legal_basis="Article 99 (Full Compliance)",
66
+ maximum_fine_eur=0.0,
67
+ turnover_percentage=0.0,
68
+ applicable_ceiling_eur=0.0,
69
+ is_sme_discount_applied=is_sme,
70
+ assumed_annual_turnover_eur=annual_turnover_eur,
71
+ affected_articles=[],
72
+ executive_liability_summary="Zero statutory fine liability. System satisfies audited regulatory constraints.",
73
+ )
74
+
75
+ affected_articles = sorted(set(v.regulatory_article for v in violations))
76
+ has_prohibited = any("5" in art for art in affected_articles)
77
+ has_high_risk = any(any(hr in art for hr in ["9", "10", "11", "12", "13", "14", "15", "16", "26", "27"]) for art in affected_articles)
78
+
79
+ if has_prohibited:
80
+ tier_name = "TIER_1_PROHIBITED_AI"
81
+ fixed_max = 35_000_000.0
82
+ pct_max = 7.0
83
+ legal_basis = "Article 99(3) [Infringement of Prohibited AI Practices in Article 5]"
84
+ elif has_high_risk:
85
+ tier_name = "TIER_2_HIGH_RISK_OBLIGATIONS"
86
+ fixed_max = 15_000_000.0
87
+ pct_max = 3.0
88
+ legal_basis = "Article 99(4) [Non-compliance with Chapter III High-Risk Requirements]"
89
+ else:
90
+ tier_name = "TIER_3_MISINFORMATION_NOTIFICATION"
91
+ fixed_max = 7_500_000.0
92
+ pct_max = 1.5
93
+ legal_basis = "Article 99(5) [General Infringement]"
94
+
95
+ turnover_based_fine = (annual_turnover_eur * (pct_max / 100.0)) if annual_turnover_eur > 0 else 0.0
96
+
97
+ if is_sme:
98
+ # Article 99(6): min(fixed_max, percentage_based_fine)
99
+ if annual_turnover_eur > 0:
100
+ applicable_ceiling = min(fixed_max, turnover_based_fine)
101
+ else:
102
+ applicable_ceiling = fixed_max
103
+ summary = (
104
+ f"SME Status Active (Article 99(6)): Maximum statutory fine capped at "
105
+ f"€{applicable_ceiling:,.2f} under {legal_basis} (subject to the lower of €{fixed_max:,.0f} or {pct_max}% of turnover)."
106
+ )
107
+ else:
108
+ # Standard enterprise: whichever is higher
109
+ applicable_ceiling = max(fixed_max, turnover_based_fine)
110
+ summary = (
111
+ f"Enterprise Exposure: Maximum statutory fine of up to "
112
+ f"€{applicable_ceiling:,.2f} under {legal_basis} (higher of €{fixed_max:,.0f} or {pct_max}% worldwide annual turnover)."
113
+ )
114
+
115
+ return FineExposureEstimate(
116
+ is_non_compliant=True,
117
+ highest_tier_triggered=tier_name,
118
+ statutory_legal_basis=legal_basis,
119
+ maximum_fine_eur=fixed_max,
120
+ turnover_percentage=pct_max,
121
+ applicable_ceiling_eur=applicable_ceiling,
122
+ is_sme_discount_applied=is_sme,
123
+ assumed_annual_turnover_eur=annual_turnover_eur,
124
+ affected_articles=affected_articles,
125
+ executive_liability_summary=summary,
126
+ )
src/reasoning/framework_crosswalk.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Multi-Framework Regulatory Harmonization Crosswalk.
3
+ Projects EU AI Act (Regulation EU 2024/1689) conformity findings onto:
4
+ - NIST AI RMF 1.0 (GOVERN, MAP, MEASURE, MANAGE)
5
+ - ISO/IEC 42001:2023 (Clauses & Annex A Controls)
6
+ - GDPR (Regulation EU 2016/679)
7
+ """
8
+
9
+ import json
10
+ from pathlib import Path
11
+ from typing import Dict, List, Any, Optional
12
+ from pydantic import BaseModel, Field
13
+
14
+ from src.core.config import BENCHMARKS_DIR
15
+ from src.core.models import ValidationViolation
16
+
17
+
18
+ class FrameworkControlStatus(BaseModel):
19
+ control_id: str
20
+ control_name: str
21
+ target_framework: str
22
+ status: str # "SATISFIED", "NON_COMPLIANT", "NOT_EVALUATED"
23
+ eu_ai_act_article: str
24
+ relationship_type: str
25
+ semantic_rationale: str
26
+ audit_guidance: str
27
+
28
+
29
+ class FrameworkSummary(BaseModel):
30
+ total_mapped_controls: int
31
+ satisfied_controls_count: int
32
+ non_compliant_controls_count: int
33
+ conformity_percentage: float
34
+ controls: List[FrameworkControlStatus] = Field(default_factory=list)
35
+
36
+
37
+ class MultiFrameworkCrosswalkResult(BaseModel):
38
+ frameworks: Dict[str, FrameworkSummary] = Field(default_factory=dict)
39
+ high_level_summary: str = ""
40
+
41
+
42
+ class MultiFrameworkCrosswalk:
43
+ def __init__(self, mappings_path: Optional[Path] = None):
44
+ self.mappings_file = mappings_path or (BENCHMARKS_DIR / "rules" / "cross_regulatory_frameworks.json")
45
+ self.mappings: List[Dict[str, Any]] = []
46
+ self._load_mappings()
47
+
48
+ def _load_mappings(self) -> None:
49
+ if self.mappings_file.exists():
50
+ with open(self.mappings_file, "r", encoding="utf-8") as f:
51
+ data = json.load(f)
52
+ self.mappings = data.get("mappings", [])
53
+ else:
54
+ self.mappings = []
55
+
56
+ def harmonize(
57
+ self,
58
+ violations: List[ValidationViolation],
59
+ all_evaluated_articles: Optional[List[str]] = None,
60
+ ) -> MultiFrameworkCrosswalkResult:
61
+ """
62
+ Projects EU AI Act conformity assessment results across target frameworks.
63
+ """
64
+ violation_articles = set(v.regulatory_article.strip() for v in violations)
65
+ # Normalize: e.g. "Article 9(2)" -> "Article 9" prefix match
66
+ def is_article_violated(article_name: str) -> bool:
67
+ for v_art in violation_articles:
68
+ if article_name.startswith(v_art) or v_art.startswith(article_name):
69
+ return True
70
+ return False
71
+
72
+ framework_controls: Dict[str, List[FrameworkControlStatus]] = {
73
+ "NIST AI RMF 1.0": [],
74
+ "ISO/IEC 42001:2023": [],
75
+ "GDPR (EU 2016/679)": [],
76
+ }
77
+
78
+ for m in self.mappings:
79
+ target_fw = m.get("target_framework", "Unknown")
80
+ eu_art = m.get("eu_ai_act_article", "")
81
+ has_violation = is_article_violated(eu_art)
82
+
83
+ status = "NON_COMPLIANT" if has_violation else "SATISFIED"
84
+
85
+ ctrl_status = FrameworkControlStatus(
86
+ control_id=m.get("target_control_id", ""),
87
+ control_name=m.get("target_control_name", ""),
88
+ target_framework=target_fw,
89
+ status=status,
90
+ eu_ai_act_article=eu_art,
91
+ relationship_type=m.get("relationship_type", "EXACT_EQUIVALENT"),
92
+ semantic_rationale=m.get("semantic_rationale", ""),
93
+ audit_guidance=m.get("audit_guidance", ""),
94
+ )
95
+
96
+ if target_fw in framework_controls:
97
+ framework_controls[target_fw].append(ctrl_status)
98
+ else:
99
+ framework_controls.setdefault(target_fw, []).append(ctrl_status)
100
+
101
+ framework_summaries: Dict[str, FrameworkSummary] = {}
102
+ total_satisfied = 0
103
+ total_controls = 0
104
+
105
+ for fw_name, ctrls in framework_controls.items():
106
+ tot = len(ctrls)
107
+ sat = sum(1 for c in ctrls if c.status == "SATISFIED")
108
+ non = sum(1 for c in ctrls if c.status == "NON_COMPLIANT")
109
+ pct = round((sat / tot * 100.0), 1) if tot > 0 else 100.0
110
+
111
+ total_satisfied += sat
112
+ total_controls += tot
113
+
114
+ framework_summaries[fw_name] = FrameworkSummary(
115
+ total_mapped_controls=tot,
116
+ satisfied_controls_count=sat,
117
+ non_compliant_controls_count=non,
118
+ conformity_percentage=pct,
119
+ controls=ctrls,
120
+ )
121
+
122
+ overall_pct = round((total_satisfied / total_controls * 100.0), 1) if total_controls > 0 else 100.0
123
+ summary_text = (
124
+ f"Multi-framework crosswalk mapped across {len(framework_summaries)} international frameworks: "
125
+ f"{total_satisfied}/{total_controls} controls satisfied ({overall_pct}% alignment). "
126
+ 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}%, "
127
+ 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}%, "
128
+ 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}%."
129
+ )
130
+
131
+ return MultiFrameworkCrosswalkResult(
132
+ frameworks=framework_summaries,
133
+ high_level_summary=summary_text,
134
+ )
src/triage/report_generator.py CHANGED
@@ -68,8 +68,35 @@ class ConformityReportGenerator:
68
  md.append(f"| `{c.claim_id}` | `{c.category.value}` | {status_emoji} {c.assertion_status.value} | {c.confidence:.2f} | {c.normative_article} | *\"{c.evidence_quote[:75]}...\"* |")
69
  md.append("")
70
 
71
- # Section 5: Cryptographic Provenance Ledger
72
- md.append("## 5. Cryptographic Provenance & Audit Ledger (W3C PROV-O)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  md.append("Every artifact in this assessment is cryptographically anchored to prevent tampering and guarantee non-repudiation:")
74
  md.append(f"- **Source Specification SHA-256:** `{prov.input_doc_sha256}`")
75
  md.append(f"- **Normative RDF Knowledge Graph Canonical SHA-256:** `{prov.graph_triples_sha256}`")
@@ -144,6 +171,50 @@ class ConformityReportGenerator:
144
  </tr>
145
  """
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  html = f"""<!DOCTYPE html>
148
  <html>
149
  <head>
@@ -284,6 +355,8 @@ class ConformityReportGenerator:
284
  <div class="info-item"><strong>Conformity Score</strong> {report.conformity_score:.1f}% ({report.passed_requirements_count}/{report.total_requirements_evaluated} requirements passed)</div>
285
  </div>
286
 
 
 
287
  <h3 style="font-size: 14px; text-transform: uppercase; margin-bottom: 8px;">Deterministic Normative Evaluation Matrix</h3>
288
  <table>
289
  <thead>
@@ -298,6 +371,8 @@ class ConformityReportGenerator:
298
  </tbody>
299
  </table>
300
 
 
 
301
  <div class="crypto-block">
302
  <strong>CRYPTOGRAPHIC PROVENANCE LEDGER (W3C PROV-O)</strong><br>
303
  Certificate Token: {prov.digital_signature}<br>
 
68
  md.append(f"| `{c.claim_id}` | `{c.category.value}` | {status_emoji} {c.assertion_status.value} | {c.confidence:.2f} | {c.normative_article} | *\"{c.evidence_quote[:75]}...\"* |")
69
  md.append("")
70
 
71
+ # Section 5: Multi-Framework Regulatory Harmonization
72
+ if report.harmonized_frameworks:
73
+ md.append("## 5. Multi-Framework Regulatory Harmonization (NIST RMF / ISO 42001 / GDPR)")
74
+ fw_data = report.harmonized_frameworks.get("frameworks", {})
75
+ for fw_name, fw_summary in fw_data.items():
76
+ pct = fw_summary.get("conformity_percentage", 100.0)
77
+ sat = fw_summary.get("satisfied_controls_count", 0)
78
+ tot = fw_summary.get("total_mapped_controls", 0)
79
+ md.append(f"### {fw_name} (Alignment: {pct}% - {sat}/{tot} controls)")
80
+ md.append("| Target Control | Control Name | Status | Linked AI Act Article | Audit Guidance |")
81
+ md.append("|---|---|---|---|---|")
82
+ for ctrl in fw_summary.get("controls", []):
83
+ c_badge = "🟢 SATISFIED" if ctrl.get("status") == "SATISFIED" else "🔴 NON-COMPLIANT"
84
+ md.append(f"| `{ctrl.get('control_id')}` | {ctrl.get('control_name')} | {c_badge} | **{ctrl.get('eu_ai_act_article')}** | {ctrl.get('audit_guidance')} |")
85
+ md.append("")
86
+
87
+ # Section 6: Statutory Fine Liability Analysis
88
+ if report.fine_exposure:
89
+ fine = report.fine_exposure
90
+ md.append("## 6. Article 99 Statutory Fine & Financial Liability Audit")
91
+ md.append(f"- **Highest Triggered Penalty Tier:** `{fine.get('highest_tier_triggered')}`")
92
+ md.append(f"- **Legal Basis:** {fine.get('statutory_legal_basis')}")
93
+ md.append(f"- **Maximum Statutory Ceiling:** **€{fine.get('applicable_ceiling_eur', 0):,.2f}**")
94
+ md.append(f"- **Turnover Penalty Rate:** {fine.get('turnover_percentage', 0)}% of global annual turnover")
95
+ md.append(f"- **SME Special Cap Applied:** {'Yes (Article 99(6))' if fine.get('is_sme_discount_applied') else 'No'}")
96
+ md.append(f"- **Executive Liability Assessment:** {fine.get('executive_liability_summary')}\n")
97
+
98
+ # Section 7: Cryptographic Provenance Ledger
99
+ md.append("## 7. Cryptographic Provenance & Audit Ledger (W3C PROV-O)")
100
  md.append("Every artifact in this assessment is cryptographically anchored to prevent tampering and guarantee non-repudiation:")
101
  md.append(f"- **Source Specification SHA-256:** `{prov.input_doc_sha256}`")
102
  md.append(f"- **Normative RDF Knowledge Graph Canonical SHA-256:** `{prov.graph_triples_sha256}`")
 
171
  </tr>
172
  """
173
 
174
+ fine_box_html = ""
175
+ if report.fine_exposure:
176
+ fine = report.fine_exposure
177
+ ceiling = fine.get("applicable_ceiling_eur", 0.0)
178
+ f_tier = fine.get("highest_tier_triggered", "NONE")
179
+ f_color = "#15803d" if ceiling == 0.0 else ("#b91c1c" if "PROHIBITED" in f_tier else "#c2410c")
180
+ f_bg = "#f0fdf4" if ceiling == 0.0 else "#fff7ed"
181
+ f_border = "#bbf7d0" if ceiling == 0.0 else "#fed7aa"
182
+
183
+ fine_box_html = f"""
184
+ <div style="background: {f_bg}; border: 1px solid {f_border}; padding: 12px 16px; border-radius: 6px; margin-bottom: 20px;">
185
+ <div style="font-size: 11px; font-weight: 700; color: {f_color}; text-transform: uppercase;">Article 99 Statutory Fine Liability Exposure</div>
186
+ <div style="font-size: 18px; font-weight: 800; color: {f_color}; margin: 2px 0;">
187
+ €{ceiling:,.2f} <span style="font-size: 12px; font-weight: 500; color: #64748b;">({f_tier})</span>
188
+ </div>
189
+ <div style="font-size: 12px; color: #475569;">
190
+ {fine.get('executive_liability_summary', '')}
191
+ </div>
192
+ </div>
193
+ """
194
+
195
+ frameworks_html = ""
196
+ if report.harmonized_frameworks:
197
+ fw_data = report.harmonized_frameworks.get("frameworks", {})
198
+ fw_badges = ""
199
+ for fw_name, fw_info in fw_data.items():
200
+ fw_pct = fw_info.get("conformity_percentage", 100.0)
201
+ fw_sat = fw_info.get("satisfied_controls_count", 0)
202
+ fw_tot = fw_info.get("total_mapped_controls", 0)
203
+ b_color = "#15803d" if fw_pct == 100.0 else "#d97706"
204
+ fw_badges += f"""
205
+ <div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 10px; border-radius: 6px; flex: 1;">
206
+ <div style="font-size: 11px; font-weight: 700; color: #64748b;">{fw_name}</div>
207
+ <div style="font-size: 16px; font-weight: 800; color: {b_color};">{fw_pct}%</div>
208
+ <div style="font-size: 11px; color: #94a3b8;">{fw_sat}/{fw_tot} controls compliant</div>
209
+ </div>
210
+ """
211
+ frameworks_html = f"""
212
+ <h3 style="font-size: 14px; text-transform: uppercase; margin: 20px 0 8px 0;">Multi-Framework Harmonization Crosswalk</h3>
213
+ <div style="display: flex; gap: 10px; margin-bottom: 20px;">
214
+ {fw_badges}
215
+ </div>
216
+ """
217
+
218
  html = f"""<!DOCTYPE html>
219
  <html>
220
  <head>
 
355
  <div class="info-item"><strong>Conformity Score</strong> {report.conformity_score:.1f}% ({report.passed_requirements_count}/{report.total_requirements_evaluated} requirements passed)</div>
356
  </div>
357
 
358
+ {fine_box_html}
359
+
360
  <h3 style="font-size: 14px; text-transform: uppercase; margin-bottom: 8px;">Deterministic Normative Evaluation Matrix</h3>
361
  <table>
362
  <thead>
 
371
  </tbody>
372
  </table>
373
 
374
+ {frameworks_html}
375
+
376
  <div class="crypto-block">
377
  <strong>CRYPTOGRAPHIC PROVENANCE LEDGER (W3C PROV-O)</strong><br>
378
  Certificate Token: {prov.digital_signature}<br>
tests/test_api.py CHANGED
@@ -36,12 +36,47 @@ def test_api_evaluate_endpoint():
36
  assert result["overall_conforms"] is True
37
  assert result["conformity_score"] == 100.0
38
  assert result["certificate_token"].startswith("REGU-")
 
 
39
 
40
 
41
  def test_api_certificate_html():
42
  response = client.get("/api/v1/certificates/REGU-DEMO-TEST/html")
43
  assert response.status_code == 200
44
  assert "EU AI Act Conformity Attestation" in response.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
 
47
  def test_api_triage_feedback():
 
36
  assert result["overall_conforms"] is True
37
  assert result["conformity_score"] == 100.0
38
  assert result["certificate_token"].startswith("REGU-")
39
+ assert "fine_exposure" in result
40
+ assert "harmonized_frameworks" in result
41
 
42
 
43
  def test_api_certificate_html():
44
  response = client.get("/api/v1/certificates/REGU-DEMO-TEST/html")
45
  assert response.status_code == 200
46
  assert "EU AI Act Conformity Attestation" in response.text
47
+ assert "Article 99 Statutory Fine Liability Exposure" in response.text
48
+
49
+
50
+ def test_api_framework_crosswalk():
51
+ response = client.get("/api/v1/frameworks/crosswalk")
52
+ assert response.status_code == 200
53
+ data = response.json()
54
+ assert data["total_mappings"] >= 20
55
+ assert any(m["target_framework"] == "NIST AI RMF 1.0" for m in data["mappings"])
56
+ assert any(m["target_framework"] == "ISO/IEC 42001:2023" for m in data["mappings"])
57
+ assert any("GDPR" in m["target_framework"] for m in data["mappings"])
58
+
59
+
60
+ def test_api_penalties_calculate():
61
+ # Test Tier 1 Prohibited practice penalty
62
+ response = client.post(
63
+ "/api/v1/penalties/calculate",
64
+ json={"violations": ["Article 5(1)(c)"], "annual_turnover_eur": 500_000_000, "is_sme": False},
65
+ )
66
+ assert response.status_code == 200
67
+ data = response.json()
68
+ assert data["highest_tier_triggered"] == "TIER_1_PROHIBITED_AI"
69
+ assert data["applicable_ceiling_eur"] == 35_000_000.0 # 7% of 500M is 35M
70
+
71
+ # Test SME cap
72
+ sme_res = client.post(
73
+ "/api/v1/penalties/calculate",
74
+ json={"violations": ["Article 14"], "annual_turnover_eur": 10_000_000, "is_sme": True},
75
+ )
76
+ assert sme_res.status_code == 200
77
+ sme_data = sme_res.json()
78
+ assert sme_data["is_sme_discount_applied"] is True
79
+ assert sme_data["applicable_ceiling_eur"] == 300_000.0 # min(15M, 3% of 10M = 300k)
80
 
81
 
82
  def test_api_triage_feedback():