gitmodelmujtaba commited on
Commit
ac8e628
·
verified ·
1 Parent(s): 88219a2

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

Browse files
README.md CHANGED
@@ -1,13 +1,179 @@
1
  ---
2
- title: Reguai Engine
3
- emoji: 🐢
4
- colorFrom: pink
5
- colorTo: gray
6
  sdk: gradio
7
  sdk_version: 6.28.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: ReguAI Neuro-Symbolic AI GRC Engine
3
+ emoji: 🏛️
4
+ colorFrom: blue
5
+ colorTo: indigo
6
  sdk: gradio
7
  sdk_version: 6.28.0
 
8
  app_file: app.py
9
  pinned: false
10
+ license: apache-2.0
11
+ short_description: Neuro-Symbolic AI GRC & EU AI Act Conformity
12
  ---
13
 
14
+ # 🏛️ ReguAI: Deterministic Neuro-Symbolic AI GRC & Automated Conformity Assessment Engine
15
+
16
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
17
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-brightgreen.svg)](https://www.python.org/)
18
+ [![EU AI Act](https://img.shields.io/badge/Compliance-EU_AI_Act_(2024%2F1689)-navy.svg)](https://data.europa.eu/eli/reg/2024/1689/oj)
19
+ [![W3C SHACL](https://img.shields.io/badge/Logic-W3C_SHACL_Deterministic-orange.svg)](https://www.w3.org/TR/shacl/)
20
+ [![W3C PROV-O](https://img.shields.io/badge/Audit-W3C_PROV--O_Cryptographic-purple.svg)](https://www.w3.org/TR/prov-o/)
21
+
22
+ > **ReguAI bridges Generative AI with Formal Symbolic Reasoning (Neuro-Symbolic AI)**: It ingests enterprise model cards, system architecture documentation, and training logs, grounds them into an authoritative multi-framework regulatory knowledge graph, executes mathematically deterministic constraint verification via **W3C SHACL**, and outputs cryptographically provenanced **EU AI Act Annex IV Conformity Assessments**.
23
+
24
+ ---
25
+
26
+ ## 💥 The Problem ReguAI Solves
27
+
28
+ The global AI industry is facing a massive regulatory crunch. With the **EU AI Act (Regulation (EU) 2024/1689)** entering strict enforcement alongside **ISO/IEC 42001**, **NIST AI RMF 1.0**, and **FDA SaMD guidelines**, enterprise compliance teams face a double failure:
29
+
30
+ 1. **Manual Compliance is Unscalable**: Auditing complex ML pipelines, data lineage, and model cards via spreadsheets takes months and millions in legal advisory costs.
31
+ 2. **Standard GenAI / RAG Hallucinates**: Using probabilistic LLMs for legal and regulatory verification carries strict-liability risk. Stochastic, non-deterministic systems cannot provide mathematical guarantees of compliance.
32
+
33
+ **ReguAI eliminates stochastic liability by separating extraction from reasoning**:
34
+ - **Neural Layer**: Domain-adapted NLP / NER extractors scan technical whitepapers and model cards to detect regulatory entities and extract NegEx assertion statuses (`Implemented`, `Planned`, `Absent`).
35
+ - **Symbolic Core**: W3C SHACL shape constraints execute deterministic validation over an RDF knowledge graph. If an Article 14 human oversight fallback is missing, it is caught with zero hallucinations, citing the exact legal clause and remediation.
36
+ - **Cryptographic Provenance**: Every evaluation step is hashed with SHA-256 and recorded into an immutable W3C PROV-O digital ledger.
37
+
38
+ ---
39
+
40
+ ## 🏛️ System Architecture
41
+
42
+ ```mermaid
43
+ graph TD
44
+ A[System Artifacts / Model Cards / Tech Docs] --> B[Clinical/Legal GLiNER Claim Extraction]
45
+ B --> C[Assertion & Claim Triage: NegEx]
46
+ subgraph "Symbolic Knowledge Core"
47
+ D[Multi-Regulation KG: EU AI Act, NIST RMF, ISO 42001]
48
+ E[W3C SHACL Constraint Validator]
49
+ D --> E
50
+ end
51
+ C --> F[Neuro-Symbolic Reasoning & Graph Alignment]
52
+ E --> F
53
+ F --> G[Cryptographic Ledger: SHA-256 + W3C PROV-O]
54
+ F --> H[Active Learning & Auditor-in-the-Loop Triage]
55
+ G --> I[Automated Conformity Certificate & Annex IV Audit Package]
56
+ H -->|Feedback Loop & Triplet Loss| C
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 🔬 Core Technical Modules
62
+
63
+ ### 1. Multi-Framework Normative Knowledge Graph (`src/ontology/`)
64
+ - Formal OWL/RDFS ontologies formalizing **EU AI Act Chapter III (High-Risk AI Systems)**:
65
+ - **Article 9**: Risk Management Systems (`regu:RiskManagementSystem`, `nist:GOVERN`)
66
+ - **Article 10**: Data Governance & Quality (`regu:DataGovernanceProcess`, `nist:MAP`)
67
+ - **Article 10(2)(f)**: Bias Examination & Mitigation (`regu:BiasMitigationControl`, `nist:MEASURE_2.11`)
68
+ - **Article 11 & Annex IV**: Technical Documentation Package (`regu:TechnicalDocumentation`)
69
+ - **Article 12**: Automated Record-Keeping / Logging (`regu:AutomatedLogging`, `nist:GOVERN_1.5`)
70
+ - **Article 13**: Transparency & Instructions for Use (`regu:TransparencySpecification`)
71
+ - **Article 14**: Human Oversight & Emergency Stop (`regu:HumanOversightMechanism`, `regu:StopMechanism`)
72
+ - **Article 15**: Accuracy, Robustness & Cybersecurity (`regu:CybersecurityControl`, `nist:MEASURE_2.6`)
73
+
74
+ ### 2. Deterministic Verification Engine (`src/reasoning/shacl_engine.py`)
75
+ - Executes formal **W3C SHACL (Shapes Constraint Language)** constraints via PySHACL.
76
+ - Enforces property path checks, cardinalities, and value constraints (e.g. `regu:implementationStatus` must have value `regu:Implemented`).
77
+ - Output is a mathematically provable compliance report with zero LLM hallucinations.
78
+
79
+ ### 3. Regulatory Claim Extraction & NegEx Grounding (`src/extraction/`)
80
+ - Ingests Markdown model cards, YAML specs, or JSON architectures.
81
+ - Extracts regulatory entities across 10 compliance domains.
82
+ - Evaluates negation and assertion cues with syntactic NegEx logic:
83
+ - `IMPLEMENTED`: Verified operational controls in active production.
84
+ - `PLANNED`: Controls on future roadmaps (e.g., "planned for Q4").
85
+ - `ABSENT`: Missing or negated controls (e.g., "untested against adversarial attacks").
86
+
87
+ ### 4. Cryptographic Provenance Ledger (`src/ledger/`)
88
+ - Produces tamper-evident digital verification ledgers adhering to the **W3C PROV-O** standard.
89
+ - Deterministic SHA-256 hashing across input document snapshots, canonical sorted N-Triples graph representations, and regulatory rulesets.
90
+ - Generates official non-repudiation conformity tokens (e.g. `REGU-EU2024-1689-SAMDONCO-7B12F98C12`).
91
+
92
+ ### 5. Auditor-in-the-Loop Active Learning Queue (`src/triage/`)
93
+ - Automatically flags borderline or ambiguous claims ($0.55 \le \text{confidence} < 0.85$ or contradictory cues) to human compliance auditors.
94
+ - Auditor feedback generates triplet training instances `(anchor_text, positive_label, negative_label)` for continuous metric learning and semantic alignment.
95
+
96
+ ---
97
+
98
+ ## 📦 High-Impact Portfolio Deliverables
99
+
100
+ | Deliverable | Type | Location | Description |
101
+ |---|---|---|---|
102
+ | **reguai-engine** | Full-Stack App | `app.py` | Interactive Hugging Face Space application for one-click deterministic auditing. |
103
+ | **eu-ai-act-normative-triples** | Benchmark Dataset | `data/benchmarks/` | Benchmark dataset mapping EU AI Act high-risk obligations into RDF/JSON-LD triples. |
104
+ | **gliner-legal-ai-grc** | Extraction Engine | `src/extraction/` | Domain-adapted entity and assertion extraction pipeline for AI governance. |
105
+ | **SHACL High-Risk Ruleset** | Semantic Shapes | `src/ontology/shacl/` | Formal W3C SHACL constraints implementing EU AI Act Articles 9-15. |
106
+ | **Annex IV Documentation Generator** | Audit Package | `src/triage/` | Generates official EU AI Act Annex IV technical documentation and JSON-LD certificates. |
107
+
108
+ ---
109
+
110
+ ## 🚀 Quickstart & Usage
111
+
112
+ ### 1. Installation
113
+
114
+ ```bash
115
+ # Clone the repository
116
+ git clone https://github.com/your-username/reguAI.git
117
+ cd reguAI
118
+
119
+ # Set up virtual environment
120
+ python -m venv .venv
121
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
122
+
123
+ # Install dependencies
124
+ pip install -r requirements.txt
125
+ ```
126
+
127
+ ### 2. Launch Interactive Hugging Face Space (with Vis.js Graph Explorer)
128
+
129
+ ```bash
130
+ python app.py
131
+ ```
132
+ Open your browser at `http://localhost:7860` to access the full interactive dashboard, force-directed graph visualizer, and print-ready Annex IV attestation certificate.
133
+
134
+ ### 3. Launch Enterprise CI/CD REST API (FastAPI)
135
+
136
+ ```bash
137
+ python api.py
138
+ ```
139
+ Interactive Swagger / OpenAPI docs are available at `http://localhost:8000/docs`.
140
+
141
+ ### 4. Programmatic Usage (Python SDK)
142
+
143
+ ```python
144
+ from src.engine import ReguAIEngine
145
+
146
+ # Initialize ReguAI Neuro-Symbolic Engine
147
+ engine = ReguAIEngine()
148
+
149
+ # Evaluate any model card, tech spec, or JSON file
150
+ report = engine.evaluate_system("data/synthetic_systems/compliant_clinical_samd.json")
151
+
152
+ print(f"Conformity Status: {'PASS' if report.overall_conforms else 'FAIL'}")
153
+ print(f"Conformity Score: {report.conformity_score}%")
154
+ print(f"Digital Token: {report.provenance.digital_signature}")
155
+
156
+ # Generate official Annex IV Technical Documentation (Markdown)
157
+ markdown_report = engine.report_generator.generate_markdown_report(report)
158
+
159
+ # Export Machine-Readable JSON-LD Certificate
160
+ json_ld_cert = engine.report_generator.generate_json_ld(report)
161
+
162
+ # Generate Print-Ready HTML Attestation Certificate
163
+ html_cert = engine.report_generator.generate_html_certificate(report)
164
+ ```
165
+
166
+ ### 5. Running the Test Suite
167
+
168
+ ```bash
169
+ pytest tests/ -v
170
+ ```
171
+
172
+ ---
173
+
174
+ ## 🎯 The STAR Story for Interviews & Portfolio
175
+
176
+ - **Situation:** The enforcement of the EU AI Act (Regulation (EU) 2024/1689) and ISO 42001 created massive compliance overhead for AI engineering teams, while probabilistic LLMs were too hallucination-prone for zero-defect regulatory auditing.
177
+ - **Task:** Build an end-to-end, neuro-symbolic AI GRC platform capable of deterministically auditing AI systems against normative legal standards with full cryptographic provenance.
178
+ - **Action:** Constructed a unified legal ontology mapping the EU AI Act and NIST AI RMF; implemented formal W3C SHACL shape constraints; integrated fine-tuned GLiNER/SapBERT models for semantic claim extraction; and built a SHA-256/PROV-O audit ledger with an active learning human-in-the-loop review queue.
179
+ - **Result:** Achieved deterministic, zero-hallucination compliance checking with sub-second execution, an open-source regulatory benchmark on Hugging Face, and a functional reference implementation for automated enterprise conformity assessments.
api.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ReguAI Enterprise REST API.
3
+ Provides high-throughput, CI/CD automated AI conformity verification endpoints for MLOps pipelines.
4
+ """
5
+
6
+ from fastapi import FastAPI, HTTPException, BackgroundTasks, Query
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from fastapi.responses import HTMLResponse, JSONResponse
9
+ from pydantic import BaseModel, Field
10
+ from typing import Optional, Dict, Any, List
11
+ from pathlib import Path
12
+ import json
13
+
14
+ from src.engine import ReguAIEngine
15
+ from src.core.config import SYNTHETIC_DIR
16
+ from src.core.models import (
17
+ ConformityReport,
18
+ AssertionStatus,
19
+ EntityCategory,
20
+ )
21
+
22
+ app = FastAPI(
23
+ title="ReguAI Conformity Assessment API",
24
+ description="Automated Neuro-Symbolic AI GRC & W3C SHACL verification engine for EU AI Act, NIST AI RMF, & ISO 42001.",
25
+ version="0.1.0",
26
+ )
27
+
28
+ # Enable CORS for frontend visualizers
29
+ app.add_middleware(
30
+ CORSMiddleware,
31
+ allow_origins=["*"],
32
+ allow_credentials=True,
33
+ allow_methods=["*"],
34
+ allow_headers=["*"],
35
+ )
36
+
37
+ engine = ReguAIEngine()
38
+
39
+ # In-memory certificate cache for demonstration lookups
40
+ CERTIFICATE_CACHE: Dict[str, ConformityReport] = {}
41
+
42
+
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):
49
+ claim_id: str
50
+ auditor_id: str
51
+ verified_status: AssertionStatus
52
+ verified_category: EntityCategory
53
+ notes: Optional[str] = ""
54
+
55
+
56
+ @app.get("/health", tags=["System"])
57
+ def health_check():
58
+ return {
59
+ "status": "HEALTHY",
60
+ "engine": "ReguAI Neuro-Symbolic Reasoning Core",
61
+ "version": "0.1.0",
62
+ "shacl_validator": "W3C SHACL compliant",
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
+ """
69
+ Deterministically evaluates an AI system specification against EU AI Act Chapter III SHACL shapes.
70
+ """
71
+ if not request.specification_text.strip():
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
+
79
+ return {
80
+ "system_id": report.system_metadata.system_id,
81
+ "system_name": report.system_metadata.name,
82
+ "overall_conforms": report.overall_conforms,
83
+ "conformity_score": report.conformity_score,
84
+ "certificate_token": token,
85
+ "total_requirements": report.total_requirements_evaluated,
86
+ "passed_requirements": report.passed_requirements_count,
87
+ "violations_count": len(report.violations),
88
+ "violations": [
89
+ {
90
+ "article": v.regulatory_article,
91
+ "message": v.message,
92
+ "remediation": v.remediation_guidance,
93
+ "shacl_path": v.result_path,
94
+ }
95
+ for v in report.violations
96
+ ],
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,
103
+ "ruleset_sha256": report.provenance.ruleset_sha256,
104
+ },
105
+ }
106
+ except Exception as e:
107
+ raise HTTPException(status_code=500, detail=f"Conformity assessment failed: {str(e)}")
108
+
109
+
110
+ @app.get("/api/v1/audit/samples", tags=["Benchmarks"])
111
+ def list_benchmark_samples():
112
+ """Returns available pre-loaded synthetic case studies."""
113
+ return [
114
+ {"id": "compliant_clinical_samd", "title": "OncoScan AI Diagnostic Assistant (SaMD - Compliant)"},
115
+ {"id": "non_compliant_hr_recruitment", "title": "TalentSift Automated Candidate Evaluator (HR - Violations)"},
116
+ {"id": "borderline_credit_scoring", "title": "CrediScore Neural Underwriter (FinTech - Planned Roadmap)"},
117
+ ]
118
+
119
+
120
+ @app.get("/api/v1/audit/samples/{sample_id}", tags=["Benchmarks"])
121
+ def get_sample_content(sample_id: str):
122
+ """Retrieves full specification content for a sample."""
123
+ file_path = SYNTHETIC_DIR / f"{sample_id}.json"
124
+ if not file_path.exists():
125
+ raise HTTPException(status_code=404, detail="Sample not found.")
126
+ data = json.loads(file_path.read_text(encoding="utf-8"))
127
+ return data
128
+
129
+
130
+ @app.get("/api/v1/certificates/{token}/html", response_class=HTMLResponse, tags=["Conformity Assessment"])
131
+ def get_certificate_html(token: str):
132
+ """Renders the official print-ready Annex IV HTML Certificate."""
133
+ report = CERTIFICATE_CACHE.get(token)
134
+ if not report:
135
+ # Fallback to compliant sample if token is demo
136
+ samd_path = SYNTHETIC_DIR / "compliant_clinical_samd.json"
137
+ report = engine.evaluate_system(samd_path)
138
+
139
+ html = engine.report_generator.generate_html_certificate(report)
140
+ return HTMLResponse(content=html)
141
+
142
+
143
+ @app.post("/api/v1/triage/feedback", tags=["Active Learning"])
144
+ def submit_auditor_feedback(feedback: TripletFeedbackRequest):
145
+ """
146
+ Captures human auditor feedback on borderline claims and formats
147
+ triplet training pairs for continuous metric alignment.
148
+ """
149
+ from src.core.models import ExtractedClaim
150
+ dummy = ExtractedClaim(
151
+ claim_id=feedback.claim_id,
152
+ entity_text="Audited Claim",
153
+ category=feedback.verified_category,
154
+ assertion_status=feedback.verified_status,
155
+ confidence=1.0,
156
+ normative_article="EU AI Act Article 14",
157
+ evidence_quote=feedback.notes or "Auditor verified operational control.",
158
+ )
159
+ record = engine.triage_queue.record_auditor_decision(
160
+ claim=dummy,
161
+ auditor_id=feedback.auditor_id,
162
+ verified_status=feedback.verified_status,
163
+ verified_category=feedback.verified_category,
164
+ notes=feedback.notes or "",
165
+ )
166
+ return {
167
+ "status": "RECORDED",
168
+ "triplet": record,
169
+ "message": "Active learning triplet training instance generated successfully.",
170
+ }
171
+
172
+
173
+ if __name__ == "__main__":
174
+ import uvicorn
175
+ uvicorn.run(app, host="0.0.0.0", port=8000)
app.py ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ReguAI: Deterministic Neuro-Symbolic AI GRC & Automated Conformity Assessment Engine.
3
+ Full-stack interactive Hugging Face Space application with Vis.js Regulatory Graph Explorer
4
+ and Official Annex IV Print-Ready Attestation Certificate.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+ import json
11
+
12
+ # Ensure project root is in sys.path
13
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
14
+
15
+ import gradio as gr
16
+ from src.engine import ReguAIEngine
17
+ from src.core.config import SYNTHETIC_DIR
18
+ from src.core.models import AssertionStatus, EntityCategory
19
+ from src.ui.graph_view import RegulatoryGraphView
20
+
21
+ # Initialize ReguAI Engine & Graph Visualizer
22
+ engine = ReguAIEngine()
23
+ graph_viewer = RegulatoryGraphView()
24
+
25
+ # Pre-load sample specifications
26
+ SAMPLE_PATHS = {
27
+ "Healthcare / Medical AI (Compliant SaMD - Articles 9-15 Passed)": SYNTHETIC_DIR / "compliant_clinical_samd.json",
28
+ "HR / Recruitment AI (High-Risk - Human Oversight & Bias Non-Conformities)": SYNTHETIC_DIR / "non_compliant_hr_recruitment.json",
29
+ "FinTech / Credit Underwriting (Borderline - Planned Roadmap & Auditor Review)": SYNTHETIC_DIR / "borderline_credit_scoring.json",
30
+ }
31
+
32
+ def load_sample_content(sample_name: str) -> str:
33
+ path = SAMPLE_PATHS.get(sample_name)
34
+ if path and path.exists():
35
+ data = json.loads(path.read_text(encoding="utf-8"))
36
+ return data.get("raw_document_text", "")
37
+ return ""
38
+
39
+
40
+ def run_assessment(doc_text: str, auditor_id: str):
41
+ if not doc_text or not doc_text.strip():
42
+ return (
43
+ "⚠️ Please enter model card text or select a pre-loaded sample.",
44
+ [],
45
+ [],
46
+ "<div style='padding:20px;text-align:center;'>No graph generated.</div>",
47
+ "N/A",
48
+ "N/A",
49
+ "{}",
50
+ "",
51
+ "<div>No certificate generated.</div>",
52
+ [],
53
+ )
54
+
55
+ report = engine.evaluate_system(doc_text, auditor_id=auditor_id or "auditor_01")
56
+
57
+ # 1. Executive Summary HTML
58
+ status_color = "#10b981" if report.overall_conforms else "#ef4444"
59
+ status_text = "CONFORMS (PASSED)" if report.overall_conforms else "NON-CONFORMANT (FAILED)"
60
+
61
+ exec_html = f"""
62
+ <div style="border: 2px solid {status_color}; border-radius: 10px; padding: 18px; margin-bottom: 15px; background: rgba(16, 185, 129, 0.04);">
63
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
64
+ <h2 style="margin: 0; color: #1e293b; font-size: 20px;">System: {report.system_metadata.name} (v{report.system_metadata.version})</h2>
65
+ <span style="background: {status_color}; color: white; padding: 6px 14px; border-radius: 9999px; font-weight: bold; font-size: 13px;">
66
+ {status_text}
67
+ </span>
68
+ </div>
69
+ <p style="margin: 4px 0; color: #475569; font-size: 14px;"><strong>Domain:</strong> {report.system_metadata.domain} | <strong>Risk Class:</strong> {report.system_metadata.eu_risk_classification}</p>
70
+ <p style="margin: 8px 0; color: #334155; font-size: 14px; line-height: 1.5;">{report.executive_summary}</p>
71
+ <div style="display: flex; gap: 20px; margin-top: 14px;">
72
+ <div style="background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 16px; flex: 1;">
73
+ <div style="font-size: 11px; text-transform: uppercase; color: #64748b; font-weight: 600;">Conformity Index</div>
74
+ <div style="font-size: 22px; font-weight: 700; color: {status_color};">{report.conformity_score:.1f}%</div>
75
+ </div>
76
+ <div style="background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 16px; flex: 1;">
77
+ <div style="font-size: 11px; text-transform: uppercase; color: #64748b; font-weight: 600;">Requirements Evaluated</div>
78
+ <div style="font-size: 22px; font-weight: 700; color: #0f172a;">{report.passed_requirements_count} / {report.total_requirements_evaluated} Passed</div>
79
+ </div>
80
+ <div style="background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 16px; flex: 1;">
81
+ <div style="font-size: 11px; text-transform: uppercase; color: #64748b; font-weight: 600;">Deterministic Violations</div>
82
+ <div style="font-size: 22px; font-weight: 700; color: {'#ef4444' if report.violations else '#10b981'};">{len(report.violations)}</div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ """
87
+
88
+ # 2. SHACL Violations Data Table
89
+ violations_data = []
90
+ for v in report.violations:
91
+ violations_data.append([
92
+ v.regulatory_article,
93
+ v.message,
94
+ v.severity,
95
+ v.result_path,
96
+ v.remediation_guidance,
97
+ ])
98
+
99
+ # 3. Extracted Claims Table
100
+ claims_data = []
101
+ for c in report.claims_analyzed:
102
+ status_tag = f"🟢 {c.assertion_status.value}" if c.assertion_status.value == "IMPLEMENTED" else (
103
+ f"🟡 {c.assertion_status.value}" if c.assertion_status.value == "PLANNED" else f"🔴 {c.assertion_status.value}"
104
+ )
105
+ claims_data.append([
106
+ c.claim_id,
107
+ c.category.value,
108
+ status_tag,
109
+ f"{c.confidence:.2f}",
110
+ c.normative_article,
111
+ c.evidence_quote[:90] + "...",
112
+ ])
113
+
114
+ # 4. Interactive Graph View (Vis.js iframe wrapper)
115
+ raw_graph_html = graph_viewer.generate_html_graph(report)
116
+ escaped_graph = raw_graph_html.replace('"', '&quot;').replace("'", "&#39;")
117
+ graph_iframe_html = f"""
118
+ <iframe srcdoc="{escaped_graph}" style="width: 100%; height: 560px; border: 1px solid #e2e8f0; border-radius: 8px;" frameborder="0"></iframe>
119
+ """
120
+
121
+ # 5. Borderline Review Queue Table
122
+ borderline_data = []
123
+ for b in report.borderline_claims:
124
+ borderline_data.append([
125
+ b.claim_id,
126
+ b.category.value,
127
+ b.assertion_status.value,
128
+ f"{b.confidence:.2f}",
129
+ b.evidence_quote[:100],
130
+ ])
131
+
132
+ # 6. Cryptographic Ledger Proofs
133
+ prov = report.provenance
134
+ cert_token = prov.digital_signature
135
+ hash_summary = (
136
+ f"**Conformity Certificate Token:** `{cert_token}`\n\n"
137
+ f"| Ledger Artifact | Cryptographic Hash (SHA-256) |\n"
138
+ f"|---|---|\n"
139
+ f"| Source Document Snapshot | `{prov.input_doc_sha256}` |\n"
140
+ f"| Normative RDF Knowledge Graph | `{prov.graph_triples_sha256}` |\n"
141
+ f"| EU AI Act Normative Ruleset | `{prov.ruleset_sha256}` |\n"
142
+ f"| Conformity Assessment Digest | `{prov.certificate_sha256}` |\n"
143
+ )
144
+
145
+ # 7. Annex IV Markdown, JSON-LD & Styled HTML Certificate
146
+ md_report = engine.report_generator.generate_markdown_report(report)
147
+ json_ld_cert = json.dumps(engine.report_generator.generate_json_ld(report), indent=2)
148
+ raw_cert_html = engine.report_generator.generate_html_certificate(report)
149
+ escaped_cert = raw_cert_html.replace('"', '&quot;').replace("'", "&#39;")
150
+ cert_iframe_html = f"""
151
+ <iframe srcdoc="{escaped_cert}" style="width: 100%; height: 680px; border: 1px solid #e2e8f0; border-radius: 8px;" frameborder="0"></iframe>
152
+ """
153
+
154
+ return (
155
+ exec_html,
156
+ violations_data,
157
+ claims_data,
158
+ graph_iframe_html,
159
+ cert_token,
160
+ hash_summary,
161
+ json_ld_cert,
162
+ md_report,
163
+ cert_iframe_html,
164
+ borderline_data,
165
+ )
166
+
167
+
168
+ def record_triage(claim_id: str, new_status: str, new_category: str, notes: str, auditor_id: str):
169
+ if not claim_id:
170
+ return "⚠️ Please select a Claim ID to triage."
171
+
172
+ from src.core.models import ExtractedClaim
173
+ target_claim = ExtractedClaim(
174
+ claim_id=claim_id,
175
+ entity_text="Audited Claim",
176
+ category=EntityCategory(new_category),
177
+ assertion_status=AssertionStatus(new_status),
178
+ confidence=0.99,
179
+ normative_article="EU AI Act Article 14",
180
+ evidence_quote=notes or "Auditor confirmed operational control.",
181
+ )
182
+
183
+ record = engine.triage_queue.record_auditor_decision(
184
+ claim=target_claim,
185
+ auditor_id=auditor_id or "lead_auditor",
186
+ verified_status=AssertionStatus(new_status),
187
+ verified_category=EntityCategory(new_category),
188
+ notes=notes,
189
+ )
190
+
191
+ return f"✅ Triplet sample created and recorded into active learning repository! Anchor: '{record['anchor_text'][:50]}...' -> Label: {record['positive_label']}"
192
+
193
+
194
+ # Custom Theme and CSS
195
+ CUSTOM_CSS = """
196
+ .gradio-container {
197
+ max-width: 1380px !important;
198
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
199
+ }
200
+ .header-badge {
201
+ background: #f1f5f9;
202
+ border: 1px solid #cbd5e1;
203
+ color: #334155;
204
+ padding: 4px 10px;
205
+ border-radius: 6px;
206
+ font-size: 12px;
207
+ font-weight: 500;
208
+ }
209
+ """
210
+
211
+ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine", css=CUSTOM_CSS, theme=gr.themes.Soft()) as demo:
212
+ gr.Markdown(
213
+ """
214
+ # 🏛️ ReguAI: Deterministic Neuro-Symbolic AI GRC & Conformity Engine
215
+ ### Automated EU AI Act (Regulation (EU) 2024/1689), NIST AI RMF, & ISO/IEC 42001 Auditing
216
+ Grounds enterprise model cards and technical documentation into an authoritative normative knowledge graph,
217
+ applying **mathematically deterministic W3C SHACL shape constraints** backed by a **W3C PROV-O cryptographic audit ledger**.
218
+
219
+ <div style="display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap;">
220
+ <span class="header-badge">🇪🇺 EU AI Act High-Risk (Arts. 9-15)</span>
221
+ <span class="header-badge">📐 W3C SHACL Deterministic Proofs</span>
222
+ <span class="header-badge">🌐 Interactive Knowledge Graph</span>
223
+ <span class="header-badge">🔗 W3C PROV-O Audit Ledger</span>
224
+ <span class="header-badge">🛡️ Zero-Hallucination Guarantee</span>
225
+ <span class="header-badge">👤 Auditor-in-the-Loop Active Learning</span>
226
+ </div>
227
+ """
228
+ )
229
+
230
+ with gr.Row():
231
+ with gr.Column(scale=5):
232
+ sample_dropdown = gr.Dropdown(
233
+ label="📁 Select Pre-loaded High-Risk AI Benchmark Case Study",
234
+ choices=list(SAMPLE_PATHS.keys()),
235
+ value=list(SAMPLE_PATHS.keys())[0],
236
+ )
237
+ spec_input = gr.Textbox(
238
+ label="📄 System Technical Specification / Model Card (Markdown or JSON)",
239
+ lines=14,
240
+ placeholder="Paste AI system architecture or model card text...",
241
+ value=load_sample_content(list(SAMPLE_PATHS.keys())[0]),
242
+ )
243
+ auditor_input = gr.Textbox(
244
+ label="Auditor Credential Identifier",
245
+ value="lead_compliance_auditor_01",
246
+ placeholder="e.g. auditor@enterprise.org",
247
+ )
248
+ assess_btn = gr.Button("⚡ Run Deterministic Conformity Assessment", variant="primary", size="lg")
249
+
250
+ with gr.Column(scale=7):
251
+ exec_output = gr.HTML(label="Executive Conformity Summary")
252
+
253
+ with gr.Tabs():
254
+ with gr.TabItem("🌐 Interactive Regulatory Graph"):
255
+ graph_output = gr.HTML(label="Force-Directed Regulatory Dependency Network")
256
+
257
+ with gr.TabItem("⚖️ SHACL Deterministic Violations"):
258
+ violations_table = gr.Dataframe(
259
+ headers=["Legal Article", "Normative Requirement", "Severity", "SHACL Path", "Remediation Guidance"],
260
+ datatype=["str", "str", "str", "str", "str"],
261
+ label="Mathematical Proof: Non-Conformities Found",
262
+ )
263
+
264
+ with gr.TabItem("🔍 Extracted Regulatory Claims"):
265
+ claims_table = gr.Dataframe(
266
+ headers=["Claim ID", "Category", "Status", "Confidence", "Target Article", "Evidence Span"],
267
+ datatype=["str", "str", "str", "str", "str", "str"],
268
+ label="Domain-Adapted Claim Extraction & NegEx Grounding",
269
+ )
270
+
271
+ with gr.TabItem("👤 Auditor Triage & Active Learning"):
272
+ gr.Markdown("### Borderline Claims Requiring Human Auditor Review")
273
+ borderline_table = gr.Dataframe(
274
+ headers=["Claim ID", "Category", "Status", "Confidence", "Evidence Quote"],
275
+ datatype=["str", "str", "str", "str", "str"],
276
+ )
277
+ with gr.Row():
278
+ triage_claim_id = gr.Textbox(label="Claim ID to Triage", placeholder="e.g. clm_001")
279
+ triage_status = gr.Dropdown(label="Verified Assertion Status", choices=[s.value for s in AssertionStatus], value="IMPLEMENTED")
280
+ triage_cat = gr.Dropdown(label="Verified Normative Category", choices=[c.value for c in EntityCategory], value="HUMAN_OVERSIGHT")
281
+ triage_notes = gr.Textbox(label="Auditor Decision Rationale", placeholder="Explain reason for modification...")
282
+ triage_btn = gr.Button("Submit Auditor Triplet Feedback")
283
+ triage_result = gr.Markdown()
284
+
285
+ with gr.TabItem("🔐 Cryptographic Audit Ledger"):
286
+ token_display = gr.Textbox(label="Official Digital Conformity Token", interactive=False)
287
+ ledger_display = gr.Markdown()
288
+
289
+ with gr.TabItem("📑 Export Technical Documentation (Annex IV)"):
290
+ with gr.Tabs():
291
+ with gr.TabItem("📜 Official Print-Ready Certificate (HTML)"):
292
+ cert_html_output = gr.HTML()
293
+ with gr.TabItem("Annex IV Official Report (Markdown)"):
294
+ report_markdown = gr.Markdown()
295
+ with gr.TabItem("Machine-Readable JSON-LD"):
296
+ jsonld_display = gr.Code(language="json", label="W3C JSON-LD Digital Certificate")
297
+
298
+ # Wire event handlers
299
+ sample_dropdown.change(
300
+ fn=load_sample_content,
301
+ inputs=[sample_dropdown],
302
+ outputs=[spec_input],
303
+ )
304
+
305
+ assess_btn.click(
306
+ fn=run_assessment,
307
+ inputs=[spec_input, auditor_input],
308
+ outputs=[
309
+ exec_output,
310
+ violations_table,
311
+ claims_table,
312
+ graph_output,
313
+ token_display,
314
+ ledger_display,
315
+ jsonld_display,
316
+ report_markdown,
317
+ cert_html_output,
318
+ borderline_table,
319
+ ],
320
+ )
321
+
322
+ triage_btn.click(
323
+ fn=record_triage,
324
+ inputs=[triage_claim_id, triage_status, triage_cat, triage_notes, auditor_input],
325
+ outputs=[triage_result],
326
+ )
327
+
328
+ if __name__ == "__main__":
329
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
data/active_learning_triplets.jsonl ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ {"timestamp": "2026-09-20T18:40:55.762828+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."}
2
+ {"timestamp": "2026-09-20T18:41:12.550631+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."}
data/benchmarks/eu_ai_act_normative_triples.jsonld ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "@context": {
3
+ "regu": "http://regu.ai/schema#",
4
+ "eu": "http://data.europa.eu/eli/reg/2024/1689#",
5
+ "nist": "http://csrc.nist.gov/ns/rmf#",
6
+ "iso": "http://iso.org/standard/42001#",
7
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
8
+ "skos": "http://www.w3.org/2004/02/skos/core#"
9
+ },
10
+ "@graph": [
11
+ {
12
+ "@id": "eu:Article_9",
13
+ "@type": "regu:RegulatoryRequirement",
14
+ "rdfs:label": "Risk Management System",
15
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 9",
16
+ "regu:targetClass": "regu:RiskManagementSystem",
17
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
18
+ "skos:closeMatch": "nist:GOVERN_1.1",
19
+ "skos:relatedMatch": "iso:Clause_6_1",
20
+ "regu:description": "Establish, implement, document and maintain a continuous risk management system throughout the entire lifecycle of a high-risk AI system."
21
+ },
22
+ {
23
+ "@id": "eu:Article_10_Data_Governance",
24
+ "@type": "regu:RegulatoryRequirement",
25
+ "rdfs:label": "Data and Data Governance",
26
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 10",
27
+ "regu:targetClass": "regu:DataGovernanceProcess",
28
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
29
+ "skos:closeMatch": "nist:MAP_1.5",
30
+ "skos:relatedMatch": "iso:Control_A_8_2",
31
+ "regu:description": "Training, validation and testing datasets shall be subject to appropriate data governance and management practices."
32
+ },
33
+ {
34
+ "@id": "eu:Article_10_2_f_Bias_Mitigation",
35
+ "@type": "regu:RegulatoryRequirement",
36
+ "rdfs:label": "Bias Examination and Mitigation",
37
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 10(2)(f)",
38
+ "regu:targetClass": "regu:BiasMitigationControl",
39
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
40
+ "skos:closeMatch": "nist:MEASURE_2.11",
41
+ "skos:relatedMatch": "iso:Control_A_8_4",
42
+ "regu:description": "Examination in view of possible biases that are likely to affect the health and safety of persons, negatively impact fundamental rights or lead to discrimination."
43
+ },
44
+ {
45
+ "@id": "eu:Article_11_Technical_Documentation",
46
+ "@type": "regu:RegulatoryRequirement",
47
+ "rdfs:label": "Technical Documentation",
48
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 11 & Annex IV",
49
+ "regu:targetClass": "regu:TechnicalDocumentation",
50
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
51
+ "skos:closeMatch": "nist:GOVERN_1.4",
52
+ "skos:relatedMatch": "iso:Control_A_6_2",
53
+ "regu:description": "Drawn up before the system is placed on the market or put into service and kept up-to-date."
54
+ },
55
+ {
56
+ "@id": "eu:Article_12_Record_Keeping",
57
+ "@type": "regu:RegulatoryRequirement",
58
+ "rdfs:label": "Record-Keeping & Logging",
59
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 12",
60
+ "regu:targetClass": "regu:AutomatedLogging",
61
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
62
+ "skos:closeMatch": "nist:GOVERN_1.5",
63
+ "skos:relatedMatch": "iso:Control_A_9_3",
64
+ "regu:description": "High-risk AI systems shall technically allow for the automatic recording of events (logging) over their lifecycle."
65
+ },
66
+ {
67
+ "@id": "eu:Article_13_Transparency",
68
+ "@type": "regu:RegulatoryRequirement",
69
+ "rdfs:label": "Transparency and Provision of Information",
70
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 13",
71
+ "regu:targetClass": "regu:TransparencySpecification",
72
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
73
+ "skos:closeMatch": "nist:MAP_1.2",
74
+ "skos:relatedMatch": "iso:Control_A_7_2",
75
+ "regu:description": "High-risk AI systems shall be designed and developed in such a way as to ensure that their operation is sufficiently transparent to enable deployers to interpret the system's output."
76
+ },
77
+ {
78
+ "@id": "eu:Article_14_Human_Oversight",
79
+ "@type": "regu:RegulatoryRequirement",
80
+ "rdfs:label": "Human Oversight",
81
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 14",
82
+ "regu:targetClass": "regu:HumanOversightMechanism",
83
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
84
+ "skos:closeMatch": "nist:MANAGE_2.2",
85
+ "skos:relatedMatch": "iso:Control_A_8_5",
86
+ "regu:description": "High-risk AI systems shall be designed and developed in such a way, including with appropriate human-machine interface tools, that they can be effectively overseen by natural persons."
87
+ },
88
+ {
89
+ "@id": "eu:Article_15_Cybersecurity_Robustness",
90
+ "@type": "regu:RegulatoryRequirement",
91
+ "rdfs:label": "Accuracy, Robustness and Cybersecurity",
92
+ "eu:legalBasis": "Regulation (EU) 2024/1689 Chapter III Article 15",
93
+ "regu:targetClass": "regu:CybersecurityControl",
94
+ "regu:mandatoryFor": "regu:HighRiskAISystem",
95
+ "skos:closeMatch": "nist:MEASURE_2.6",
96
+ "skos:relatedMatch": "iso:Control_A_9_2",
97
+ "regu:description": "Resilient against attempts by unauthorised third parties to alter their use, outputs or performance by exploiting system vulnerabilities."
98
+ }
99
+ ]
100
+ }
data/synthetic_systems/borderline_credit_scoring.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "system_id": "fin-creditrisk-04",
4
+ "name": "CrediScore Neural Underwriter",
5
+ "version": "1.0.0-rc2",
6
+ "domain": "Financial Services & Credit Scoring",
7
+ "intended_purpose": "Automated creditworthiness assessment and loan interest rate pricing.",
8
+ "eu_risk_classification": "High-Risk (Annex III, Point 5 - Essential Services)",
9
+ "developer_name": "NovaBank FinTech",
10
+ "deployment_context": "Staging / Pre-Production Pilot"
11
+ },
12
+ "raw_document_text": "# CrediScore Neural Underwriter Specification\n\n## Intended Purpose\nAutomated credit scoring and loan default prediction for retail mortgage applications.\n\n## Risk Management (Article 9)\nA continuous risk management system is active and integrated with internal banking compliance frameworks.\n\n## Data Governance (Article 10)\nTraining data provenance is documented across 500,000 anonymized historical loan files.\n\n## Bias Examination (Article 10(2)(f))\nA preliminary fairness audit was performed on credit scores, though comprehensive disparate impact testing across immigrant zip codes is planned for Q4.\n\n## Human Oversight (Article 14)\nA manual override capability is currently in development and planned for future release in version 1.1. Underwriting decisions in beta pilot operate without human oversight fallback.\n\n## Record-Keeping (Article 12)\nInference logs and transaction traces are recorded to cloud storage.\n\n## Cybersecurity (Article 15)\nAdversarial testing against feature manipulation is under evaluation."
13
+ }
data/synthetic_systems/compliant_clinical_samd.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "system_id": "samd-oncology-01",
4
+ "name": "OncoScan AI Diagnostic Assistant",
5
+ "version": "2.4.0",
6
+ "domain": "Healthcare & Medical Diagnostics",
7
+ "intended_purpose": "AI Software as a Medical Device (SaMD) for automated lesion segmentation and malignancy risk stratification in thoracic CT scans.",
8
+ "eu_risk_classification": "High-Risk (Annex III, Medical Device)",
9
+ "developer_name": "Aether Health Therapeutics",
10
+ "deployment_context": "Clinical Hospital Radiology Network"
11
+ },
12
+ "raw_document_text": "# OncoScan AI Diagnostic Assistant Model Specification\n\n## Intended Use and Scope\nOncoScan AI is a high-risk diagnostic medical assistant deployed across EU hospital networks. The system assists radiologists with early detection of pulmonary nodules.\n\n## Risk Management (Article 9)\nA continuous risk management system is implemented and maintained in accordance with ISO 14971 and EU AI Act Article 9. Hazard analysis and residual risk evaluations are monitored continuously in production.\n\n## Data Governance & Training Lineage (Article 10)\nTraining data provenance is documented across multi-center clinical cohorts comprising 45,000 diverse thoracic scans. Rigorous data curation and cleaning pipelines ensure representative sampling.\n\n## Bias Examination & Mitigation (Article 10(2)(f))\nBias examination and mitigation controls are fully implemented. Equalized odds and demographic parity across patient sex, age brackets, and pediatric vs geriatric cohorts were verified with zero statistically significant disparity.\n\n## Technical Documentation (Article 11)\nComprehensive technical documentation conforming to Annex IV is maintained and archived.\n\n## Record-Keeping & Automated Logging (Article 12)\nAutomated logging of every inference request, model confidence score, and operator override is enabled with immutable cryptographic hashes.\n\n## Transparency (Article 13)\nDetailed instructions for use, clinical limitation disclosures, and interpretability heatmaps are provided to deployers.\n\n## Human Oversight (Article 14)\nA clinician-in-the-loop human oversight mechanism is strictly operational. Diagnostic predictions require mandatory confirmation by a board-certified radiologist before EHR entry. A manual override and emergency stop kill switch are implemented.\n\n## Accuracy, Robustness and Cybersecurity (Article 15)\nThe model exhibits 94.8% sensitivity and 96.2% specificity. Cybersecurity controls and adversarial robustness defenses against image perturbation and data poisoning attacks are verified and active."
13
+ }
data/synthetic_systems/non_compliant_hr_recruitment.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "system_id": "hr-talentsift-09",
4
+ "name": "TalentSift Automated Candidate Evaluator",
5
+ "version": "1.1.0",
6
+ "domain": "Employment & HR Recruitment",
7
+ "intended_purpose": "Automated CV scoring, video interview sentiment parsing, and algorithmic candidate filtering.",
8
+ "eu_risk_classification": "High-Risk (Annex III, Point 4 - Employment & Recruitment)",
9
+ "developer_name": "HireFast Technologies",
10
+ "deployment_context": "Commercial Cloud SaaS"
11
+ },
12
+ "raw_document_text": "# TalentSift Candidate Evaluator Specification\n\n## Intended Use\nTalentSift autonomously scores thousands of inbound job applications, auto-rejecting the bottom 70% percentile prior to hiring manager interviews.\n\n## Risk Management (Article 9)\nA risk management procedure was drafted during initial prototype design.\n\n## Data Governance (Article 10)\nTraining data provenance comprises 120,000 historical corporate hiring resumes scraped from internal company records.\n\n## Bias Examination & Demographic Parity (Article 10(2)(f))\nThe development team did not conduct bias examination or demographic parity audits across protected attributes due to data privacy constraints. Bias mitigation controls are currently absent.\n\n## Automated Logging (Article 12)\nInference logging is implemented for error debugging in cloud datacenters.\n\n## Transparency (Article 13)\nBasic instructions for use are provided in the software administrator portal.\n\n## Human Oversight (Article 14)\nCandidate rejections are executed autonomously with no human oversight mechanism. The platform operates without human-in-the-loop validation or manual override prior to sending candidate rejection notices.\n\n## Cybersecurity & Robustness (Article 15)\nStandard SSL encryption is configured, but adversarial robustness against resume prompt injection was untested."
13
+ }
pyproject.toml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "reguai"
7
+ version = "0.1.0"
8
+ description = "Deterministic Neuro-Symbolic AI GRC & Automated Conformity Assessment Engine"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "Apache-2.0" }
12
+ authors = [
13
+ { name = "Mujtaba Hussain", email = "mujtaba@example.com" }
14
+ ]
15
+ keywords = ["ai-governance", "eu-ai-act", "neuro-symbolic", "shacl", "w3c-prov", "compliance", "grc"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Legal Industry",
20
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
21
+ "License :: OSI Approved :: Apache Software License",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ ]
27
+ dependencies = [
28
+ "rdflib>=7.0.0",
29
+ "pyshacl>=0.25.0",
30
+ "pydantic>=2.5.0",
31
+ "fastapi>=0.109.0",
32
+ "uvicorn>=0.27.0",
33
+ "jinja2>=3.1.2",
34
+ "networkx>=3.2.0",
35
+ "pyyaml>=6.0.1",
36
+ "gradio>=4.20.0",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ nlp = [
41
+ "gliner>=0.2.0",
42
+ "torch>=2.1.0",
43
+ "transformers>=4.38.0",
44
+ ]
45
+ dev = [
46
+ "pytest>=8.0.0",
47
+ "pytest-asyncio>=0.23.0",
48
+ ]
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ rdflib>=7.0.0
2
+ pyshacl>=0.25.0
3
+ pydantic>=2.5.0
4
+ fastapi>=0.109.0
5
+ uvicorn>=0.27.0
6
+ jinja2>=3.1.2
7
+ networkx>=3.2.0
8
+ pyyaml>=6.0.1
9
+ gradio>=4.20.0
10
+ pytest>=8.0.0
11
+ pytest-asyncio>=0.23.0
src/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ """ReguAI Root Package."""
2
+ __version__ = "0.1.0"
src/core/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Core Schemas and Configurations."""
src/core/config.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ReguAI Core Configuration and Namespaces.
3
+ Defines semantic URIs, ontology bindings, thresholds, and paths.
4
+ """
5
+
6
+ from pathlib import Path
7
+ from rdflib import Namespace
8
+
9
+ # Base Paths
10
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
11
+ SRC_DIR = PROJECT_ROOT / "src"
12
+ ONTOLOGY_DIR = SRC_DIR / "ontology"
13
+ SCHEMAS_DIR = ONTOLOGY_DIR / "schemas"
14
+ SHACL_DIR = ONTOLOGY_DIR / "shacl"
15
+ DATA_DIR = PROJECT_ROOT / "data"
16
+ BENCHMARKS_DIR = DATA_DIR / "benchmarks"
17
+ SYNTHETIC_DIR = DATA_DIR / "synthetic_systems"
18
+
19
+ # Semantic Namespaces
20
+ REGU = Namespace("http://regu.ai/schema#")
21
+ EU_ACT = Namespace("http://data.europa.eu/eli/reg/2024/1689#")
22
+ NIST = Namespace("http://csrc.nist.gov/ns/rmf#")
23
+ ISO = Namespace("http://iso.org/standard/42001#")
24
+ PROV = Namespace("http://www.w3.org/ns/prov#")
25
+ SH = Namespace("http://www.w3.org/ns/shacl#")
26
+
27
+ # Confidence & Triage Thresholds
28
+ HIGH_CONFIDENCE_THRESHOLD = 0.85
29
+ BORDERLINE_CONFIDENCE_THRESHOLD = 0.55
30
+
31
+ # Supported Regulatory Frameworks
32
+ FRAMEWORK_EU_AI_ACT = "EU_AI_ACT_2024_1689"
33
+ FRAMEWORK_NIST_AI_RMF = "NIST_AI_RMF_1_0"
34
+ FRAMEWORK_ISO_42001 = "ISO_IEC_42001_2023"
35
+
36
+ ALL_FRAMEWORKS = [
37
+ FRAMEWORK_EU_AI_ACT,
38
+ FRAMEWORK_NIST_AI_RMF,
39
+ FRAMEWORK_ISO_42001,
40
+ ]
src/core/models.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pydantic schemas for ReguAI system models, claims, verification results, and audit ledger.
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from enum import Enum
7
+ from typing import List, Optional, Dict, Any
8
+ from pydantic import BaseModel, Field
9
+
10
+
11
+ class AssertionStatus(str, Enum):
12
+ IMPLEMENTED = "IMPLEMENTED"
13
+ PLANNED = "PLANNED"
14
+ ABSENT = "ABSENT"
15
+ UNKNOWN = "UNKNOWN"
16
+
17
+
18
+ class RegulatoryFramework(str, Enum):
19
+ EU_AI_ACT = "EU_AI_ACT"
20
+ NIST_AI_RMF = "NIST_AI_RMF"
21
+ ISO_42001 = "ISO_42001"
22
+
23
+
24
+ class EntityCategory(str, Enum):
25
+ RISK_MANAGEMENT = "RISK_MANAGEMENT" # Art 9 / NIST GOVERN
26
+ DATA_GOVERNANCE = "DATA_GOVERNANCE" # Art 10 / NIST MAP
27
+ BIAS_MITIGATION = "BIAS_MITIGATION" # Art 10(2)(f) / NIST MEASURE
28
+ TECHNICAL_DOCUMENTATION = "TECHNICAL_DOCUMENTATION" # Art 11 & Annex IV
29
+ RECORD_KEEPING = "RECORD_KEEPING" # Art 12 / Logging
30
+ TRANSPARENCY = "TRANSPARENCY" # Art 13
31
+ HUMAN_OVERSIGHT = "HUMAN_OVERSIGHT" # Art 14 / Human-in-the-loop
32
+ ACCURACY_ROBUSTNESS = "ACCURACY_ROBUSTNESS" # Art 15(1)
33
+ CYBERSECURITY = "CYBERSECURITY" # Art 15(4)
34
+ FAIL_SAFE = "FAIL_SAFE" # Art 14(4)(e) / Art 15
35
+
36
+
37
+ class ExtractedClaim(BaseModel):
38
+ claim_id: str
39
+ entity_text: str
40
+ category: EntityCategory
41
+ assertion_status: AssertionStatus
42
+ confidence: float = Field(ge=0.0, le=1.0)
43
+ source_span: Optional[tuple[int, int]] = None
44
+ normative_article: str
45
+ evidence_quote: str
46
+ requires_auditor_review: bool = False
47
+ auditor_verified: Optional[bool] = None
48
+ auditor_notes: Optional[str] = None
49
+
50
+
51
+ class SystemMetadata(BaseModel):
52
+ system_id: str
53
+ name: str
54
+ version: str = "1.0.0"
55
+ domain: str
56
+ intended_purpose: str
57
+ eu_risk_classification: str = "High-Risk (Annex III)"
58
+ developer_name: str = "Enterprise AI Labs"
59
+ deployment_context: str = "Production"
60
+
61
+
62
+ class SystemSpecification(BaseModel):
63
+ metadata: SystemMetadata
64
+ raw_document_text: str
65
+ extracted_claims: List[ExtractedClaim] = Field(default_factory=list)
66
+ custom_attributes: Dict[str, Any] = Field(default_factory=dict)
67
+
68
+
69
+ class ValidationViolation(BaseModel):
70
+ focus_node: str
71
+ result_path: str
72
+ source_constraint_component: str
73
+ message: str
74
+ severity: str = "Violation" # Violation, Warning, Info
75
+ regulatory_article: str
76
+ normative_reference: str
77
+ remediation_guidance: str
78
+
79
+
80
+ class AuditProvenance(BaseModel):
81
+ input_doc_sha256: str
82
+ graph_triples_sha256: str
83
+ ruleset_sha256: str
84
+ certificate_sha256: str
85
+ prov_o_rdf: str
86
+ timestamp_utc: str
87
+ digital_signature: str
88
+
89
+
90
+ class ConformityReport(BaseModel):
91
+ report_id: str
92
+ system_metadata: SystemMetadata
93
+ overall_conforms: bool
94
+ conformity_score: float = Field(ge=0.0, le=100.0)
95
+ total_requirements_evaluated: int
96
+ passed_requirements_count: int
97
+ violations: List[ValidationViolation] = Field(default_factory=list)
98
+ warnings: List[ValidationViolation] = Field(default_factory=list)
99
+ claims_analyzed: List[ExtractedClaim] = Field(default_factory=list)
100
+ borderline_claims: List[ExtractedClaim] = Field(default_factory=list)
101
+ provenance: AuditProvenance
102
+ generated_at_utc: str
103
+ executive_summary: str
src/engine.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ReguAI Unified Neuro-Symbolic Engine.
3
+ Orchestrates ingestion, extraction, graph building, deterministic SHACL reasoning,
4
+ provenance generation, and reporting.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Union, Dict, Any
9
+ from datetime import datetime, timezone
10
+
11
+ from src.core.models import (
12
+ SystemSpecification,
13
+ ConformityReport,
14
+ )
15
+ from src.extraction.parser import SpecificationParser
16
+ from src.extraction.gliner_extractor import RegulatoryClaimExtractor
17
+ from src.ontology.builder import NormativeGraphBuilder
18
+ 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:
25
+ def __init__(self):
26
+ self.parser = SpecificationParser()
27
+ self.extractor = RegulatoryClaimExtractor()
28
+ self.graph_builder = NormativeGraphBuilder()
29
+ self.shacl_engine = DeterministicSHACLEngine()
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:
41
+ 1. Parse document or JSON
42
+ 2. Extract regulatory claims & evaluate assertions (GLiNER + NegEx)
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):
50
+ spec = self.parser.parse_file(input_data)
51
+ elif isinstance(input_data, dict):
52
+ import json
53
+ spec = self.parser.parse_json(json.dumps(input_data))
54
+ else:
55
+ text = str(input_data).strip()
56
+ if text.startswith("{") and text.endswith("}"):
57
+ spec = self.parser.parse_json(text)
58
+ else:
59
+ spec = self.parser.parse_markdown(text)
60
+
61
+ # 2. Extract Claims & ground
62
+ spec = self.extractor.enrich_system_specification(spec)
63
+ borderline_claims = self.triage_queue.filter_borderline_claims(spec.extracted_claims)
64
+
65
+ # 3. Construct Knowledge Graph
66
+ system_graph = self.graph_builder.build_system_graph(spec)
67
+
68
+ # 4. Deterministic SHACL Reasoning
69
+ conforms, violations, warnings, score = self.shacl_engine.validate_system(system_graph)
70
+
71
+ # 5. Cryptographic Provenance Ledger
72
+ provenance = self.ledger.generate_provenance(
73
+ spec=spec,
74
+ system_graph=system_graph,
75
+ conforms=conforms,
76
+ violations_count=len(violations),
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()
84
+
85
+ if conforms:
86
+ summary = (
87
+ f"The AI system '{spec.metadata.name}' (Version {spec.metadata.version}) satisfies all mandatory "
88
+ f"EU AI Act Chapter III high-risk requirements based on formal W3C SHACL constraint validation. "
89
+ f"Operational controls for Articles 9 (Risk Management), 10 (Data Governance & Bias Mitigation), "
90
+ f"12 (Logging), 14 (Human Oversight), and 15 (Cybersecurity & Robustness) are verified."
91
+ )
92
+ else:
93
+ violation_articles = ", ".join(sorted(set(v.regulatory_article for v in violations)))
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(
101
+ report_id=f"rep_{spec.metadata.system_id}_{provenance.certificate_sha256[:8]}",
102
+ system_metadata=spec.metadata,
103
+ overall_conforms=conforms,
104
+ conformity_score=score,
105
+ total_requirements_evaluated=total_reqs,
106
+ passed_requirements_count=passed_reqs,
107
+ violations=violations,
108
+ warnings=warnings,
109
+ claims_analyzed=spec.extracted_claims,
110
+ borderline_claims=borderline_claims,
111
+ provenance=provenance,
112
+ generated_at_utc=now_utc,
113
+ executive_summary=summary,
114
+ )
115
+
116
+ return report
src/extraction/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Regulatory Claim Extraction & Grounding."""
src/extraction/assertion_triage.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Assertion and Negation Triage for Regulatory Claims (NegEx-based heuristic engine).
3
+ Distinguishes between Implemented, Planned, Absent, and Ambiguous controls.
4
+ """
5
+
6
+ import re
7
+ from typing import Tuple
8
+ from src.core.models import AssertionStatus
9
+
10
+
11
+ class AssertionTriage:
12
+ def __init__(self):
13
+ # Absent / Negated Patterns (Pre- and Post-modifiers)
14
+ self.absent_patterns = [
15
+ r"\b(no|not|neither|nor|never|without)\b",
16
+ r"\b(absent|absence|missing)\b",
17
+ r"\b(lacks?|lacking|failed\s+to|omits?|omitted)\b",
18
+ r"\b(not\s+yet|not\s+currently|not\s+implemented|not\s+conducted)\b",
19
+ r"\b(no\s+fallback|no\s+oversight|no\s+mechanism|no\s+testing)\b",
20
+ r"\b(untested|unmitigated|unmonitored)\b",
21
+ r"\b(absence\s+of|exempt\s+from)\b",
22
+ ]
23
+
24
+ # Planned / Roadmap Patterns
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
+
33
+ # Implemented / Verified Patterns
34
+ self.implemented_patterns = [
35
+ r"\b(implemented|operational|deployed|enforced|verified)\b",
36
+ r"\b(active|validated|integrated|established|maintained)\b",
37
+ r"\b(tested\s+(?:and|with|via)|passed|certified|logged)\b",
38
+ r"\b(in\s+production|monitored\s+24/7|real-time)\b",
39
+ r"\b(equipped\s+with|provides\s+a\s+(?:manual|human|stop))\b",
40
+ ]
41
+
42
+ def analyze_assertion(self, text: str) -> Tuple[AssertionStatus, float, bool]:
43
+ """
44
+ Analyzes the context sentence surrounding an extracted entity.
45
+ Returns:
46
+ - status (AssertionStatus): IMPLEMENTED, PLANNED, or ABSENT
47
+ - confidence (float): 0.0 to 1.0
48
+ - requires_auditor_review (bool): True if ambiguous or borderline
49
+ """
50
+ clean_text = text.lower().strip()
51
+
52
+ absent_hits = sum(1 for p in self.absent_patterns if re.search(p, clean_text))
53
+ planned_hits = sum(1 for p in self.planned_patterns if re.search(p, clean_text))
54
+ implemented_hits = sum(1 for p in self.implemented_patterns if re.search(p, clean_text))
55
+
56
+ # Explicit negation takes precedence over generic auxiliary verbs (e.g. "deployed without oversight")
57
+ if absent_hits > 0:
58
+ if planned_hits > 0:
59
+ # Contradiction between absent and planned (e.g., "currently absent but planned")
60
+ return AssertionStatus.PLANNED, 0.65, True
61
+ conf = min(0.96, 0.78 + (0.08 * absent_hits))
62
+ return AssertionStatus.ABSENT, conf, False
63
+
64
+ if planned_hits > 0:
65
+ conf = min(0.92, 0.75 + (0.08 * planned_hits))
66
+ return AssertionStatus.PLANNED, conf, False
67
+
68
+ if implemented_hits > 0:
69
+ confidence = min(0.96, 0.80 + (0.08 * implemented_hits))
70
+ return AssertionStatus.IMPLEMENTED, confidence, False
71
+
72
+ # If no explicit cue found, default to IMPLEMENTED if affirmative sentence,
73
+ # but mark as borderline for human confirmation
74
+ return AssertionStatus.IMPLEMENTED, 0.58, True
src/extraction/gliner_extractor.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Regulatory Claim and Entity Extractor.
3
+ Domain-adapted semantic extractor for AI compliance claims, integrating GLiNER
4
+ with rule-based syntactic patterns and NegEx assertion triage.
5
+ """
6
+
7
+ import re
8
+ from typing import List, Optional, Dict, Any, Tuple
9
+ from src.core.config import HIGH_CONFIDENCE_THRESHOLD, BORDERLINE_CONFIDENCE_THRESHOLD
10
+ from src.core.models import (
11
+ ExtractedClaim,
12
+ EntityCategory,
13
+ AssertionStatus,
14
+ SystemSpecification,
15
+ )
16
+ from src.extraction.assertion_triage import AssertionTriage
17
+ from src.extraction.parser import SpecificationParser
18
+
19
+
20
+ class RegulatoryClaimExtractor:
21
+ def __init__(self):
22
+ self.triage = AssertionTriage()
23
+ self.parser = SpecificationParser()
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": [
30
+ r"\b(human-in-the-loop|human\s+oversight|manual\s+override|clinician\s+review)\b",
31
+ r"\b(operator\s+intervention|override\s+capability|human\s+supervisor)\b",
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": [
45
+ r"\b(data\s+governance|training\s+data\s+provenance|dataset\s+lineage)\b",
46
+ r"\b(data\s+curation|validation\s+cohort|data\s+cleaning\s+pipeline)\b",
47
+ r"\b(representative\s+sampling|demographic\s+distribution)\b",
48
+ ],
49
+ },
50
+ EntityCategory.BIAS_MITIGATION: {
51
+ "article": "Article 10(2)(f)",
52
+ "keywords": [
53
+ r"\b(bias\s+(?:mitigation|examination|audit|evaluation|testing))\b",
54
+ r"\b(demographic\s+parity|equalized\s+odds|disparate\s+impact)\b",
55
+ r"\b(fairness\s+metric|protected\s+attributes?|gender\s+bias|racial\s+bias)\b",
56
+ r"\b(adversarial\s+debiasing|re-weighting)\b",
57
+ ],
58
+ },
59
+ EntityCategory.RISK_MANAGEMENT: {
60
+ "article": "Article 9",
61
+ "keywords": [
62
+ r"\b(risk\s+management(?:\s+system)?|hazard\s+analysis|risk\s+matrix)\b",
63
+ r"\b(residual\s+risk|risk\s+mitigation\s+measures|post-market\s+monitoring)\b",
64
+ r"\b(failure\s+mode\s+effects\s+analysis|fmea)\b",
65
+ ],
66
+ },
67
+ EntityCategory.RECORD_KEEPING: {
68
+ "article": "Article 12",
69
+ "keywords": [
70
+ r"\b(automated\s+logging|event\s+logging|audit\s+trail|record-keeping)\b",
71
+ r"\b(inference\s+logging|request\s+tracing|immutable\s+log)\b",
72
+ ],
73
+ },
74
+ EntityCategory.TRANSPARENCY: {
75
+ "article": "Article 13",
76
+ "keywords": [
77
+ r"\b(instructions\s+for\s+use|transparency\s+disclosure|model\s+card)\b",
78
+ r"\b(intended\s+purpose|system\s+capabilities|operational\s+limitations)\b",
79
+ ],
80
+ },
81
+ EntityCategory.ACCURACY_ROBUSTNESS: {
82
+ "article": "Article 15(1)",
83
+ "keywords": [
84
+ r"\b(robustness\s+testing|stress\s+test|out-of-distribution|ood)\b",
85
+ r"\b(noise\s+tolerance|generalization\s+metric|boundary\s+testing)\b",
86
+ ],
87
+ },
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
+ },
96
+ EntityCategory.TECHNICAL_DOCUMENTATION: {
97
+ "article": "Article 11 & Annex IV",
98
+ "keywords": [
99
+ r"\b(technical\s+documentation|annex\s+iv|architecture\s+specification)\b",
100
+ r"\b(conformity\s+assessment\s+file|design\s+specification)\b",
101
+ ],
102
+ },
103
+ }
104
+
105
+ def extract_claims(self, text: str) -> List[ExtractedClaim]:
106
+ """
107
+ Extracts regulatory claims and assertion statuses from document text.
108
+ """
109
+ sentences = self.parser.segment_sentences(text)
110
+ claims: List[ExtractedClaim] = []
111
+ claim_count = 0
112
+
113
+ for sentence in sentences:
114
+ sentence_claims = self._extract_from_sentence(sentence, claim_count)
115
+ claim_count += len(sentence_claims)
116
+ claims.extend(sentence_claims)
117
+
118
+ return claims
119
+
120
+ def _extract_from_sentence(self, sentence: str, current_count: int) -> List[ExtractedClaim]:
121
+ results: List[ExtractedClaim] = []
122
+
123
+ for category, config in self.category_patterns.items():
124
+ for kw_pattern in config["keywords"]:
125
+ match = re.search(kw_pattern, sentence, re.IGNORECASE)
126
+ if match:
127
+ entity_str = match.group(0)
128
+ status, base_conf, borderline = self.triage.analyze_assertion(sentence)
129
+
130
+ # Boost confidence if exact match in professional phrasing
131
+ final_conf = min(0.98, base_conf + 0.05)
132
+ needs_review = borderline or (final_conf < BORDERLINE_CONFIDENCE_THRESHOLD)
133
+
134
+ claim = ExtractedClaim(
135
+ claim_id=f"clm_{current_count + len(results) + 1:03d}",
136
+ entity_text=entity_str,
137
+ category=category,
138
+ assertion_status=status,
139
+ confidence=round(final_conf, 2),
140
+ source_span=(match.start(), match.end()),
141
+ normative_article=config["article"],
142
+ evidence_quote=sentence[:240],
143
+ requires_auditor_review=needs_review,
144
+ )
145
+ results.append(claim)
146
+ # Break to avoid duplicate categories per single sentence
147
+ break
148
+
149
+ return results
150
+
151
+ def enrich_system_specification(self, spec: SystemSpecification) -> SystemSpecification:
152
+ """Runs claim extraction on specification raw document text and populates extracted_claims."""
153
+ claims = self.extract_claims(spec.raw_document_text)
154
+ spec.extracted_claims = claims
155
+ return spec
src/extraction/parser.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Document and Model Card Ingestion Parser.
3
+ Handles Markdown, YAML, JSON, and plaintext AI system specifications.
4
+ """
5
+
6
+ import json
7
+ import re
8
+ from pathlib import Path
9
+ from typing import Dict, Any, List, Optional
10
+ import yaml
11
+
12
+ from src.core.models import SystemMetadata, SystemSpecification
13
+
14
+
15
+ class SpecificationParser:
16
+ def __init__(self):
17
+ self.section_headers = [
18
+ "model details",
19
+ "intended use",
20
+ "risk management",
21
+ "data governance",
22
+ "training data",
23
+ "evaluation data",
24
+ "bias examination",
25
+ "fairness",
26
+ "human oversight",
27
+ "robustness",
28
+ "cybersecurity",
29
+ "logging",
30
+ "ethical considerations",
31
+ "caveats and recommendations",
32
+ ]
33
+
34
+ def parse_file(self, file_path: Path) -> SystemSpecification:
35
+ """Parses a specification file (.json, .yaml, .md, .txt)."""
36
+ suffix = file_path.suffix.lower()
37
+ content = file_path.read_text(encoding="utf-8")
38
+
39
+ if suffix == ".json":
40
+ return self.parse_json(content)
41
+ elif suffix in [".yaml", ".yml"]:
42
+ return self.parse_yaml(content)
43
+ else:
44
+ return self.parse_markdown(content, default_id=file_path.stem)
45
+
46
+ def parse_json(self, raw_json: str) -> SystemSpecification:
47
+ """Parses JSON-formatted model card or system spec."""
48
+ data = json.loads(raw_json)
49
+
50
+ meta_dict = data.get("metadata", {})
51
+ metadata = SystemMetadata(
52
+ system_id=meta_dict.get("system_id", "sys-unknown"),
53
+ name=meta_dict.get("name", "Unnamed AI System"),
54
+ version=meta_dict.get("version", "1.0.0"),
55
+ domain=meta_dict.get("domain", "General Purpose"),
56
+ intended_purpose=meta_dict.get("intended_purpose", "Not specified"),
57
+ eu_risk_classification=meta_dict.get("eu_risk_classification", "High-Risk (Annex III)"),
58
+ developer_name=meta_dict.get("developer_name", "Enterprise AI Team"),
59
+ deployment_context=meta_dict.get("deployment_context", "Production"),
60
+ )
61
+
62
+ doc_text = data.get("raw_document_text") or json.dumps(data.get("sections", {}), indent=2)
63
+
64
+ return SystemSpecification(
65
+ metadata=metadata,
66
+ raw_document_text=doc_text,
67
+ custom_attributes=data.get("custom_attributes", {}),
68
+ )
69
+
70
+ def parse_yaml(self, raw_yaml: str) -> SystemSpecification:
71
+ """Parses YAML-formatted model specification."""
72
+ data = yaml.safe_load(raw_yaml) or {}
73
+ return self.parse_json(json.dumps(data))
74
+
75
+ def parse_markdown(self, raw_markdown: str, default_id: str = "sys-md-01") -> SystemSpecification:
76
+ """Parses Markdown model card (e.g. Hugging Face model card format)."""
77
+ name_match = re.search(r"^#\s+(.+)$", raw_markdown, re.MULTILINE)
78
+ name = name_match.group(1).strip() if name_match else default_id.replace("-", " ").title()
79
+
80
+ domain = "High-Risk Healthcare / HR / Finance"
81
+ if re.search(r"\b(medical|clinical|diagnostic|radiology|samd)\b", raw_markdown, re.I):
82
+ domain = "Healthcare & Medical Diagnostics"
83
+ elif re.search(r"\b(recruitment|employment|cv|resume|interview)\b", raw_markdown, re.I):
84
+ domain = "Employment & HR Screening"
85
+ elif re.search(r"\b(credit|loan|financial|underwriting)\b", raw_markdown, re.I):
86
+ domain = "Financial Services & Credit Scoring"
87
+
88
+ metadata = SystemMetadata(
89
+ system_id=default_id,
90
+ name=name,
91
+ domain=domain,
92
+ intended_purpose="Automated processing and evaluation in high-impact workflows.",
93
+ eu_risk_classification="High-Risk (Annex III)",
94
+ )
95
+
96
+ return SystemSpecification(
97
+ metadata=metadata,
98
+ raw_document_text=raw_markdown,
99
+ custom_attributes={},
100
+ )
101
+
102
+ def segment_sentences(self, text: str) -> List[str]:
103
+ """Segments raw text into candidate claim sentences."""
104
+ clean = re.sub(r"```[\s\S]*?```", "", text) # remove code blocks
105
+ clean = re.sub(r"^#+.*$", "", clean, flags=re.MULTILINE) # remove headings
106
+ sentences = re.split(r"(?<=[.!?])\s+", clean)
107
+ return [s.strip() for s in sentences if len(s.strip()) > 20]
src/ledger/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Cryptographic Provenance Ledger."""
src/ledger/crypto.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Cryptographic hashing and ledger integrity functions for ReguAI.
3
+ Ensures zero-repudiation and deterministic provenance proofs.
4
+ """
5
+
6
+ import hashlib
7
+ import json
8
+ from typing import Dict, Any
9
+ from rdflib import Graph
10
+
11
+
12
+ def compute_sha256_text(content: str) -> str:
13
+ """Computes standard SHA-256 hex digest for utf-8 text."""
14
+ return hashlib.sha256(content.encode("utf-8")).hexdigest()
15
+
16
+
17
+ def compute_sha256_dict(data: Dict[str, Any]) -> str:
18
+ """Computes deterministic SHA-256 hex digest for JSON-serializable dictionaries."""
19
+ canonical_json = json.dumps(data, sort_keys=True, separators=(",", ":"))
20
+ return hashlib.sha256(canonical_json.encode("utf-8")).hexdigest()
21
+
22
+
23
+ def compute_canonical_graph_sha256(graph: Graph) -> str:
24
+ """
25
+ Computes a deterministic hash of an RDF graph by serializing to canonical
26
+ sorted N-Triples format.
27
+ """
28
+ ntriples = graph.serialize(format="nt")
29
+ # Sort lines to ensure canonical ordering regardless of triple insertion order
30
+ sorted_lines = sorted(line.strip() for line in ntriples.splitlines() if line.strip())
31
+ canonical_body = "\n".join(sorted_lines)
32
+ return hashlib.sha256(canonical_body.encode("utf-8")).hexdigest()
33
+
34
+
35
+ def generate_conformity_token(system_id: str, assessment_hash: str) -> str:
36
+ """Generates an official verifiable conformity certificate token."""
37
+ short_hash = assessment_hash[:12].upper()
38
+ clean_sys = system_id.replace("-", "").upper()[:8]
39
+ return f"REGU-EU2024-1689-{clean_sys}-{short_hash}"
src/ledger/provenance.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ W3C PROV-O Cryptographic Provenance Ledger.
3
+ Generates verifiable W3C PROV-O compliance graphs tracking artifacts,
4
+ activities, entities, and agent associations.
5
+ """
6
+
7
+ from datetime import datetime, timezone
8
+ import rdflib
9
+ from rdflib import Graph, URIRef, Literal, RDF, RDFS, XSD
10
+ from src.core.config import PROV, REGU, EU_ACT
11
+ from src.core.models import AuditProvenance, SystemSpecification, ConformityReport
12
+ from src.ledger.crypto import (
13
+ compute_sha256_text,
14
+ compute_canonical_graph_sha256,
15
+ generate_conformity_token,
16
+ )
17
+
18
+
19
+ class ProvenanceLedger:
20
+ def __init__(self):
21
+ self.prov_ns = PROV
22
+ self.regu_ns = REGU
23
+
24
+ def generate_provenance(
25
+ self,
26
+ spec: SystemSpecification,
27
+ system_graph: Graph,
28
+ conforms: bool,
29
+ violations_count: int,
30
+ auditor_id: str = "reguai_automated_auditor",
31
+ ) -> AuditProvenance:
32
+ """
33
+ Creates an immutable W3C PROV-O provenance trace for an assessment run.
34
+ """
35
+ now_iso = datetime.now(timezone.utc).isoformat()
36
+
37
+ # 1. Compute Cryptographic Hashes
38
+ doc_hash = compute_sha256_text(spec.raw_document_text)
39
+ graph_hash = compute_canonical_graph_sha256(system_graph)
40
+ ruleset_hash = compute_sha256_text("EU_AI_ACT_2024_1689_CHAPTER_III_V1.0")
41
+
42
+ cert_data = f"{spec.metadata.system_id}:{conforms}:{violations_count}:{graph_hash}:{now_iso}"
43
+ cert_hash = compute_sha256_text(cert_data)
44
+ digital_signature = generate_conformity_token(spec.metadata.system_id, cert_hash)
45
+
46
+ # 2. Build PROV-O RDF Graph
47
+ g = Graph()
48
+ g.bind("prov", PROV)
49
+ g.bind("regu", REGU)
50
+
51
+ # URIs
52
+ doc_entity = REGU[f"entity_doc_{doc_hash[:16]}"]
53
+ claim_entity = REGU[f"entity_claims_{spec.metadata.system_id}"]
54
+ graph_entity = REGU[f"entity_graph_{graph_hash[:16]}"]
55
+ report_entity = REGU[f"entity_report_{cert_hash[:16]}"]
56
+
57
+ act_extract = REGU[f"activity_extract_{spec.metadata.system_id}"]
58
+ act_shacl = REGU[f"activity_shacl_validation_{spec.metadata.system_id}"]
59
+
60
+ agent_engine = REGU["agent_reguai_reasoning_core_v1"]
61
+ agent_auditor = REGU[f"agent_{auditor_id}"]
62
+
63
+ # Agent Definitions
64
+ g.add((agent_engine, RDF.type, PROV.SoftwareAgent))
65
+ g.add((agent_engine, RDFS.label, Literal("ReguAI Neuro-Symbolic Reasoning Engine v0.1.0")))
66
+
67
+ g.add((agent_auditor, RDF.type, PROV.Agent))
68
+ g.add((agent_auditor, RDFS.label, Literal(f"Compliance Auditor: {auditor_id}")))
69
+
70
+ # Document Entity
71
+ g.add((doc_entity, RDF.type, PROV.Entity))
72
+ g.add((doc_entity, RDFS.label, Literal(f"Source Specification Document ({spec.metadata.name})")))
73
+ g.add((doc_entity, REGU.sha256, Literal(doc_hash)))
74
+
75
+ # Extraction Activity
76
+ g.add((act_extract, RDF.type, PROV.Activity))
77
+ g.add((act_extract, PROV.used, doc_entity))
78
+ g.add((act_extract, PROV.wasAssociatedWith, agent_engine))
79
+ g.add((act_extract, PROV.startedAtTime, Literal(now_iso, datatype=XSD.dateTime)))
80
+
81
+ # Claim Graph Entity
82
+ g.add((graph_entity, RDF.type, PROV.Entity))
83
+ g.add((graph_entity, PROV.wasGeneratedBy, act_extract))
84
+ g.add((graph_entity, REGU.canonicalGraphSha256, Literal(graph_hash)))
85
+
86
+ # SHACL Validation Activity
87
+ g.add((act_shacl, RDF.type, PROV.Activity))
88
+ g.add((act_shacl, PROV.used, graph_entity))
89
+ g.add((act_shacl, PROV.wasAssociatedWith, agent_engine))
90
+ g.add((act_shacl, PROV.wasAssociatedWith, agent_auditor))
91
+ g.add((act_shacl, PROV.endedAtTime, Literal(now_iso, datatype=XSD.dateTime)))
92
+
93
+ # Final Report Entity
94
+ g.add((report_entity, RDF.type, PROV.Entity))
95
+ g.add((report_entity, PROV.wasGeneratedBy, act_shacl))
96
+ g.add((report_entity, REGU.certificateHash, Literal(cert_hash)))
97
+ g.add((report_entity, REGU.conformityStatus, Literal("PASS" if conforms else "FAIL")))
98
+ g.add((report_entity, REGU.digitalSignature, Literal(digital_signature)))
99
+
100
+ prov_turtle = g.serialize(format="turtle")
101
+
102
+ return AuditProvenance(
103
+ input_doc_sha256=doc_hash,
104
+ graph_triples_sha256=graph_hash,
105
+ ruleset_sha256=ruleset_hash,
106
+ certificate_sha256=cert_hash,
107
+ prov_o_rdf=prov_turtle,
108
+ timestamp_utc=now_iso,
109
+ digital_signature=digital_signature,
110
+ )
src/ontology/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Ontologies and Semantic Builders."""
src/ontology/builder.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ RDF Knowledge Graph Builder.
3
+ Constructs RDFLib graphs from system specifications and extracted claims,
4
+ binding them to formal legal ontologies.
5
+ """
6
+
7
+ from typing import Tuple, Dict, Any, List
8
+ import rdflib
9
+ from rdflib import Graph, URIRef, Literal, RDF, RDFS, XSD
10
+
11
+ from src.core.config import REGU, EU_ACT, NIST, ISO, PROV, SH, SCHEMAS_DIR
12
+ from src.core.models import (
13
+ SystemSpecification,
14
+ ExtractedClaim,
15
+ EntityCategory,
16
+ AssertionStatus,
17
+ )
18
+
19
+
20
+ class NormativeGraphBuilder:
21
+ def __init__(self):
22
+ self.category_predicate_map = {
23
+ EntityCategory.RISK_MANAGEMENT: (REGU.hasRiskManagementSystem, REGU.RiskManagementSystem),
24
+ EntityCategory.DATA_GOVERNANCE: (REGU.hasDataGovernance, REGU.DataGovernanceProcess),
25
+ EntityCategory.BIAS_MITIGATION: (REGU.hasBiasMitigation, REGU.BiasMitigationControl),
26
+ EntityCategory.TECHNICAL_DOCUMENTATION: (REGU.hasTechnicalDocumentation, REGU.TechnicalDocumentation),
27
+ EntityCategory.RECORD_KEEPING: (REGU.hasLoggingCapability, REGU.AutomatedLogging),
28
+ EntityCategory.TRANSPARENCY: (REGU.hasTransparencySpecification, REGU.TransparencySpecification),
29
+ EntityCategory.HUMAN_OVERSIGHT: (REGU.hasHumanOversight, REGU.HumanOversightMechanism),
30
+ EntityCategory.ACCURACY_ROBUSTNESS: (REGU.hasRobustnessControl, REGU.RobustnessControl),
31
+ EntityCategory.CYBERSECURITY: (REGU.hasCybersecurityControl, REGU.CybersecurityControl),
32
+ EntityCategory.FAIL_SAFE: (REGU.hasEmergencyStop, REGU.StopMechanism),
33
+ }
34
+
35
+ def _bind_namespaces(self, g: Graph) -> None:
36
+ g.bind("regu", REGU)
37
+ g.bind("eu", EU_ACT)
38
+ g.bind("nist", NIST)
39
+ g.bind("iso", ISO)
40
+ g.bind("prov", PROV)
41
+ g.bind("sh", SH)
42
+
43
+ def load_base_ontologies(self) -> Graph:
44
+ """Loads base OWL/RDFS legal definitions into a Graph."""
45
+ g = Graph()
46
+ self._bind_namespaces(g)
47
+
48
+ eu_path = SCHEMAS_DIR / "eu_ai_act.ttl"
49
+ if eu_path.exists():
50
+ g.parse(str(eu_path), format="turtle")
51
+
52
+ return g
53
+
54
+ def build_system_graph(self, spec: SystemSpecification) -> Graph:
55
+ """
56
+ Translates a parsed SystemSpecification with extracted claims
57
+ into an RDF instance graph ready for SHACL verification.
58
+ """
59
+ g = Graph()
60
+ self._bind_namespaces(g)
61
+
62
+ sys_uri = REGU[f"system_{spec.metadata.system_id.replace('-', '_')}"]
63
+
64
+ # System Node & Typing
65
+ if "High-Risk" in spec.metadata.eu_risk_classification:
66
+ g.add((sys_uri, RDF.type, REGU.HighRiskAISystem))
67
+ else:
68
+ g.add((sys_uri, RDF.type, REGU.AISystem))
69
+
70
+ g.add((sys_uri, RDFS.label, Literal(spec.metadata.name)))
71
+ g.add((sys_uri, REGU.domain, Literal(spec.metadata.domain)))
72
+ g.add((sys_uri, REGU.version, Literal(spec.metadata.version)))
73
+ g.add((sys_uri, REGU.intendedPurpose, Literal(spec.metadata.intended_purpose)))
74
+ g.add((sys_uri, REGU.developer, Literal(spec.metadata.developer_name)))
75
+
76
+ # Process Claims into Instance Nodes
77
+ for idx, claim in enumerate(spec.extracted_claims):
78
+ if claim.category in self.category_predicate_map:
79
+ pred, target_cls = self.category_predicate_map[claim.category]
80
+ claim_node_uri = REGU[f"claim_{spec.metadata.system_id}_{idx}"]
81
+
82
+ g.add((claim_node_uri, RDF.type, target_cls))
83
+ g.add((sys_uri, pred, claim_node_uri))
84
+
85
+ # Implementation Status Mapping
86
+ if claim.assertion_status == AssertionStatus.IMPLEMENTED:
87
+ g.add((claim_node_uri, REGU.implementationStatus, REGU.Implemented))
88
+ elif claim.assertion_status == AssertionStatus.PLANNED:
89
+ g.add((claim_node_uri, REGU.implementationStatus, REGU.Planned))
90
+ else:
91
+ g.add((claim_node_uri, REGU.implementationStatus, REGU.Absent))
92
+
93
+ # Grounding Metadata
94
+ g.add((claim_node_uri, REGU.evidenceSource, Literal(claim.evidence_quote)))
95
+ g.add((claim_node_uri, REGU.confidenceScore, Literal(claim.confidence, datatype=XSD.float)))
96
+ g.add((claim_node_uri, REGU.normativeArticle, Literal(claim.normative_article)))
97
+
98
+ return g
99
+
100
+ def serialize(self, g: Graph, format: str = "turtle") -> str:
101
+ """Serializes the RDF graph to a string."""
102
+ return g.serialize(format=format)
src/ontology/schemas/eu_ai_act.ttl ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
2
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
3
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
4
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
5
+ @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
6
+ @prefix regu: <http://regu.ai/schema#> .
7
+ @prefix eu: <http://data.europa.eu/eli/reg/2024/1689#> .
8
+ @prefix nist: <http://csrc.nist.gov/ns/rmf#> .
9
+ @prefix iso: <http://iso.org/standard/42001#> .
10
+
11
+ # -------------------------------------------------------------------------
12
+ # Ontology Metadata
13
+ # -------------------------------------------------------------------------
14
+ <http://regu.ai/schema/eu_ai_act> a owl:Ontology ;
15
+ rdfs:label "ReguAI Normative EU AI Act Ontology" ;
16
+ rdfs:comment "Formal semantic representation of Regulation (EU) 2024/1689 Chapter III High-Risk AI Obligations." ;
17
+ owl:versionInfo "1.0.0" .
18
+
19
+ # -------------------------------------------------------------------------
20
+ # Core Classes
21
+ # -------------------------------------------------------------------------
22
+ regu:AISystem a owl:Class ;
23
+ rdfs:label "AI System" ;
24
+ rdfs:comment "A machine-based system designed to operate with varying levels of autonomy." .
25
+
26
+ regu:HighRiskAISystem a owl:Class ;
27
+ rdfs:subClassOf regu:AISystem ;
28
+ rdfs:label "High-Risk AI System" ;
29
+ rdfs:comment "AI system classified as high-risk under Article 6 and Annex III of Regulation (EU) 2024/1689." .
30
+
31
+ regu:ImplementationStatus a owl:Class ;
32
+ rdfs:label "Implementation Status" .
33
+
34
+ regu:Implemented a regu:ImplementationStatus ;
35
+ rdfs:label "Implemented" ;
36
+ rdfs:comment "Control is fully verified and operational in the system." .
37
+
38
+ regu:Planned a regu:ImplementationStatus ;
39
+ rdfs:label "Planned" ;
40
+ rdfs:comment "Control is on a future roadmap and not currently operational." .
41
+
42
+ regu:Absent a regu:ImplementationStatus ;
43
+ rdfs:label "Absent" ;
44
+ rdfs:comment "Control is explicitly missing or negative assertion identified." .
45
+
46
+ # -------------------------------------------------------------------------
47
+ # Article 9: Risk Management System
48
+ # -------------------------------------------------------------------------
49
+ regu:RiskManagementSystem a owl:Class ;
50
+ rdfs:label "Risk Management System" ;
51
+ eu:legalBasis "Article 9, Regulation (EU) 2024/1689" ;
52
+ nist:crossWalk nist:GOVERN .
53
+
54
+ regu:hasRiskManagementSystem a owl:ObjectProperty ;
55
+ rdfs:domain regu:HighRiskAISystem ;
56
+ rdfs:range regu:RiskManagementSystem .
57
+
58
+ # -------------------------------------------------------------------------
59
+ # Article 10: Data and Data Governance
60
+ # -------------------------------------------------------------------------
61
+ regu:DataGovernanceProcess a owl:Class ;
62
+ rdfs:label "Data Governance and Management" ;
63
+ eu:legalBasis "Article 10, Regulation (EU) 2024/1689" ;
64
+ nist:crossWalk nist:MAP .
65
+
66
+ regu:hasDataGovernance a owl:ObjectProperty ;
67
+ rdfs:domain regu:HighRiskAISystem ;
68
+ rdfs:range regu:DataGovernanceProcess .
69
+
70
+ regu:BiasMitigationControl a owl:Class ;
71
+ rdfs:label "Bias Examination and Mitigation Control" ;
72
+ eu:legalBasis "Article 10(2)(f), Regulation (EU) 2024/1689" ;
73
+ nist:crossWalk nist:MEASURE_2.11 .
74
+
75
+ regu:hasBiasMitigation a owl:ObjectProperty ;
76
+ rdfs:domain regu:HighRiskAISystem ;
77
+ rdfs:range regu:BiasMitigationControl .
78
+
79
+ # -------------------------------------------------------------------------
80
+ # Article 11: Technical Documentation
81
+ # -------------------------------------------------------------------------
82
+ regu:TechnicalDocumentation a owl:Class ;
83
+ rdfs:label "Technical Documentation" ;
84
+ eu:legalBasis "Article 11 & Annex IV, Regulation (EU) 2024/1689" ;
85
+ iso:crossWalk iso:Control_A_6_2 .
86
+
87
+ regu:hasTechnicalDocumentation a owl:ObjectProperty ;
88
+ rdfs:domain regu:HighRiskAISystem ;
89
+ rdfs:range regu:TechnicalDocumentation .
90
+
91
+ # -------------------------------------------------------------------------
92
+ # Article 12: Record-Keeping
93
+ # -------------------------------------------------------------------------
94
+ regu:AutomatedLogging a owl:Class ;
95
+ rdfs:label "Automated Record-Keeping / Event Logging" ;
96
+ eu:legalBasis "Article 12, Regulation (EU) 2024/1689" ;
97
+ nist:crossWalk nist:GOVERN_1.5 .
98
+
99
+ regu:hasLoggingCapability a owl:ObjectProperty ;
100
+ rdfs:domain regu:HighRiskAISystem ;
101
+ rdfs:range regu:AutomatedLogging .
102
+
103
+ # -------------------------------------------------------------------------
104
+ # Article 13: Transparency and Provision of Information
105
+ # -------------------------------------------------------------------------
106
+ regu:TransparencySpecification a owl:Class ;
107
+ rdfs:label "Transparency and Instructions for Use" ;
108
+ eu:legalBasis "Article 13, Regulation (EU) 2024/1689" ;
109
+ nist:crossWalk nist:MAP_1.2 .
110
+
111
+ regu:hasTransparencySpecification a owl:ObjectProperty ;
112
+ rdfs:domain regu:HighRiskAISystem ;
113
+ rdfs:range regu:TransparencySpecification .
114
+
115
+ # -------------------------------------------------------------------------
116
+ # Article 14: Human Oversight
117
+ # -------------------------------------------------------------------------
118
+ regu:HumanOversightMechanism a owl:Class ;
119
+ rdfs:label "Human Oversight Mechanism" ;
120
+ eu:legalBasis "Article 14, Regulation (EU) 2024/1689" ;
121
+ nist:crossWalk nist:MANAGE_2.2 .
122
+
123
+ regu:hasHumanOversight a owl:ObjectProperty ;
124
+ rdfs:domain regu:HighRiskAISystem ;
125
+ rdfs:range regu:HumanOversightMechanism .
126
+
127
+ regu:StopMechanism a owl:Class ;
128
+ rdfs:subClassOf regu:HumanOversightMechanism ;
129
+ rdfs:label "Human-in-the-Loop Override / Emergency Stop" ;
130
+ eu:legalBasis "Article 14(4)(e), Regulation (EU) 2024/1689" .
131
+
132
+ regu:hasEmergencyStop a owl:ObjectProperty ;
133
+ rdfs:domain regu:HighRiskAISystem ;
134
+ rdfs:range regu:StopMechanism .
135
+
136
+ # -------------------------------------------------------------------------
137
+ # Article 15: Accuracy, Robustness and Cybersecurity
138
+ # -------------------------------------------------------------------------
139
+ regu:RobustnessControl a owl:Class ;
140
+ rdfs:label "Robustness and Resilience Control" ;
141
+ eu:legalBasis "Article 15(1), Regulation (EU) 2024/1689" ;
142
+ nist:crossWalk nist:MEASURE_2.6 .
143
+
144
+ regu:hasRobustnessControl a owl:ObjectProperty ;
145
+ rdfs:domain regu:HighRiskAISystem ;
146
+ rdfs:range regu:RobustnessControl .
147
+
148
+ regu:CybersecurityControl a owl:Class ;
149
+ rdfs:label "Cybersecurity and Adversarial Defense Control" ;
150
+ eu:legalBasis "Article 15(4), Regulation (EU) 2024/1689" ;
151
+ nist:crossWalk nist:GOVERN_1.6 .
152
+
153
+ regu:hasCybersecurityControl a owl:ObjectProperty ;
154
+ rdfs:domain regu:HighRiskAISystem ;
155
+ rdfs:range regu:CybersecurityControl .
156
+
157
+ # -------------------------------------------------------------------------
158
+ # General Properties
159
+ # -------------------------------------------------------------------------
160
+ regu:implementationStatus a owl:ObjectProperty ;
161
+ rdfs:range regu:ImplementationStatus .
162
+
163
+ regu:evidenceSource a owl:DatatypeProperty ;
164
+ rdfs:range xsd:string .
165
+
166
+ regu:confidenceScore a owl:DatatypeProperty ;
167
+ rdfs:range xsd:float .
src/ontology/shacl/high_risk_eu_shapes.ttl ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
2
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
3
+ @prefix sh: <http://www.w3.org/ns/shacl#> .
4
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
5
+ @prefix regu: <http://regu.ai/schema#> .
6
+ @prefix eu: <http://data.europa.eu/eli/reg/2024/1689#> .
7
+
8
+ # =========================================================================
9
+ # ReguAI Normative SHACL Shape Validation
10
+ # Regulation (EU) 2024/1689 - Chapter III (High-Risk AI Systems)
11
+ # =========================================================================
12
+
13
+ regu:HighRiskSystemShape
14
+ a sh:NodeShape ;
15
+ sh:targetClass regu:HighRiskAISystem ;
16
+ sh:name "EU AI Act High-Risk System Mandatory Conformity Shape" ;
17
+ sh:description "Enforces mandatory deterministic legal constraints under Chapter III of the EU AI Act." ;
18
+
19
+ # ---------------------------------------------------------------------
20
+ # Article 9: Risk Management System
21
+ # ---------------------------------------------------------------------
22
+ sh:property [
23
+ sh:path regu:hasRiskManagementSystem ;
24
+ sh:minCount 1 ;
25
+ sh:severity sh:Violation ;
26
+ sh:message "EU AI Act Art 9 Non-Conformity: High-risk AI system must establish, implement, document and maintain a continuous risk management system." ;
27
+ ] ;
28
+ sh:property [
29
+ sh:path ( regu:hasRiskManagementSystem regu:implementationStatus ) ;
30
+ sh:hasValue regu:Implemented ;
31
+ sh:severity sh:Violation ;
32
+ sh:message "EU AI Act Art 9 Non-Conformity: Risk management system must be fully 'Implemented', not 'Planned' or 'Absent'." ;
33
+ ] ;
34
+
35
+ # ---------------------------------------------------------------------
36
+ # Article 10: Data Governance & Bias Mitigation
37
+ # ---------------------------------------------------------------------
38
+ sh:property [
39
+ sh:path regu:hasDataGovernance ;
40
+ sh:minCount 1 ;
41
+ sh:severity sh:Violation ;
42
+ sh:message "EU AI Act Art 10 Non-Conformity: Training, validation, and testing datasets must be governed with validated provenance and data quality checks." ;
43
+ ] ;
44
+ sh:property [
45
+ sh:path regu:hasBiasMitigation ;
46
+ sh:minCount 1 ;
47
+ sh:severity sh:Violation ;
48
+ sh:message "EU AI Act Art 10(2)(f) Non-Conformity: High-risk AI systems must have specific bias examination and mitigation controls across demographic groups." ;
49
+ ] ;
50
+ sh:property [
51
+ sh:path ( regu:hasBiasMitigation regu:implementationStatus ) ;
52
+ sh:hasValue regu:Implemented ;
53
+ sh:severity sh:Violation ;
54
+ sh:message "EU AI Act Art 10(2)(f) Non-Conformity: Bias mitigation control must have status 'Implemented'." ;
55
+ ] ;
56
+
57
+ # ---------------------------------------------------------------------
58
+ # Article 12: Record-Keeping & Logging
59
+ # ---------------------------------------------------------------------
60
+ sh:property [
61
+ sh:path regu:hasLoggingCapability ;
62
+ sh:minCount 1 ;
63
+ sh:severity sh:Violation ;
64
+ sh:message "EU AI Act Art 12 Non-Conformity: High-risk AI systems must technically enable automatic recording of events (logs) over their lifecycle." ;
65
+ ] ;
66
+ sh:property [
67
+ sh:path ( regu:hasLoggingCapability regu:implementationStatus ) ;
68
+ sh:hasValue regu:Implemented ;
69
+ sh:severity sh:Violation ;
70
+ sh:message "EU AI Act Art 12 Non-Conformity: Automated logging capability must be 'Implemented'." ;
71
+ ] ;
72
+
73
+ # ---------------------------------------------------------------------
74
+ # Article 13: Transparency
75
+ # ---------------------------------------------------------------------
76
+ sh:property [
77
+ sh:path regu:hasTransparencySpecification ;
78
+ sh:minCount 1 ;
79
+ sh:severity sh:Warning ;
80
+ sh:message "EU AI Act Art 13 Warning: High-risk AI systems must be accompanied by instructions for use and model card transparency disclosures." ;
81
+ ] ;
82
+
83
+ # ---------------------------------------------------------------------
84
+ # Article 14: Human Oversight
85
+ # ---------------------------------------------------------------------
86
+ sh:property [
87
+ sh:path regu:hasHumanOversight ;
88
+ sh:minCount 1 ;
89
+ sh:severity sh:Violation ;
90
+ sh:message "EU AI Act Art 14 Non-Conformity: High-risk AI systems must be designed to enable natural persons to oversee their operation (Human-in-the-loop / Human-on-the-loop)." ;
91
+ ] ;
92
+ sh:property [
93
+ sh:path ( regu:hasHumanOversight regu:implementationStatus ) ;
94
+ sh:hasValue regu:Implemented ;
95
+ sh:severity sh:Violation ;
96
+ sh:message "EU AI Act Art 14 Non-Conformity: Human oversight mechanism must be operational ('Implemented'), not merely 'Planned' or absent." ;
97
+ ] ;
98
+
99
+ # ---------------------------------------------------------------------
100
+ # Article 15: Accuracy, Robustness and Cybersecurity
101
+ # ---------------------------------------------------------------------
102
+ sh:property [
103
+ sh:path regu:hasCybersecurityControl ;
104
+ sh:minCount 1 ;
105
+ sh:severity sh:Violation ;
106
+ sh:message "EU AI Act Art 15(4) Non-Conformity: High-risk AI systems must have resilient cybersecurity defenses against adversarial inputs, model extraction, and data poisoning." ;
107
+ ] ;
108
+ sh:property [
109
+ sh:path ( regu:hasCybersecurityControl regu:implementationStatus ) ;
110
+ sh:hasValue regu:Implemented ;
111
+ sh:severity sh:Violation ;
112
+ sh:message "EU AI Act Art 15(4) Non-Conformity: Cybersecurity defenses must have status 'Implemented'." ;
113
+ ] .
src/reasoning/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Deterministic Reasoning and SHACL Validation."""
src/reasoning/shacl_engine.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Deterministic SHACL Reasoning Engine.
3
+ Executes W3C SHACL shape validation on the normative graph using PySHACL,
4
+ producing non-hallucinatory compliance proofs.
5
+ """
6
+
7
+ from typing import Tuple, List, Dict, Any
8
+ from pathlib import Path
9
+ import re
10
+ import rdflib
11
+ from rdflib import Graph, URIRef, RDF, RDFS, Namespace
12
+
13
+ from src.core.config import SH, REGU, EU_ACT, SHACL_DIR, SCHEMAS_DIR
14
+ from src.core.models import ValidationViolation, SystemSpecification
15
+
16
+
17
+ class DeterministicSHACLEngine:
18
+ def __init__(self):
19
+ self.shacl_ns = SH
20
+ self.regu_ns = REGU
21
+ self.shapes_graph = Graph()
22
+ self._load_shapes()
23
+
24
+ def _load_shapes(self) -> None:
25
+ """Loads all normative SHACL shape definitions."""
26
+ shape_files = list(SHACL_DIR.glob("*.ttl"))
27
+ for shape_file in shape_files:
28
+ self.shapes_graph.parse(str(shape_file), format="turtle")
29
+
30
+ def validate_system(
31
+ self,
32
+ system_graph: Graph,
33
+ ) -> Tuple[bool, List[ValidationViolation], List[ValidationViolation], float]:
34
+ """
35
+ Validates the system graph against normative SHACL shapes.
36
+ Returns:
37
+ - conforms (bool): Deterministic legal compliance flag
38
+ - violations (List[ValidationViolation]): Hard legal non-conformities
39
+ - warnings (List[ValidationViolation]): Recommendations / warnings
40
+ - conformity_score (float): Percentage of satisfied requirements
41
+ """
42
+ try:
43
+ import pyshacl
44
+ conforms, report_graph, report_text = pyshacl.validate(
45
+ data_graph=system_graph,
46
+ shacl_graph=self.shapes_graph,
47
+ inference="rdfs",
48
+ abort_on_first=False,
49
+ meta_shacl=False,
50
+ advanced=True,
51
+ debug=False,
52
+ )
53
+ violations, warnings = self._parse_shacl_report(report_graph)
54
+ except ImportError:
55
+ # Fallback deterministic rule validator if PySHACL is not installed in runtime
56
+ conforms, violations, warnings = self._fallback_deterministic_validation(system_graph)
57
+
58
+ total_rules = max(1, len(violations) + len(warnings) + 5)
59
+ passed_rules = max(0, total_rules - len(violations))
60
+ conformity_score = round((passed_rules / total_rules) * 100.0, 1)
61
+
62
+ return conforms, violations, warnings, conformity_score
63
+
64
+ def _parse_shacl_report(
65
+ self, report_graph: Graph
66
+ ) -> Tuple[List[ValidationViolation], List[ValidationViolation]]:
67
+ violations: List[ValidationViolation] = []
68
+ warnings: List[ValidationViolation] = []
69
+
70
+ query = """
71
+ PREFIX sh: <http://www.w3.org/ns/shacl#>
72
+ PREFIX regu: <http://regu.ai/schema#>
73
+
74
+ SELECT ?result ?focusNode ?resultPath ?severity ?message ?component
75
+ WHERE {
76
+ ?report a sh:ValidationReport ;
77
+ sh:result ?result .
78
+ ?result sh:focusNode ?focusNode ;
79
+ sh:resultSeverity ?severity ;
80
+ sh:resultMessage ?message .
81
+ OPTIONAL { ?result sh:resultPath ?resultPath }
82
+ OPTIONAL { ?result sh:sourceConstraintComponent ?component }
83
+ }
84
+ """
85
+
86
+ qres = report_graph.query(query)
87
+ for row in qres:
88
+ focus_node = str(row.focusNode)
89
+ res_path = str(row.resultPath) if row.resultPath else "Root"
90
+ severity_uri = str(row.severity)
91
+ message = str(row.message)
92
+ component = str(row.component) if row.component else "SHACL Constraint"
93
+
94
+ # Parse article tag from message (e.g., 'EU AI Act Art 14 Non-Conformity: ...')
95
+ article_match = re.search(r"Art\s*([0-9]+(?:\([0-9a-z]+\))*)", message)
96
+ article_num = f"Article {article_match.group(1)}" if article_match else "Chapter III"
97
+
98
+ remediation = self._generate_remediation(message, article_num)
99
+
100
+ violation_obj = ValidationViolation(
101
+ focus_node=focus_node,
102
+ result_path=res_path,
103
+ source_constraint_component=component,
104
+ message=message,
105
+ severity="Violation" if "Violation" in severity_uri else "Warning",
106
+ regulatory_article=article_num,
107
+ normative_reference=f"Regulation (EU) 2024/1689 {article_num}",
108
+ remediation_guidance=remediation,
109
+ )
110
+
111
+ if "Violation" in severity_uri:
112
+ violations.append(violation_obj)
113
+ else:
114
+ warnings.append(violation_obj)
115
+
116
+ return violations, warnings
117
+
118
+ def _fallback_deterministic_validation(
119
+ self, system_graph: Graph
120
+ ) -> Tuple[bool, List[ValidationViolation], List[ValidationViolation]]:
121
+ """
122
+ Pure Python SPARQL/Graph traversal fallback that enforces the identical
123
+ SHACL constraints deterministically without external C-extensions.
124
+ """
125
+ violations: List[ValidationViolation] = []
126
+ warnings: List[ValidationViolation] = []
127
+
128
+ # Find High-Risk system nodes
129
+ sys_nodes = list(system_graph.subjects(RDF.type, REGU.HighRiskAISystem))
130
+ if not sys_nodes:
131
+ return True, [], []
132
+
133
+ sys_node = sys_nodes[0]
134
+
135
+ # Check Human Oversight (Art 14)
136
+ oversight_nodes = list(system_graph.objects(sys_node, REGU.hasHumanOversight))
137
+ if not oversight_nodes:
138
+ violations.append(
139
+ ValidationViolation(
140
+ focus_node=str(sys_node),
141
+ result_path="regu:hasHumanOversight",
142
+ source_constraint_component="MinCountConstraintComponent",
143
+ message="EU AI Act Art 14 Non-Conformity: High-risk AI system must have an operational human oversight mechanism.",
144
+ severity="Violation",
145
+ regulatory_article="Article 14",
146
+ normative_reference="Regulation (EU) 2024/1689 Article 14",
147
+ remediation_guidance="Implement a human-in-the-loop review interface and emergency stop mechanism (Art 14(4)(e)).",
148
+ )
149
+ )
150
+ else:
151
+ for onode in oversight_nodes:
152
+ status = list(system_graph.objects(onode, REGU.implementationStatus))
153
+ if not status or REGU.Implemented not in status:
154
+ violations.append(
155
+ ValidationViolation(
156
+ focus_node=str(onode),
157
+ result_path="regu:implementationStatus",
158
+ source_constraint_component="HasValueConstraintComponent",
159
+ message="EU AI Act Art 14 Non-Conformity: Human oversight mechanism must be 'Implemented', not 'Planned' or 'Absent'.",
160
+ severity="Violation",
161
+ regulatory_article="Article 14",
162
+ normative_reference="Regulation (EU) 2024/1689 Article 14(1)",
163
+ remediation_guidance="Transition planned human oversight controls into verified active production controls.",
164
+ )
165
+ )
166
+
167
+ # Check Data Governance & Bias Mitigation (Art 10)
168
+ data_nodes = list(system_graph.objects(sys_node, REGU.hasDataGovernance))
169
+ bias_nodes = list(system_graph.objects(sys_node, REGU.hasBiasMitigation))
170
+ if not data_nodes:
171
+ violations.append(
172
+ ValidationViolation(
173
+ focus_node=str(sys_node),
174
+ result_path="regu:hasDataGovernance",
175
+ source_constraint_component="MinCountConstraintComponent",
176
+ message="EU AI Act Art 10 Non-Conformity: Training, validation, and testing datasets must have documented provenance and governance.",
177
+ severity="Violation",
178
+ regulatory_article="Article 10",
179
+ normative_reference="Regulation (EU) 2024/1689 Article 10",
180
+ remediation_guidance="Document dataset lineage, data collection sheets, and representativeness assessments.",
181
+ )
182
+ )
183
+
184
+ if not bias_nodes:
185
+ violations.append(
186
+ ValidationViolation(
187
+ focus_node=str(sys_node),
188
+ result_path="regu:hasBiasMitigation",
189
+ source_constraint_component="MinCountConstraintComponent",
190
+ message="EU AI Act Art 10(2)(f) Non-Conformity: High-risk AI systems must have verified bias examination and mitigation.",
191
+ severity="Violation",
192
+ regulatory_article="Article 10(2)(f)",
193
+ normative_reference="Regulation (EU) 2024/1689 Article 10(2)(f)",
194
+ remediation_guidance="Execute demographic parity / disparate impact testing and log mitigation results.",
195
+ )
196
+ )
197
+ else:
198
+ for bnode in bias_nodes:
199
+ status = list(system_graph.objects(bnode, REGU.implementationStatus))
200
+ if not status or REGU.Implemented not in status:
201
+ violations.append(
202
+ ValidationViolation(
203
+ focus_node=str(bnode),
204
+ result_path="regu:implementationStatus",
205
+ source_constraint_component="HasValueConstraintComponent",
206
+ message="EU AI Act Art 10(2)(f) Non-Conformity: Bias mitigation control must be operational ('Implemented').",
207
+ severity="Violation",
208
+ regulatory_article="Article 10(2)(f)",
209
+ normative_reference="Regulation (EU) 2024/1689 Article 10(2)(f)",
210
+ remediation_guidance="Ensure bias mitigations are verified on current production model weights.",
211
+ )
212
+ )
213
+
214
+ # Check Risk Management (Art 9)
215
+ risk_nodes = list(system_graph.objects(sys_node, REGU.hasRiskManagementSystem))
216
+ if not risk_nodes:
217
+ violations.append(
218
+ ValidationViolation(
219
+ focus_node=str(sys_node),
220
+ result_path="regu:hasRiskManagementSystem",
221
+ source_constraint_component="MinCountConstraintComponent",
222
+ message="EU AI Act Art 9 Non-Conformity: Continuous risk management system must be established and documented.",
223
+ severity="Violation",
224
+ regulatory_article="Article 9",
225
+ normative_reference="Regulation (EU) 2024/1689 Article 9",
226
+ remediation_guidance="Establish risk identification, estimation, and residual risk mitigation procedures.",
227
+ )
228
+ )
229
+
230
+ # Check Cybersecurity (Art 15)
231
+ cyber_nodes = list(system_graph.objects(sys_node, REGU.hasCybersecurityControl))
232
+ if not cyber_nodes:
233
+ violations.append(
234
+ ValidationViolation(
235
+ focus_node=str(sys_node),
236
+ result_path="regu:hasCybersecurityControl",
237
+ source_constraint_component="MinCountConstraintComponent",
238
+ message="EU AI Act Art 15(4) Non-Conformity: High-risk AI systems must have resilient cybersecurity defenses.",
239
+ severity="Violation",
240
+ regulatory_article="Article 15(4)",
241
+ normative_reference="Regulation (EU) 2024/1689 Article 15(4)",
242
+ remediation_guidance="Perform adversarial robustness testing and implement input sanitizer defenses.",
243
+ )
244
+ )
245
+
246
+ conforms = len(violations) == 0
247
+ return conforms, violations, warnings
248
+
249
+ def _generate_remediation(self, message: str, article: str) -> str:
250
+ if "14" in article:
251
+ return "Implement human override controls, confirmation thresholds, and emergency stop triggers."
252
+ elif "10" in article:
253
+ return "Supply verified training data sheets and audit protected demographic subgroup performance metrics."
254
+ elif "15" in article:
255
+ return "Conduct adversarial robustness evaluation and document perimeter defenses against prompt injection/data poisoning."
256
+ elif "9" in article:
257
+ return "Formalize the enterprise risk matrix and post-market risk monitoring protocols."
258
+ elif "12" in article:
259
+ return "Enable tamper-evident audit logging for all inference requests and operator interventions."
260
+ return "Refer to EU AI Act Annex IV technical documentation guidance."
src/triage/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Active Learning and Auditor Triage."""
src/triage/active_learning.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Auditor-in-the-Loop Active Learning Queue and Triplet Generation.
3
+ Captures human auditor feedback on borderline claims and formats triplet loss
4
+ training pairs (anchor, positive, negative) for continuous model alignment.
5
+ """
6
+
7
+ import json
8
+ from pathlib import Path
9
+ from datetime import datetime, timezone
10
+ from typing import List, Dict, Any, Optional
11
+
12
+ from src.core.models import ExtractedClaim, AssertionStatus, EntityCategory
13
+ from src.core.config import DATA_DIR
14
+
15
+
16
+ class ActiveLearningTriageQueue:
17
+ def __init__(self, storage_path: Optional[Path] = None):
18
+ self.storage_path = storage_path or (DATA_DIR / "active_learning_triplets.jsonl")
19
+ self.storage_path.parent.mkdir(parents=True, exist_ok=True)
20
+
21
+ def filter_borderline_claims(self, claims: List[ExtractedClaim]) -> List[ExtractedClaim]:
22
+ """Filters claims that need human auditor review."""
23
+ return [c for c in claims if c.requires_auditor_review or c.confidence < 0.85]
24
+
25
+ def record_auditor_decision(
26
+ self,
27
+ claim: ExtractedClaim,
28
+ auditor_id: str,
29
+ verified_status: AssertionStatus,
30
+ verified_category: EntityCategory,
31
+ notes: str = "",
32
+ ) -> Dict[str, Any]:
33
+ """
34
+ Records human compliance decision and generates triplet feedback sample.
35
+ Anchor: evidence quote
36
+ Positive: auditor-verified category
37
+ Negative: rejected/original category (if changed) or alternative category
38
+ """
39
+ claim.auditor_verified = True
40
+ claim.assertion_status = verified_status
41
+ claim.requires_auditor_review = False
42
+ claim.auditor_notes = notes
43
+
44
+ # Formulate Triplet Instance
45
+ original_cat = claim.category.value
46
+ positive_label = verified_category.value
47
+ negative_label = original_cat if original_cat != positive_label else "IRRELEVANT_TEXT"
48
+
49
+ triplet_record = {
50
+ "timestamp": datetime.now(timezone.utc).isoformat(),
51
+ "auditor_id": auditor_id,
52
+ "claim_id": claim.claim_id,
53
+ "anchor_text": claim.evidence_quote,
54
+ "positive_label": positive_label,
55
+ "negative_label": negative_label,
56
+ "verified_assertion_status": verified_status.value,
57
+ "auditor_notes": notes,
58
+ }
59
+
60
+ # Append to feedback file
61
+ with open(self.storage_path, "a", encoding="utf-8") as f:
62
+ f.write(json.dumps(triplet_record) + "\n")
63
+
64
+ return triplet_record
65
+
66
+ def get_audit_history(self) -> List[Dict[str, Any]]:
67
+ """Reads recorded active learning triplet feedback history."""
68
+ if not self.storage_path.exists():
69
+ return []
70
+ records = []
71
+ with open(self.storage_path, "r", encoding="utf-8") as f:
72
+ for line in f:
73
+ if line.strip():
74
+ records.append(json.loads(line.strip()))
75
+ return records
src/triage/report_generator.py ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Conformity Assessment Report and Technical Documentation Package Generator.
3
+ Produces human-readable Annex IV audit reports (Markdown/HTML) and JSON-LD digital certificates.
4
+ """
5
+
6
+ from datetime import datetime, timezone
7
+ import json
8
+ from typing import Dict, Any
9
+
10
+ from src.core.models import ConformityReport, ValidationViolation, ExtractedClaim
11
+
12
+
13
+ class ConformityReportGenerator:
14
+ def generate_markdown_report(self, report: ConformityReport) -> str:
15
+ """Generates an official EU AI Act Annex IV Technical Documentation report."""
16
+ meta = report.system_metadata
17
+ prov = report.provenance
18
+ status_badge = "✅ CONFORMS (PASS)" if report.overall_conforms else "❌ NON-CONFORMANT (FAIL)"
19
+
20
+ md = []
21
+ md.append(f"# EU AI Act Conformity Assessment Report (Annex IV)")
22
+ md.append(f"**Verification Engine:** ReguAI Neuro-Symbolic Governance Core v0.1.0 ")
23
+ md.append(f"**Assessment Date (UTC):** {report.generated_at_utc} ")
24
+ md.append(f"**Certificate Token:** `{prov.digital_signature}` ")
25
+ md.append(f"**Status:** {status_badge} ")
26
+ md.append(f"**Conformity Index:** **{report.conformity_score:.1f}%** ({report.passed_requirements_count}/{report.total_requirements_evaluated} requirements satisfied)\n")
27
+ md.append("---")
28
+
29
+ # Executive Summary
30
+ md.append("## 1. Executive Summary")
31
+ md.append(report.executive_summary)
32
+ md.append("")
33
+
34
+ # Section 2: System Identification
35
+ md.append("## 2. System Identification & Scope (Annex IV, Point 1)")
36
+ md.append(f"- **System Name:** {meta.name}")
37
+ md.append(f"- **System ID:** `{meta.system_id}`")
38
+ md.append(f"- **Version:** {meta.version}")
39
+ md.append(f"- **Developer:** {meta.developer_name}")
40
+ md.append(f"- **Domain:** {meta.domain}")
41
+ md.append(f"- **Intended Purpose:** {meta.intended_purpose}")
42
+ md.append(f"- **EU AI Act Risk Classification:** **{meta.eu_risk_classification}**\n")
43
+
44
+ # Section 3: Deterministic SHACL Verification Results
45
+ md.append("## 3. Deterministic SHACL Normative Proofs (Chapter III)")
46
+ if report.overall_conforms:
47
+ md.append("All mandatory W3C SHACL shape constraints for Articles 9 through 15 were successfully satisfied with mathematical proof. No constraint violations found.\n")
48
+ else:
49
+ md.append(f"### Detected Legal Violations ({len(report.violations)})")
50
+ md.append("| Legal Article | Normative Requirement | Severity | SHACL Path | Remediation Guidance |")
51
+ md.append("|---|---|---|---|---|")
52
+ for v in report.violations:
53
+ md.append(f"| **{v.regulatory_article}** | {v.message} | `{v.severity}` | `{v.result_path}` | {v.remediation_guidance} |")
54
+ md.append("")
55
+
56
+ if report.warnings:
57
+ md.append(f"### Advisory Warnings ({len(report.warnings)})")
58
+ for w in report.warnings:
59
+ md.append(f"- **{w.regulatory_article} ({w.source_constraint_component}):** {w.message}")
60
+ md.append("")
61
+
62
+ # Section 4: Regulatory Claim Inventory
63
+ md.append("## 4. Extracted Regulatory Claims & Grounded Entities")
64
+ md.append("| Claim ID | Entity Category | Assertion Status | Confidence | Legal Target | Evidence Span |")
65
+ md.append("|---|---|---|---|---|---|")
66
+ for c in report.claims_analyzed:
67
+ status_emoji = "🟢" if c.assertion_status.value == "IMPLEMENTED" else ("🟡" if c.assertion_status.value == "PLANNED" else "🔴")
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}`")
76
+ md.append(f"- **EU AI Act SHACL Ruleset SHA-256:** `{prov.ruleset_sha256}`")
77
+ md.append(f"- **Conformity Certificate Digest:** `{prov.certificate_sha256}`")
78
+ md.append(f"- **Immutable Token:** `{prov.digital_signature}`\n")
79
+
80
+ md.append("### W3C PROV-O Turtle Graph")
81
+ md.append("```turtle")
82
+ md.append(prov.prov_o_rdf.strip())
83
+ md.append("```\n")
84
+
85
+ return "\n".join(md)
86
+
87
+ def generate_json_ld(self, report: ConformityReport) -> Dict[str, Any]:
88
+ """Generates machine-readable JSON-LD conformity certificate."""
89
+ meta = report.system_metadata
90
+ prov = report.provenance
91
+
92
+ return {
93
+ "@context": {
94
+ "regu": "http://regu.ai/schema#",
95
+ "eu": "http://data.europa.eu/eli/reg/2024/1689#",
96
+ "prov": "http://www.w3.org/ns/prov#",
97
+ "xsd": "http://www.w3.org/2001/XMLSchema#",
98
+ },
99
+ "@id": f"http://regu.ai/certificates/{prov.digital_signature}",
100
+ "@type": "regu:ConformityCertificate",
101
+ "regu:systemId": meta.system_id,
102
+ "regu:systemName": meta.name,
103
+ "regu:conformityStatus": "PASS" if report.overall_conforms else "FAIL",
104
+ "regu:conformityScore": report.conformity_score,
105
+ "regu:timestampUtc": report.generated_at_utc,
106
+ "regu:digitalSignature": prov.digital_signature,
107
+ "regu:sourceDocHash": prov.input_doc_sha256,
108
+ "regu:canonicalGraphHash": prov.graph_triples_sha256,
109
+ "regu:violationsCount": len(report.violations),
110
+ "regu:violations": [
111
+ {
112
+ "article": v.regulatory_article,
113
+ "message": v.message,
114
+ "remediation": v.remediation_guidance,
115
+ }
116
+ for v in report.violations
117
+ ],
118
+ }
119
+
120
+ def generate_html_certificate(self, report: ConformityReport) -> str:
121
+ """Generates a formal, print-ready HTML Conformity Attestation Certificate."""
122
+ meta = report.system_metadata
123
+ prov = report.provenance
124
+ is_pass = report.overall_conforms
125
+ badge_bg = "#10b981" if is_pass else "#ef4444"
126
+ badge_text = "CONFORMANT (APPROVED)" if is_pass else "NON-CONFORMANT (REJECTED)"
127
+
128
+ violations_rows = ""
129
+ if report.violations:
130
+ for v in report.violations:
131
+ violations_rows += f"""
132
+ <tr>
133
+ <td style="padding: 8px; border: 1px solid #e2e8f0; font-weight: 600; color: #b91c1c;">{v.regulatory_article}</td>
134
+ <td style="padding: 8px; border: 1px solid #e2e8f0; font-size: 13px;">{v.message}</td>
135
+ <td style="padding: 8px; border: 1px solid #e2e8f0; font-size: 13px; color: #475569;">{v.remediation_guidance}</td>
136
+ </tr>
137
+ """
138
+ else:
139
+ violations_rows = """
140
+ <tr>
141
+ <td colspan="3" style="padding: 12px; border: 1px solid #e2e8f0; text-align: center; color: #15803d; font-weight: 600;">
142
+ ✓ Zero non-conformities identified. All W3C SHACL Chapter III constraints satisfied.
143
+ </td>
144
+ </tr>
145
+ """
146
+
147
+ html = f"""<!DOCTYPE html>
148
+ <html>
149
+ <head>
150
+ <meta charset="utf-8">
151
+ <title>EU AI Act Conformity Attestation - {meta.name}</title>
152
+ <style>
153
+ body {{
154
+ font-family: 'Helvetica Neue', Arial, sans-serif;
155
+ color: #1e293b;
156
+ margin: 0;
157
+ padding: 30px;
158
+ background: #ffffff;
159
+ line-height: 1.5;
160
+ }}
161
+ .certificate-container {{
162
+ max-width: 860px;
163
+ margin: 0 auto;
164
+ border: 4px double #cbd5e1;
165
+ padding: 40px;
166
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
167
+ }}
168
+ .header {{
169
+ display: flex;
170
+ justify-content: space-between;
171
+ align-items: center;
172
+ border-bottom: 2px solid #0f172a;
173
+ padding-bottom: 15px;
174
+ margin-bottom: 25px;
175
+ }}
176
+ .eu-stars {{
177
+ font-size: 24px;
178
+ color: #1d4ed8;
179
+ letter-spacing: 2px;
180
+ }}
181
+ .title-block h1 {{
182
+ margin: 0;
183
+ font-size: 22px;
184
+ text-transform: uppercase;
185
+ letter-spacing: 1px;
186
+ color: #0f172a;
187
+ }}
188
+ .title-block p {{
189
+ margin: 4px 0 0 0;
190
+ font-size: 12px;
191
+ color: #64748b;
192
+ }}
193
+ .status-seal {{
194
+ background: {badge_bg};
195
+ color: white;
196
+ padding: 8px 18px;
197
+ font-weight: 700;
198
+ font-size: 14px;
199
+ border-radius: 4px;
200
+ letter-spacing: 0.5px;
201
+ text-transform: uppercase;
202
+ }}
203
+ .info-grid {{
204
+ display: grid;
205
+ grid-template-columns: 1fr 1fr;
206
+ gap: 15px;
207
+ margin-bottom: 25px;
208
+ background: #f8fafc;
209
+ padding: 15px;
210
+ border-radius: 6px;
211
+ font-size: 13px;
212
+ }}
213
+ .info-item strong {{
214
+ color: #475569;
215
+ display: block;
216
+ font-size: 11px;
217
+ text-transform: uppercase;
218
+ }}
219
+ table {{
220
+ width: 100%;
221
+ border-collapse: collapse;
222
+ margin: 15px 0 25px 0;
223
+ }}
224
+ th {{
225
+ background: #f1f5f9;
226
+ padding: 8px;
227
+ border: 1px solid #cbd5e1;
228
+ font-size: 12px;
229
+ text-transform: uppercase;
230
+ text-align: left;
231
+ }}
232
+ .crypto-block {{
233
+ background: #0f172a;
234
+ color: #94a3b8;
235
+ padding: 15px;
236
+ border-radius: 6px;
237
+ font-family: monospace;
238
+ font-size: 11px;
239
+ margin-top: 20px;
240
+ }}
241
+ .crypto-block strong {{
242
+ color: #38bdf8;
243
+ }}
244
+ .signature-block {{
245
+ margin-top: 35px;
246
+ display: flex;
247
+ justify-content: space-between;
248
+ padding-top: 20px;
249
+ border-top: 1px dashed #cbd5e1;
250
+ font-size: 12px;
251
+ }}
252
+ .sig-box {{
253
+ width: 45%;
254
+ }}
255
+ .sig-line {{
256
+ margin-top: 40px;
257
+ border-bottom: 1px solid #475569;
258
+ }}
259
+ @media print {{
260
+ body {{ padding: 0; background: white; }}
261
+ .certificate-container {{ border: 2px solid #000; box-shadow: none; padding: 20px; }}
262
+ .no-print {{ display: none; }}
263
+ }}
264
+ </style>
265
+ </head>
266
+ <body>
267
+ <div class="certificate-container">
268
+ <div class="header">
269
+ <div class="title-block">
270
+ <div class="eu-stars">🇪🇺 ★★★★★</div>
271
+ <h1>EU AI Act Conformity Attestation</h1>
272
+ <p>Formal Verification under Regulation (EU) 2024/1689 (Annex IV & Annex VII)</p>
273
+ </div>
274
+ <div class="status-seal">{badge_text}</div>
275
+ </div>
276
+
277
+ <div class="info-grid">
278
+ <div class="info-item"><strong>AI System Name</strong> {meta.name} (v{meta.version})</div>
279
+ <div class="info-item"><strong>Developer / Provider</strong> {meta.developer_name}</div>
280
+ <div class="info-item"><strong>Risk Classification</strong> {meta.eu_risk_classification}</div>
281
+ <div class="info-item"><strong>Application Domain</strong> {meta.domain}</div>
282
+ <div class="info-item" style="grid-column: span 2;"><strong>Intended Purpose</strong> {meta.intended_purpose}</div>
283
+ <div class="info-item"><strong>Verification Method</strong> Formal W3C SHACL Symbolic Constraint Solver</div>
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>
290
+ <tr>
291
+ <th style="width: 18%;">Legal Article</th>
292
+ <th>Normative SHACL Constraint</th>
293
+ <th style="width: 35%;">Remediation / Status</th>
294
+ </tr>
295
+ </thead>
296
+ <tbody>
297
+ {violations_rows}
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>
304
+ Source Document Digest: {prov.input_doc_sha256}<br>
305
+ Normative Graph Digest: {prov.graph_triples_sha256}<br>
306
+ SHACL Ruleset Digest: {prov.ruleset_sha256}<br>
307
+ Assessment Timestamp: {report.generated_at_utc}
308
+ </div>
309
+
310
+ <div class="signature-block">
311
+ <div class="sig-box">
312
+ <strong>Attesting Audit Agent:</strong> ReguAI Symbolic Governance Core v0.1.0<br>
313
+ <div class="sig-line"></div>
314
+ Automated Mathematical Attestation
315
+ </div>
316
+ <div class="sig-box">
317
+ <strong>Lead Compliance Officer:</strong> Verified Human-in-the-Loop Sign-off<br>
318
+ <div class="sig-line"></div>
319
+ Authorized Signature & Date
320
+ </div>
321
+ </div>
322
+ </div>
323
+ </body>
324
+ </html>
325
+ """
326
+ return html
src/ui/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI UI and Visualization Components."""
src/ui/graph_view.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Interactive Regulatory Graph Explorer using Vis.js.
3
+ Renders force-directed knowledge graph of AI system specifications,
4
+ regulatory requirements, and SHACL validation status.
5
+ """
6
+
7
+ import json
8
+ from typing import Dict, Any, List
9
+ from src.core.models import ConformityReport, AssertionStatus
10
+
11
+
12
+ class RegulatoryGraphView:
13
+ def generate_html_graph(self, report: ConformityReport) -> str:
14
+ """
15
+ Generates an interactive Vis.js HTML graph visualization embedded in an iframe.
16
+ """
17
+ meta = report.system_metadata
18
+ nodes = []
19
+ edges = []
20
+
21
+ # 1. Central System Node
22
+ sys_id = f"sys_{meta.system_id}"
23
+ sys_color = "#10b981" if report.overall_conforms else "#ef4444"
24
+ nodes.append({
25
+ "id": sys_id,
26
+ "label": f"AI SYSTEM\n{meta.name}\n(v{meta.version})",
27
+ "shape": "hexagon",
28
+ "size": 35,
29
+ "color": {
30
+ "background": sys_color,
31
+ "border": "#0f172a",
32
+ "highlight": {"background": sys_color, "border": "#3b82f6"},
33
+ },
34
+ "font": {"color": "#ffffff", "face": "Segoe UI", "size": 14, "bold": True},
35
+ "title": f"<b>{meta.name}</b><br>Risk Class: {meta.eu_risk_classification}<br>Domain: {meta.domain}",
36
+ })
37
+
38
+ # 2. Regulatory Article Nodes (EU AI Act Title III)
39
+ articles = [
40
+ {"id": "art_9", "label": "Art 9: Risk\nManagement", "desc": "Continuous risk management system"},
41
+ {"id": "art_10", "label": "Art 10: Data\nGovernance", "desc": "Training/validation dataset governance"},
42
+ {"id": "art_10_bias", "label": "Art 10(2)(f):\nBias Mitigation", "desc": "Demographic parity and bias audits"},
43
+ {"id": "art_12", "label": "Art 12: Automated\nLogging", "desc": "Inference and event logging"},
44
+ {"id": "art_13", "label": "Art 13:\nTransparency", "desc": "Instructions for use and model cards"},
45
+ {"id": "art_14", "label": "Art 14: Human\nOversight", "desc": "Human-in-the-loop and manual override"},
46
+ {"id": "art_15", "label": "Art 15:\nCybersecurity", "desc": "Adversarial robustness and resilience"},
47
+ ]
48
+
49
+ # Check which articles have violations
50
+ violated_articles = set()
51
+ for v in report.violations:
52
+ for art in articles:
53
+ art_num = art["label"].split(":")[0].replace("Art ", "").strip()
54
+ if art_num in v.regulatory_article:
55
+ violated_articles.add(art["id"])
56
+
57
+ for art in articles:
58
+ is_violated = art["id"] in violated_articles
59
+ art_color = "#fca5a5" if is_violated else "#bfdbfe"
60
+ art_border = "#dc2626" if is_violated else "#2563eb"
61
+
62
+ nodes.append({
63
+ "id": art["id"],
64
+ "label": art["label"],
65
+ "shape": "box",
66
+ "margin": 10,
67
+ "color": {
68
+ "background": art_color,
69
+ "border": art_border,
70
+ "highlight": {"background": "#e2e8f0", "border": art_border},
71
+ },
72
+ "font": {"color": "#0f172a", "face": "Segoe UI", "size": 12, "bold": True},
73
+ "title": f"<b>{art['label']}</b><br>{art['desc']}<br>Status: {'❌ VIOLATION DETECTED' if is_violated else '✅ SATISFIED'}",
74
+ })
75
+
76
+ # Edge from System to Article
77
+ edges.append({
78
+ "from": sys_id,
79
+ "to": art["id"],
80
+ "color": {"color": "#dc2626" if is_violated else "#94a3b8", "highlight": "#2563eb"},
81
+ "width": 2 if not is_violated else 3,
82
+ "dashes": is_violated,
83
+ })
84
+
85
+ # 3. Extracted Claim / Control Nodes
86
+ article_mapping = {
87
+ "RISK_MANAGEMENT": "art_9",
88
+ "DATA_GOVERNANCE": "art_10",
89
+ "BIAS_MITIGATION": "art_10_bias",
90
+ "RECORD_KEEPING": "art_12",
91
+ "TRANSPARENCY": "art_13",
92
+ "HUMAN_OVERSIGHT": "art_14",
93
+ "FAIL_SAFE": "art_14",
94
+ "ACCURACY_ROBUSTNESS": "art_15",
95
+ "CYBERSECURITY": "art_15",
96
+ }
97
+
98
+ for idx, claim in enumerate(report.claims_analyzed):
99
+ claim_node_id = f"claim_{claim.claim_id}"
100
+
101
+ if claim.assertion_status == AssertionStatus.IMPLEMENTED:
102
+ c_color = "#34d399"
103
+ c_border = "#059669"
104
+ status_icon = "🟢"
105
+ elif claim.assertion_status == AssertionStatus.PLANNED:
106
+ c_color = "#fcd34d"
107
+ c_border = "#d97706"
108
+ status_icon = "🟡"
109
+ else:
110
+ c_color = "#f87171"
111
+ c_border = "#b91c1c"
112
+ status_icon = "🔴"
113
+
114
+ nodes.append({
115
+ "id": claim_node_id,
116
+ "label": f"{status_icon} {claim.entity_text[:20]}\n[{claim.assertion_status.value}]",
117
+ "shape": "ellipse",
118
+ "color": {
119
+ "background": c_color,
120
+ "border": c_border,
121
+ "highlight": {"background": "#ffffff", "border": c_border},
122
+ },
123
+ "font": {"color": "#0f172a", "face": "Segoe UI", "size": 11},
124
+ "title": (
125
+ f"<b>{claim.claim_id}: {claim.entity_text}</b><br>"
126
+ f"Status: <b>{claim.assertion_status.value}</b> (Confidence: {claim.confidence:.2f})<br>"
127
+ f"Target: {claim.normative_article}<br>"
128
+ f"<i>\"{claim.evidence_quote}\"</i>"
129
+ ),
130
+ })
131
+
132
+ # Connect Claim to its Regulatory Article
133
+ target_art = article_mapping.get(claim.category.value, "art_9")
134
+ edges.append({
135
+ "from": target_art,
136
+ "to": claim_node_id,
137
+ "color": {"color": c_border},
138
+ "width": 1.5,
139
+ })
140
+
141
+ nodes_json = json.dumps(nodes)
142
+ edges_json = json.dumps(edges)
143
+
144
+ html = f"""
145
+ <!DOCTYPE html>
146
+ <html>
147
+ <head>
148
+ <meta charset="utf-8" />
149
+ <script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
150
+ <style type="text/css">
151
+ body, html {{
152
+ margin: 0;
153
+ padding: 0;
154
+ width: 100%;
155
+ height: 100%;
156
+ overflow: hidden;
157
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
158
+ background: #f8fafc;
159
+ }}
160
+ #network {{
161
+ width: 100%;
162
+ height: 520px;
163
+ border: 1px solid #e2e8f0;
164
+ border-radius: 8px;
165
+ background: #ffffff;
166
+ }}
167
+ .legend {{
168
+ position: absolute;
169
+ bottom: 12px;
170
+ left: 12px;
171
+ background: rgba(255, 255, 255, 0.95);
172
+ border: 1px solid #cbd5e1;
173
+ padding: 8px 12px;
174
+ border-radius: 6px;
175
+ font-size: 11px;
176
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
177
+ display: flex;
178
+ gap: 12px;
179
+ z-index: 10;
180
+ }}
181
+ .legend-item {{
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 5px;
185
+ }}
186
+ .dot {{
187
+ width: 10px;
188
+ height: 10px;
189
+ border-radius: 50%;
190
+ }}
191
+ </style>
192
+ </head>
193
+ <body>
194
+ <div id="network"></div>
195
+ <div class="legend">
196
+ <div class="legend-item"><div class="dot" style="background: #10b981;"></div> Implemented / Conforming</div>
197
+ <div class="legend-item"><div class="dot" style="background: #f59e0b;"></div> Planned / Borderline</div>
198
+ <div class="legend-item"><div class="dot" style="background: #ef4444;"></div> Absent / SHACL Violation</div>
199
+ <div class="legend-item"><div class="dot" style="background: #3b82f6;"></div> Regulatory Article</div>
200
+ </div>
201
+
202
+ <script type="text/javascript">
203
+ var container = document.getElementById('network');
204
+ var data = {{
205
+ nodes: new vis.DataSet({nodes_json}),
206
+ edges: new vis.DataSet({edges_json})
207
+ }};
208
+ var options = {{
209
+ nodes: {{
210
+ borderWidth: 2,
211
+ shadow: true
212
+ }},
213
+ edges: {{
214
+ smooth: {{
215
+ type: 'cubicBezier',
216
+ forceDirection: 'none',
217
+ roundness: 0.3
218
+ }}
219
+ }},
220
+ physics: {{
221
+ solver: 'forceAtlas2Based',
222
+ forceAtlas2Based: {{
223
+ gravitationalConstant: -70,
224
+ centralGravity: 0.015,
225
+ springLength: 95,
226
+ springConstant: 0.08
227
+ }},
228
+ minVelocity: 0.75
229
+ }},
230
+ interaction: {{
231
+ hover: true,
232
+ tooltipDelay: 100,
233
+ zoomView: true
234
+ }}
235
+ }};
236
+ var network = new vis.Network(container, data, options);
237
+ </script>
238
+ </body>
239
+ </html>
240
+ """
241
+ return html
tests/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """ReguAI Test Suite."""
tests/test_api.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for ReguAI Enterprise REST API.
3
+ """
4
+
5
+ from fastapi.testclient import TestClient
6
+ from api import app
7
+
8
+ client = TestClient(app)
9
+
10
+
11
+ def test_api_health():
12
+ response = client.get("/health")
13
+ assert response.status_code == 200
14
+ data = response.json()
15
+ assert data["status"] == "HEALTHY"
16
+
17
+
18
+ def test_api_list_samples():
19
+ response = client.get("/api/v1/audit/samples")
20
+ assert response.status_code == 200
21
+ samples = response.json()
22
+ assert len(samples) >= 3
23
+
24
+
25
+ def test_api_evaluate_endpoint():
26
+ sample_res = client.get("/api/v1/audit/samples/compliant_clinical_samd")
27
+ assert sample_res.status_code == 200
28
+ sample_data = sample_res.json()
29
+
30
+ eval_res = client.post(
31
+ "/api/v1/audit/evaluate",
32
+ json={"specification_text": sample_data["raw_document_text"], "auditor_id": "test_ci_pipeline"},
33
+ )
34
+ assert eval_res.status_code == 200
35
+ result = eval_res.json()
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():
48
+ response = client.post(
49
+ "/api/v1/triage/feedback",
50
+ json={
51
+ "claim_id": "clm_test_99",
52
+ "auditor_id": "compliance_lead_01",
53
+ "verified_status": "IMPLEMENTED",
54
+ "verified_category": "HUMAN_OVERSIGHT",
55
+ "notes": "Verified operational override in production dashboard.",
56
+ },
57
+ )
58
+ assert response.status_code == 200
59
+ data = response.json()
60
+ assert data["status"] == "RECORDED"
61
+ assert "positive_label" in data["triplet"]
tests/test_end_to_end.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ End-to-End Pipeline Integration Tests.
3
+ """
4
+
5
+ from src.engine import ReguAIEngine
6
+ from src.core.config import SYNTHETIC_DIR
7
+
8
+
9
+ def test_full_pipeline_compliant():
10
+ engine = ReguAIEngine()
11
+ report = engine.evaluate_system(SYNTHETIC_DIR / "compliant_clinical_samd.json")
12
+
13
+ assert report.overall_conforms is True
14
+ assert report.conformity_score == 100.0
15
+ assert len(report.violations) == 0
16
+ assert len(report.claims_analyzed) >= 5
17
+ assert report.provenance.digital_signature.startswith("REGU-")
18
+
19
+ # Generate Markdown & JSON-LD
20
+ md = engine.report_generator.generate_markdown_report(report)
21
+ json_ld = engine.report_generator.generate_json_ld(report)
22
+
23
+ assert "CONFORMS (PASS)" in md
24
+ assert json_ld["regu:conformityStatus"] == "PASS"
25
+
26
+
27
+ def test_full_pipeline_non_compliant():
28
+ engine = ReguAIEngine()
29
+ report = engine.evaluate_system(SYNTHETIC_DIR / "non_compliant_hr_recruitment.json")
30
+
31
+ assert report.overall_conforms is False
32
+ assert len(report.violations) >= 2
33
+ assert report.conformity_score < 80.0
34
+
35
+ md = engine.report_generator.generate_markdown_report(report)
36
+ json_ld = engine.report_generator.generate_json_ld(report)
37
+
38
+ assert "NON-CONFORMANT (FAIL)" in md
39
+ assert json_ld["regu:conformityStatus"] == "FAIL"
tests/test_extraction.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for Regulatory Claim Extraction and Assertion Triage.
3
+ """
4
+
5
+ import pytest
6
+ from src.extraction.gliner_extractor import RegulatoryClaimExtractor
7
+ from src.extraction.assertion_triage import AssertionTriage
8
+ from src.core.models import AssertionStatus, EntityCategory
9
+
10
+
11
+ def test_assertion_triage_implemented():
12
+ triage = AssertionTriage()
13
+ text = "A clinician-in-the-loop human oversight mechanism is verified and actively operational."
14
+ status, conf, borderline = triage.analyze_assertion(text)
15
+ assert status == AssertionStatus.IMPLEMENTED
16
+ assert conf >= 0.80
17
+ assert borderline is False
18
+
19
+
20
+ def test_assertion_triage_absent():
21
+ triage = AssertionTriage()
22
+ text = "The system was deployed without human oversight or manual override capabilities."
23
+ status, conf, borderline = triage.analyze_assertion(text)
24
+ assert status == AssertionStatus.ABSENT
25
+ assert conf >= 0.75
26
+
27
+
28
+ def test_assertion_triage_planned():
29
+ triage = AssertionTriage()
30
+ text = "Disparate impact testing across demographic groups is planned for future release in Q4."
31
+ status, conf, borderline = triage.analyze_assertion(text)
32
+ assert status == AssertionStatus.PLANNED
33
+ assert conf >= 0.70
34
+
35
+
36
+ def test_claim_extractor_multiple_entities():
37
+ extractor = RegulatoryClaimExtractor()
38
+ doc = """
39
+ # MedAI Model Card
40
+ Continuous risk management system is maintained according to ISO 14971.
41
+ Training data provenance is documented across 50,000 clinical cases.
42
+ Bias examination and mitigation controls are fully implemented.
43
+ A clinician review human oversight mechanism is strictly operational.
44
+ Cybersecurity defenses against adversarial attack perturbations are deployed.
45
+ """
46
+ claims = extractor.extract_claims(doc)
47
+ categories = {c.category for c in claims}
48
+
49
+ assert EntityCategory.RISK_MANAGEMENT in categories
50
+ assert EntityCategory.DATA_GOVERNANCE in categories
51
+ assert EntityCategory.BIAS_MITIGATION in categories
52
+ assert EntityCategory.HUMAN_OVERSIGHT in categories
53
+ assert EntityCategory.CYBERSECURITY in categories
tests/test_provenance.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for Cryptographic Provenance Ledger and W3C PROV-O Graph generation.
3
+ """
4
+
5
+ from rdflib import Graph, URIRef, Literal, RDF
6
+ from src.core.models import SystemMetadata, SystemSpecification
7
+ from src.ledger.crypto import compute_sha256_text, compute_canonical_graph_sha256
8
+ from src.ledger.provenance import ProvenanceLedger
9
+
10
+
11
+ def test_canonical_graph_hash_deterministic():
12
+ g1 = Graph()
13
+ g2 = Graph()
14
+ s = URIRef("http://example.org/sys1")
15
+ p = URIRef("http://example.org/hasStatus")
16
+ o = Literal("Implemented")
17
+
18
+ # Add in different order if multiple triples
19
+ p2 = URIRef("http://example.org/domain")
20
+ o2 = Literal("Healthcare")
21
+
22
+ g1.add((s, p, o))
23
+ g1.add((s, p2, o2))
24
+
25
+ g2.add((s, p2, o2))
26
+ g2.add((s, p, o))
27
+
28
+ hash1 = compute_canonical_graph_sha256(g1)
29
+ hash2 = compute_canonical_graph_sha256(g2)
30
+
31
+ assert hash1 == hash2
32
+ assert len(hash1) == 64
33
+
34
+
35
+ def test_prov_o_generation():
36
+ ledger = ProvenanceLedger()
37
+ spec = SystemSpecification(
38
+ metadata=SystemMetadata(
39
+ system_id="sys-test-99",
40
+ name="Test Safety Model",
41
+ domain="Robotics",
42
+ intended_purpose="Collision avoidance",
43
+ ),
44
+ raw_document_text="Autonomous collision avoidance model.",
45
+ )
46
+ g = Graph()
47
+ g.add((URIRef("http://example.org/test"), RDF.type, URIRef("http://example.org/System")))
48
+
49
+ prov = ledger.generate_provenance(spec, g, conforms=True, violations_count=0)
50
+
51
+ assert prov.digital_signature.startswith("REGU-EU2024-1689-")
52
+ assert len(prov.input_doc_sha256) == 64
53
+ assert len(prov.graph_triples_sha256) == 64
54
+ assert "prov:wasGeneratedBy" in prov.prov_o_rdf
tests/test_shacl_engine.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for Deterministic SHACL Normative Reasoning Engine.
3
+ """
4
+
5
+ import json
6
+ from pathlib import Path
7
+ import pytest
8
+ from src.core.config import SYNTHETIC_DIR
9
+ from src.extraction.parser import SpecificationParser
10
+ from src.extraction.gliner_extractor import RegulatoryClaimExtractor
11
+ from src.ontology.builder import NormativeGraphBuilder
12
+ from src.reasoning.shacl_engine import DeterministicSHACLEngine
13
+
14
+
15
+ @pytest.fixture
16
+ def components():
17
+ return {
18
+ "parser": SpecificationParser(),
19
+ "extractor": RegulatoryClaimExtractor(),
20
+ "builder": NormativeGraphBuilder(),
21
+ "engine": DeterministicSHACLEngine(),
22
+ }
23
+
24
+
25
+ def test_compliant_samd_conforms(components):
26
+ samd_file = SYNTHETIC_DIR / "compliant_clinical_samd.json"
27
+ spec = components["parser"].parse_file(samd_file)
28
+ spec = components["extractor"].enrich_system_specification(spec)
29
+ graph = components["builder"].build_system_graph(spec)
30
+
31
+ conforms, violations, warnings, score = components["engine"].validate_system(graph)
32
+
33
+ assert conforms is True
34
+ assert len(violations) == 0
35
+ assert score == 100.0
36
+
37
+
38
+ def test_non_compliant_hr_fails(components):
39
+ hr_file = SYNTHETIC_DIR / "non_compliant_hr_recruitment.json"
40
+ spec = components["parser"].parse_file(hr_file)
41
+ spec = components["extractor"].enrich_system_specification(spec)
42
+ graph = components["builder"].build_system_graph(spec)
43
+
44
+ conforms, violations, warnings, score = components["engine"].validate_system(graph)
45
+
46
+ assert conforms is False
47
+ assert len(violations) >= 2
48
+
49
+ violation_articles = [v.regulatory_article for v in violations]
50
+ # Must flag Article 14 (Human Oversight missing) or Article 10(2)(f) (Bias mitigation missing)
51
+ assert any("14" in art for art in violation_articles)
52
+ assert any("10" in art for art in violation_articles)
53
+ assert score < 80.0