OPDA Knowledge base
Physical — ontology

SHACL-AF rules

SHACL-AF rules

Per ODR-0017 §1a, OPDA emits 11 non-blocking quality rules as SHACL Advanced Features (SHACL-AF) sh:SPARQLRule constructions. Each rule materialises a derived predicate at sh:Info severity (one exception: PII rule at sh:Warning); consumers can route on the materialised predicate without the rule itself blocking conformance.

Rule-to-ODR citation graph

--- config: layout: elk elk: mergeEdges: false nodePlacementStrategy: BRANDES_KOEPF --- %%{init: {"theme": "base", "themeVariables": {"primaryColor": "#E1F5FE", "primaryTextColor": "#01579B", "primaryBorderColor": "#0277BD", "lineColor": "#37474F"}}}%% flowchart LR accTitle: SHACL-AF rule citation graph — 11 rules and the ODRs that cite each as the rule source accDescr: Each SHACL-AF rule materialises a derived predicate; this graph shows the rule, the ODR that names it as a citing site, the module it lives in, and the derived predicate it constructs. %% @prefix opda: %% @prefix sh: classDef rule fill:#E1F5FE,stroke:#0277BD,stroke-width:2px,color:#01579B classDef odr fill:#ECEFF1,stroke:#455A64,stroke-width:2px,color:#263238 classDef derived fill:#F8BBD9,stroke:#AD1457,stroke-width:2px,color:#880E4F classDef warning fill:#FFF9C4,stroke:#F9A825,stroke-width:2px,color:#F57F17 R1[opda:UPRNSuccessionRule
property]:::rule R2[opda:DeprecationChainRule
foundation]:::rule R3[opda:INSPIRESuccessionRule
property]:::rule R4[opda:PROVOClaimsRule
claim]:::rule R5[opda:IdentifierSuccessionRule
agent]:::rule R6[opda:CapacityAuthorityMatchRule
agent]:::rule R7[opda:LeaseTermSuccessionRule
transaction]:::rule R8[opda:MilestoneVarianceRule
transaction]:::rule R9[opda:VerificationActivitySuccessionRule
claim]:::rule R10[opda:PIIWithoutDPVCoAnnotationRule
foundation cross-cutting]:::warning O1[ODR-0005 §6a
UPRN as contingent identifier]:::odr O2[ODR-0011 §5a
SKOS deprecation lifecycle]:::odr O3[ODR-0015 §4a
INSPIRE Identifier succession]:::odr O4[ODR-0009 §Q7
claims provenance chain]:::odr O5[ODR-0006 §Q1
Person IC over name-change]:::odr O6[ODR-0006 §Q4
Capacity / authority split]:::odr O7[ODR-0007 §Q5
Lease term as interval]:::odr O8[ODR-0007 §Q6
Expected-vs-actual variance]:::odr O9[ODR-0009 §Q7
Re-verification chains]:::odr O10[ODR-0012 §Q5
DPV co-annotation discipline]:::odr D1[opda:hasUPRNSuccessionStatus]:::derived D2[opda:hasDeprecationStatus + opda:hasSuccessor]:::derived D3[opda:hasINSPIRESuccessionStatus]:::derived D4[opda:hasProvenanceChainStatus]:::derived D5[opda:hasIdentifierSuccessionEvent]:::derived D6[opda:hasCapacityAuthorityMatchStatus]:::derived D7[opda:hasLeaseTermSuccessionStatus]:::derived D8[opda:hasVarianceStatus + opda:hasVarianceDays]:::derived D9[opda:hasVerificationSuccessionStatus]:::derived D10[opda:hasPIIWithoutCoAnnotationFlag]:::derived R1 -->|dct:source| O1 R2 -->|dct:source| O2 R3 -->|dct:source| O3 R4 -->|dct:source| O4 R5 -->|dct:source| O5 R6 -->|dct:source| O6 R7 -->|dct:source| O7 R8 -->|dct:source| O8 R9 -->|dct:source| O9 R10 -->|dct:source| O10 R1 -->|sh:construct| D1 R2 -->|sh:construct| D2 R3 -->|sh:construct| D3 R4 -->|sh:construct| D4 R5 -->|sh:construct| D5 R6 -->|sh:construct| D6 R7 -->|sh:construct| D7 R8 -->|sh:construct| D8 R9 -->|sh:construct| D9 R10 -->|sh:construct| D10

