SHACL validation

rete shacl validates a .rete file against SHACL Core shapes. It is meant for release checks and CI gates: build the graph once, run the shape file against the default graph or a named graph, and fail the job if the validation report is not conformant.

rete build data.ttl -o data.rete
rete shacl data.rete --shapes shapes.ttl
rete shacl data.rete --shapes shapes.ttl --format json
rete shacl data.rete --shapes shapes.ttl --graph '<http://ex/releases/2026-06>'

The command exits with status 0 when the report conforms and non-zero when it finds at least one result. Shapes are read as Turtle. Data comes from the .rete file, so validation runs over exactly the graph you publish and query.

Validating a remote graph (lazy)

SHACL validation is node-by-node: a shape names its targets (a class, a node, the subjects/objects of a predicate), then checks each focus node's own property values. That maps onto routed range reads, so a remote .rete can be validated over HTTP without downloading it — each lookup faults only the tiles holding the target nodes and their values:

rete shacl-url https://host/data.rete --shapes shapes.ttl
# (fetched 38912 bytes in 7 range request(s); file is 1048576 bytes)

A targeted shape (sh:targetClass / targetNode / targetSubjectsOf / targetObjectsOf) fetches only its targets — the win grows with the file. The one exception is a target-less shape (one that implicitly targets every node) or a general inverse path, which must read the whole graph; ^predicate inverse paths are routed (they become a single (?, p, focus) lookup). shacl-url validates the default graph.

A minimal shape

@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://ex/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ex:PersonShape
  a sh:NodeShape ;
  sh:targetClass ex:Person ;
  sh:property [
    sh:path ex:email ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
    sh:datatype xsd:string ;
    sh:pattern "@" ;
    sh:message "Every person needs exactly one email string." ;
  ] .
rete shacl people.rete --shapes person-shapes.ttl

Text output is compact and human-oriented:

conforms: false

- focus: <http://ex/Alice>
  severity: http://www.w3.org/ns/shacl#Violation
  component: http://www.w3.org/ns/shacl#MinCountConstraintComponent
  path: <http://ex/email>
  shape: _:b1
  message: Every person needs exactly one email string.

Use --format json for automation and --format ttl for a Turtle validation report.

Supported SHACL surface

This implementation targets the stable W3C SHACL Core 2017 Recommendation. It does not try to implement SHACL-SPARQL, SHACL-AF, SHACL-JS, SHACL 1.2 drafts, or ShEx.

Supported targets:

FeatureStatus
sh:targetNodeyes
sh:targetClassyes, including rdfs:subClassOf closure in the data graph
sh:targetSubjectsOfyes
sh:targetObjectsOfyes
implicit class targets (rdfs:Class, owl:Class)yes
sh:deactivated, sh:severity, sh:messageyes

Supported property paths:

Path formStatus
predicate IRIyes
sh:inversePathyes
RDF list sequence pathsyes
sh:alternativePathyes
sh:zeroOrMorePathyes
sh:oneOrMorePathyes
sh:zeroOrOnePathyes

Supported constraint components:

Constraint familyComponents
Cardinalitysh:minCount, sh:maxCount
Value typesh:class, sh:datatype, sh:nodeKind
Value rangesh:minInclusive, sh:maxInclusive, sh:minExclusive, sh:maxExclusive
Strings and languagessh:minLength, sh:maxLength, sh:pattern, sh:flags, sh:languageIn, sh:uniqueLang
Property pairssh:equals, sh:disjoint, sh:lessThan, sh:lessThanOrEquals
Value setssh:hasValue, sh:in
Nested shapessh:node, sh:property
Logical constraintssh:not, sh:and, sh:or, sh:xone
Closed shapessh:closed, sh:ignoredProperties
Qualified valuessh:qualifiedValueShape, sh:qualifiedMinCount, sh:qualifiedMaxCount, sh:qualifiedValueShapesDisjoint

Current limits

  • Shape files must be Turtle.
  • SHACL-SPARQL constraints, custom functions, rules, and JavaScript extensions are out of scope for this command.
  • Recursive shape cycles are reported as validation results instead of being treated as fatal engine errors.
  • Rete files are immutable snapshots. If your build uses --materialize, SHACL validates the already-materialized graph; otherwise it validates asserted data only.

Core API

The CLI uses the reusable core API. validate_shacl is generic over a [GraphView] — the data graph can be an in-memory DataGraph (eager) or a ReteGraph that routes every lookup as a range read (lazy / remote):

use rete_core::{validate_shacl, DataGraph, ReteGraph, Rete, ShaclShapes};

let shapes = ShaclShapes::parse_turtle(&std::fs::read_to_string("shapes.ttl")?)?;

// Eager: whole graph in memory.
let rete = Rete::open(&std::fs::read("data.rete")?)?;
let report = validate_shacl(&DataGraph::from_rete(&rete, None), &shapes);

// Lazy: validate over a range reader (e.g. an HTTP backend) — fetches only the
// shapes' targets.
let rete = Rete::open_ranged_lazy(reader)?;
let report = validate_shacl(&ReteGraph::new(&rete), &shapes);

Pass Some("<graph-iri>") to DataGraph::from_rete to validate one named graph (the lazy ReteGraph validates the default graph).