Assessing AI Certification Portability with SHACL Governance Rules¶
This notebook demonstrates the approach from the paper "Assessing AI Certification Validity via Knowledge Graphs for Use Case Similarity" but using the SHACL rules instead of star-graph similarity.
Scenario: An AI hiring model is developed and certified in New York, US under NYC Local Law 144. The organisation now wants to deploy the same model in the EU (GDPR Art. 22 applies).
Question: Is the original NY certification still valid in the EU?
The governance logic is encoded directly as SHACL sh:SPARQLRule entries. The rules fire during SHACLEngine.infer() and derive, for each AI system:
applicableFramework— which regulatory framework governs itrequiredControl— which compliance control it must implement
When the derived requirements differ across jurisdictions the certification gap is explicit and auditable.
1. Write SHACL governance rules and load data¶
Four sh:SPARQLRule entries target nexus:AiSystem instances.
Each rule reads the system's isUsedWithinLocality value and derives the applicable framework and required control in a forward-chaining pass.
from pathlib import Path
from ai_atlas_nexus import AIAtlasNexus
SAMPLE_DATA_DIR = Path("sample_data")
shapes_dir = SAMPLE_DATA_DIR / "shapes"
shapes_dir.mkdir(exist_ok=True)
# Four sh:SPARQLRule entries: locality -> applicable framework + required control
ttl_lines = ['@prefix sh: <http://www.w3.org/ns/shacl#> .', '@prefix nexus: <https://w3id.org/ai-atlas-nexus/> .', '', 'nexus:CertificationGovernanceShape a sh:NodeShape ;', ' sh:targetClass nexus:AiSystem ;', '', ' sh:rule [ a sh:SPARQLRule ; sh:construct """', 'PREFIX nexus: <https://w3id.org/ai-atlas-nexus/>', 'CONSTRUCT { ?this nexus:applicableFramework "nyc-local-law-144" }', 'WHERE { ?this nexus:isUsedWithinLocality "hiring-usecase-locality-ny-ny-usa" . }', '""" ] ;', '', ' sh:rule [ a sh:SPARQLRule ; sh:construct """', 'PREFIX nexus: <https://w3id.org/ai-atlas-nexus/>', 'CONSTRUCT { ?this nexus:applicableFramework "gdpr-art-22" }', 'WHERE { ?this nexus:isUsedWithinLocality "hiring-usecase-locality-dublin-ie-eu" . }', '""" ] ;', '', ' sh:rule [ a sh:SPARQLRule ; sh:construct """', 'PREFIX nexus: <https://w3id.org/ai-atlas-nexus/>', 'CONSTRUCT { ?this nexus:requiredControl "hiring-control-audit-ai-ny" }', 'WHERE { ?this nexus:isUsedWithinLocality "hiring-usecase-locality-ny-ny-usa" . }', '""" ] ;', '', ' sh:rule [ a sh:SPARQLRule ; sh:construct """', 'PREFIX nexus: <https://w3id.org/ai-atlas-nexus/>', 'CONSTRUCT { ?this nexus:requiredControl "hiring-control-gdpr-explanation-eu" }', 'WHERE { ?this nexus:isUsedWithinLocality "hiring-usecase-locality-dublin-ie-eu" . }', '""" ] .']
(shapes_dir / "certification_governance.ttl").write_text("\n".join(ttl_lines))
nexus = AIAtlasNexus(base_dir=str(SAMPLE_DATA_DIR))
engine = nexus.get_shacl_engine()
print(f"Shapes loaded: {engine.has_shapes() if engine else False}")
[2026-05-29 15:10:39:412] - INFO - AIAtlasNexus - Created AIAtlasNexus instance. Base_dir: sample_data
Shapes loaded: True
2. The two hiring systems¶
Both systems share the same five risks (lack of transparency, over/under-reliance, discriminatory actions, unexplainable output, unrepresentative data). The only structural difference is isUsedWithinLocality.
from ai_atlas_nexus.blocks.graph_explorer import PyoxigraphExplorer
from ai_atlas_nexus.blocks.graph_explorer.query_builder import NEXUS_URI
ox = PyoxigraphExplorer(nexus._ontology)
hiring_ny = ox.get_by_id(None, "hiring-usecase-ny")
hiring_eu = ox.get_by_id(None, "hiring-usecase-eu")
for label, sys in [("NY", hiring_ny), ("EU", hiring_eu)]:
print(f"{label}: {sys.name}")
print(f" jurisdiction : {sys.isUsedWithinLocality}")
print(f" shared risks : {len(sys.hasRelatedRisk or [])} risks")
NY: Algorithmic Hiring (New York, US) jurisdiction : ['hiring-usecase-locality-ny-ny-usa'] shared risks : 5 risks EU: Algorithmic Hiring (EU) jurisdiction : ['hiring-usecase-locality-dublin-ie-eu'] shared risks : 5 risks
3. Apply governance rules¶
SHACLEngine.infer() executes each sh:SPARQLRule CONSTRUCT query against the pyoxigraph store and returns a {subject_uri: {predicate: value}} map of newly derived triples.
The comparison table makes the compliance divergence explicit.
derived = engine.infer(ox._store)
ny_uri = f"{NEXUS_URI}hiring-usecase-ny"
eu_uri = f"{NEXUS_URI}hiring-usecase-eu"
ny_gov = derived.get(ny_uri, {})
eu_gov = derived.get(eu_uri, {})
print("Governance requirements derived by SHACL rules\n")
print(f"{'Attribute':<26} {'NY deployment':<30} {'EU deployment'}")
print("-" * 80)
for attr in ("applicableFramework", "requiredControl"):
print(f"{attr:<26} {ny_gov.get(attr, '—'):<30} {eu_gov.get(attr, '—')}")
Governance requirements derived by SHACL rules Attribute NY deployment EU deployment -------------------------------------------------------------------------------- applicableFramework nyc-local-law-144 gdpr-art-22 requiredControl hiring-control-audit-ai-ny hiring-control-gdpr-explanation-eu
4. Cross-deployment scenario¶
What governance requirements would apply if the NY-certified model were re-deployed in the EU?
We add the EU locality triple to the NY system's graph and re-run inference. The EU rules now fire for the NY system, revealing the control mismatch.
import pyoxigraph
# Simulate the NY system being deployed to EU: add EU locality to its graph
sim_store = pyoxigraph.Store()
for q in ox._store:
sim_store.add(q)
sim_store.add(pyoxigraph.Quad(
pyoxigraph.NamedNode(f"{NEXUS_URI}hiring-usecase-ny"),
pyoxigraph.NamedNode(f"{NEXUS_URI}isUsedWithinLocality"),
pyoxigraph.Literal("hiring-usecase-locality-dublin-ie-eu"),
pyoxigraph.DefaultGraph(),
))
sim_derived = engine.infer(sim_store)
ny_cross = sim_derived.get(ny_uri, {})
print("NY system re-evaluated under EU jurisdiction\n")
print(f" applicableFramework : {ny_cross.get('applicableFramework')}")
print(f" requiredControl : {ny_cross.get('requiredControl')}")
print()
print("Original NY certification required : hiring-control-audit-ai-ny")
print("EU jurisdiction now requires : hiring-control-gdpr-explanation-eu")
print("=> Control mismatch: certification must be re-evaluated")
NY system re-evaluated under EU jurisdiction applicableFramework : gdpr-art-22 requiredControl : hiring-control-gdpr-explanation-eu Original NY certification required : hiring-control-audit-ai-ny EU jurisdiction now requires : hiring-control-gdpr-explanation-eu => Control mismatch: certification must be re-evaluated
5. Validate data against shape constraints¶
The same SHACLEngine can run pyshacl validation. The current shapes carry only sh:SPARQLRule entries (no sh:property constraints), so the existing data conforms. Adding sh:property constraints per jurisdiction would turn policy rules into enforceable checks.
report = engine.validate(ox._store)
print(f"Data conforms to shape constraints: {report.conforms}")
print()
print(report.results_text[:300])
Data conforms to shape constraints: True Validation Report Conforms: True
Conclusion¶
| NY deployment | EU deployment | |
|---|---|---|
| Applicable framework | NYC Local Law 144 | GDPR Art. 22 |
| Required control | AuditAI (bias audit) | Provide explanation |
| Shared risks | 5 | 5 |
| Certification portable? | Original scope | Re-evaluation required |
Both deployments share the same five identified risks — matching the finding in hiring_usecase_comparison.ipynb. But the governance rules surface a control divergence that the star-graph similarity score (~0.92) signals as a review case.
The SHACL approach makes the governance logic explicit and portable: the same .ttl rule file can be applied to any AI system in the knowledge graph, automatically deriving compliance obligations per jurisdiction without manual inspection.
Recommendation: the original NY certification should be re-evaluated before EU deployment — the system must implement hiring-control-gdpr-explanation-eu (GDPR Art. 22 explanation capability) in addition to its existing bias audit controls.