Pattern

Each rule sits inside a sh:NodeShape that:

  1. sh:targetClasses the focus Kind (or owl:Class for cross-cutting rules)
  2. carries sh:severity sh:Info (or sh:Warning for PII rule)
  3. names an sh:rule blank-node sh:SPARQLRule that bears sh:construct with the SPARQL CONSTRUCT body

The CONSTRUCT body emits a derived predicate (opda:has<Something>Status or opda:has<Something>Event) into the inference graph. Consumer tooling reads the materialised predicate as the routing signal.

11 citing sites

Per ODR-0017 §1a, 11 ODRs cite the SHACL-AF pattern as their non-blocking-quality emission mechanism:

#RuleCiting ODRModule
1opda:UPRNSuccessionRuleODR-0005 §6aproperty
2opda:DeprecationChainRuleODR-0011 §5afoundation
3opda:INSPIRESuccessionRuleODR-0015 §4aproperty
4opda:PROVOClaimsRuleODR-0009 §Q7claim
5opda:IdentifierSuccessionRuleODR-0006 §Q1agent
6opda:CapacityAuthorityMatchRuleODR-0006 §Q4agent
7opda:LeaseTermSuccessionRuleODR-0007 §Q5transaction
8opda:MilestoneVarianceRuleODR-0007 §Q6transaction
9opda:VerificationActivitySuccessionRuleODR-0009 §Q7claim
10opda:PIIWithoutDPVCoAnnotationRuleODR-0012 §Q5foundation (cross-cutting)
11(placeholder for future emission)

opda:UPRNSuccessionRule

opda:UPRNSuccessionRule
    rdf:type sh:NodeShape ;
    rdfs:comment "UPRN succession rule (ODR-0005 §6a; SHACL-AF citing site #1). Materialises opda:hasUPRNSuccessionStatus on every Property with a UPRN: 'succession-tracked' when prov:wasDerivedFrom names a predecessor with a different UPRN; 'primary-uprn' otherwise. Per ODR-0017 §1a non-blocking-quality-rule pattern."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0005/section-6a> ;
    sh:rule _:b16e82da2b31c ;
    sh:severity sh:Info ;
    sh:targetClass opda:Property .

_:b16e82da2b31c
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nCONSTRUCT {\n  ?property opda:hasUPRNSuccessionStatus ?status .\n}\nWHERE {\n  ?property a opda:Property ;\n            opda:hasUPRN ?currentUPRN .\n  OPTIONAL { ?property prov:wasDerivedFrom ?predecessor .\n             ?predecessor opda:hasUPRN ?priorUPRN .\n             FILTER (?currentUPRN != ?priorUPRN) }\n  BIND (IF(BOUND(?priorUPRN), \"succession-tracked\", \"primary-uprn\") AS ?status)\n}" .

Derives

opda:hasUPRNSuccessionStatus (“succession-tracked” | “primary-uprn”)

Citing site

ODR-0005 §6a — UPRN as contingent identifier

Severity

sh:Info

Source ODR + ADR

opda:DeprecationChainRule

opda:DeprecationChainRule
    rdf:type sh:NodeShape ;
    rdfs:comment "Meta-rule per ODR-0011 §5a: materialises the deprecation chain for any SKOS Concept marked owl:deprecated true. Severity sh:Info when dct:isReplacedBy is present; the Three-tier severity decision table in ODR-0017 §2a notes that deprecation-without-successor escalates to sh:Warning (handled by the materialised opda:hasDeprecationStatus value rather than a separate shape)."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0011/section-5a> ;
    sh:rule _:be6b6213de607 ;
    sh:severity sh:Info ;
    sh:targetClass skos:Concept .

_:be6b6213de607
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX dct: <http://purl.org/dc/terms/>\nPREFIX owl: <http://www.w3.org/2002/07/owl#>\nPREFIX skos: <http://www.w3.org/2004/02/skos/core#>\nCONSTRUCT {\n  ?concept opda:hasDeprecationStatus ?status .\n  ?concept opda:hasSuccessor ?successor .\n}\nWHERE {\n  ?concept a skos:Concept ;\n           owl:deprecated true .\n  OPTIONAL { ?concept dct:isReplacedBy ?successor }\n  BIND (IF(BOUND(?successor), \"with-succession\", \"without-succession\") AS ?status)\n}" .

Derives

opda:hasDeprecationStatus (“with-succession” | “without-succession”), opda:hasSuccessor

Citing site

ODR-0011 §5a — SKOS deprecation lifecycle

Severity

sh:Info (decision table in ODR-0017 §2a notes the materialised “without-succession” status is the escalation hook; the rule itself stays Info)

Source ODR + ADR

opda:INSPIRESuccessionRule

opda:INSPIRESuccessionRule
    rdf:type sh:NodeShape ;
    rdfs:comment "INSPIRE Identifier / OS AddressBase succession rule (ODR-0015 §4a; SHACL-AF citing site #3). Materialises opda:hasINSPIRESuccessionStatus on inspire-variant Address instances. Per ODR-0017 §1a."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0015/section-4a> ;
    sh:rule _:becbeff0baa17 ;
    sh:severity sh:Info ;
    sh:targetClass opda:Address .

_:becbeff0baa17
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nCONSTRUCT {\n  ?address opda:hasINSPIRESuccessionStatus ?status .\n}\nWHERE {\n  ?address a opda:Address ;\n           opda:addressVariant \"inspire\" .\n  OPTIONAL { ?address prov:wasDerivedFrom ?prior .\n             ?prior opda:addressVariant \"inspire\" }\n  BIND (IF(BOUND(?prior), \"inspire-re-issued\", \"inspire-primary\") AS ?status)\n}" .

Derives

opda:hasINSPIRESuccessionStatus (“inspire-re-issued” | “inspire-primary”)

Citing site

ODR-0015 §4a — INSPIRE Identifier succession

Severity

sh:Info

Source ODR + ADR

opda:PROVOClaimsRule

opda:PROVOClaimsRule
    rdf:type sh:NodeShape ;
    rdfs:comment "PROV-O Claims/Evidence rule (ODR-0009 §Q7; SHACL-AF citing site #4). Materialises opda:hasProvenanceChainStatus to surface Claims with absent or partial PROV-O chains. Per ODR-0017 §1a; complements the UnprovenancedClaimShape (which is a Violation-tier shape; this is informative)."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0009/section-Q7> ;
    sh:rule _:bb11b45f9d7c0 ;
    sh:severity sh:Info ;
    sh:targetClass opda:Claim .

_:bb11b45f9d7c0
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nCONSTRUCT {\n  ?claim opda:hasProvenanceChainStatus ?status .\n}\nWHERE {\n  ?claim a opda:Claim .\n  OPTIONAL { ?claim prov:wasDerivedFrom ?source }\n  OPTIONAL { ?claim prov:wasGeneratedBy ?activity }\n  BIND (IF(BOUND(?source) || BOUND(?activity), \"chain-present\", \"chain-absent\") AS ?status)\n}" .

Derives

opda:hasProvenanceChainStatus (“chain-present” | “chain-absent”)

Citing site

ODR-0009 §Q7 — claims provenance chain

Severity

sh:Info

Source ODR + ADR

opda:IdentifierSuccessionRule

opda:IdentifierSuccessionRule
    rdf:type sh:NodeShape ;
    rdfs:comment "Person identifier-succession rule (ODR-0006 §Q1; SHACL-AF citing site #5). Materialises opda:hasIdentifierSuccessionEvent for downstream audit when a NameChangeEvent (or subclass: passport-renewal, NI-renumbering) names the Person via prov:wasAssociatedWith. Per ODR-0017 §1a."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0006/section-Q1> ;
    sh:rule _:b04ddc2ae8a10 ;
    sh:severity sh:Info ;
    sh:targetClass opda:Person .

_:b04ddc2ae8a10
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nCONSTRUCT {\n  ?person opda:hasIdentifierSuccessionEvent ?event .\n}\nWHERE {\n  ?person a opda:Person .\n  ?event a opda:NameChangeEvent ;\n         prov:wasAssociatedWith ?person .\n}" .

Derives

opda:hasIdentifierSuccessionEvent (IRI of the succession event)

Citing site

ODR-0006 §Q1 — Person IC over name-change

Severity

sh:Info

Source ODR + ADR

opda:CapacityAuthorityMatchRule

opda:CapacityAuthorityMatchRule
    rdf:type sh:NodeShape ;
    rdfs:comment "Capacity-authority match rule (ODR-0006 §Q4; SHACL-AF citing site #6). Materialises opda:hasCapacityAuthorityMatchStatus to surface Persons declaring a capacity (e.g. 'Director', 'Trustee') without an evidenced authority triple. Status value 'unevidenced-capacity' is a hook for downstream-tooling escalation per ODR-0017 §2a without-substantive-succession discipline."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0006/section-Q4> ;
    sh:rule _:bcd856a2c693b ;
    sh:severity sh:Info ;
    sh:targetClass opda:Person .

_:bcd856a2c693b
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nCONSTRUCT {\n  ?agent opda:hasCapacityAuthorityMatchStatus ?status .\n}\nWHERE {\n  ?agent opda:hasAssertedCapacity ?cap .\n  OPTIONAL { ?agent opda:hasEvidencedAuthority ?auth }\n  BIND (IF(BOUND(?auth), \"matched\", \"unevidenced-capacity\") AS ?status)\n}" .

Derives

opda:hasCapacityAuthorityMatchStatus (“matched” | “unevidenced-capacity”)

Citing site

ODR-0006 §Q4 — Capacity / authority split

Severity

sh:Info

Source ODR + ADR

opda:LeaseTermSuccessionRule

opda:LeaseTermSuccessionRule
    rdf:type sh:NodeShape ;
    rdfs:comment "LeaseTerm succession rule (ODR-0007 §Q5; SHACL-AF citing site #7). Materialises opda:hasLeaseTermSuccessionStatus: extended-from-predecessor when the term carries prov:wasDerivedFrom to another LeaseTerm; primary-term otherwise. Per ODR-0017 §1a + LeaseExtensionEvent (ODR-0005 §3b)."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0007/section-Q5> ;
    sh:rule _:b6dbc2616d1c0 ;
    sh:severity sh:Info ;
    sh:targetClass opda:LeaseTerm .

_:b6dbc2616d1c0
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nPREFIX time: <http://www.w3.org/2006/time#>\nCONSTRUCT {\n  ?term opda:hasLeaseTermSuccessionStatus ?status .\n}\nWHERE {\n  ?term a opda:LeaseTerm .\n  OPTIONAL { ?term prov:wasDerivedFrom ?prior .\n             ?prior a opda:LeaseTerm }\n  BIND (IF(BOUND(?prior), \"extended-from-predecessor\", \"primary-term\") AS ?status)\n}" .

Derives

opda:hasLeaseTermSuccessionStatus (“extended-from-predecessor” | “primary-term”)

Citing site

ODR-0007 §Q5 — Lease term as interval

Severity

sh:Info

Source ODR + ADR

opda:MilestoneVarianceRule

opda:MilestoneVarianceRule
    rdf:type sh:NodeShape ;
    rdfs:comment "Milestone variance rule (ODR-0007 §Q6; SHACL-AF citing site #8). Dynamic severity per ODR-0007 §Q6: less-than-14-day slip surfaces as 'info-flagged'; otherwise 'warning-flagged'. The materialised opda:hasVarianceStatus value is the consumer's escalation hook; the shape itself stays sh:Info per ODR-0017 §1a (the rule is informative; consumer tooling interprets the variance category)."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0007/section-Q6> ;
    sh:rule _:b55cf070b367d ;
    sh:severity sh:Info ;
    sh:targetClass opda:Milestone .

_:b55cf070b367d
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\nCONSTRUCT {\n  ?milestone opda:hasVarianceStatus ?varianceCategory .\n  ?milestone opda:hasVarianceDays ?days .\n}\nWHERE {\n  ?milestone a opda:Milestone ;\n             opda:occurredAtTime ?actual ;\n             opda:plannedAtTime ?planned .\n  BIND (xsd:integer((?actual - ?planned) / xsd:dayTimeDuration(\"P1D\")) AS ?days)\n  BIND (IF(?days < 14, \"info-flagged\", \"warning-flagged\") AS ?varianceCategory)\n}" .

Derives

opda:hasVarianceStatus (“info-flagged” | “warning-flagged”), opda:hasVarianceDays (integer)

Citing site

ODR-0007 §Q6 — Expected-vs-actual variance

Severity

sh:Info (the materialised status carries the variance category)

Source ODR + ADR

opda:VerificationActivitySuccessionRule

opda:VerificationActivitySuccessionRule
    rdf:type sh:NodeShape ;
    rdfs:comment "VerificationActivity succession rule (ODR-0009 §Q7; SHACL-AF citing site #9). Materialises opda:hasVerificationSuccessionStatus to track re-verification chains via prov:wasInformedBy. Per ODR-0017 §1a."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0009/section-Q7> ;
    sh:rule _:b28ba9d05939d ;
    sh:severity sh:Info ;
    sh:targetClass opda:VerificationActivity .

_:b28ba9d05939d
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nCONSTRUCT {\n  ?activity opda:hasVerificationSuccessionStatus ?status .\n}\nWHERE {\n  ?activity a opda:VerificationActivity .\n  OPTIONAL { ?activity prov:wasInformedBy ?prior .\n             ?prior a opda:VerificationActivity }\n  BIND (IF(BOUND(?prior), \"re-verified\", \"initial-verification\") AS ?status)\n}" .

Derives

opda:hasVerificationSuccessionStatus (“re-verified” | “initial-verification”)

Citing site

ODR-0009 §Q7 — Re-verification chains

Severity

sh:Info

Source ODR + ADR

opda:PIIWithoutDPVCoAnnotationRule

opda:PIIWithoutDPVCoAnnotationRule
    rdf:type sh:NodeShape ;
    rdfs:comment "Meta-rule: any class marked opda:isPIIBearing true that lacks a dpv-pd:hasPersonalDataCategory annotation in the annotation graph is flagged as a PII-without-co-annotation breach. Severity sh:Warning per ADR-0012 §SHACL-AF rule emission (silent PII leakage is high-impact even though the rule is SHACL-AF-pattern-shaped)."@en ;
    dct:source <https://opda.org.uk/pdtf/harness/odr/ODR-0012/section-Q5> ;
    sh:rule _:b3f168211e733 ;
    sh:severity sh:Warning ;
    sh:targetClass owl:Class .

_:b3f168211e733
    rdf:type sh:SPARQLRule ;
    sh:construct "PREFIX opda: <https://opda.org.uk/pdtf/>\nPREFIX dpv-pd: <https://w3id.org/dpv/pd#>\nPREFIX owl: <http://www.w3.org/2002/07/owl#>\nCONSTRUCT {\n  ?class opda:hasPIIWithoutCoAnnotationFlag true .\n}\nWHERE {\n  ?class a owl:Class ;\n         opda:isPIIBearing true .\n  FILTER NOT EXISTS {\n    ?class dpv-pd:hasPersonalDataCategory ?category .\n  }\n}" .

Derives

opda:hasPIIWithoutCoAnnotationFlag (boolean true)

Citing site

ODR-0012 §Q5 — DPV co-annotation discipline

Severity

sh:Warning (explicit override above the sh:Info default — silent PII leakage is high-impact)

Source ODR + ADR

Comments

Loading comments…