SHACL: Shapes Constraint Language [For SHACL where shapes determine path-following. Both sh:property and sh:predicate have been removed. Doesn't cover constructs that don't affect validation.] PREAMBLE (Informative) SHACL is designed to determine whether an RDF graph meets some conditions. These conditions are grouped into shapes, which check that particular RDF terms each meet the constraints of the shape. Shapes are themselves expressed as triples in an RDF graph, called a shapes graph. NAMESPACES (Normative) Throughout this document, IRIs are written in Turtle syntax, using the following mapping of prefixes to namespaces: Prefix Namespace rdf http://www.w3.org/1999/02/22-rdf-syntax-ns# rdfs http://www.w3.org/2000/01/rdf-schema# sh http://www.w3.org/ns/shacl# xsd http://www.w3.org/2001/XMLSchema# ex http://example.com/ns# BASIC TERMINOLOGY (Normative) Terms that are linked to portions of RDF 1.1 Concepts and Abstract Syntax are used in SHACL as defined there. Terms that are linked to portions of SPARQL 1.1 Query Language are used in SHACL as defined there. A single linkage is sufficient to provide a definition for all occurences of a particular term in this document. In this ASCII version of the document links to other documents are enclosed in *'s and SHACL terms being defined are enclosed in **'s. The definitions of some SHACL terms are dispersed throughout the document. For these terms each portion of the definition is marked with **'s. Path: A **path** in an *RDF graph* from *RDF term* n to RDF term m is a sequence of *RDF triples* in the graph such that the *subject* of the first RDF triple is n, the *object* of the last RDF triple is m, and the object of each RDF triple except the last is the subject of the next. Property: A **property** is an *IRI*. Value: An RDF term n has **value** v for property p in an RDF graph G if there is an RDF triple in G with subject n, predicate p, and object v. An RDF term n has **value** v for *SPARQL property path expression* p in an RDF graph G if there is a solution mapping in the result of the SPARQL query SELECT ?s ?o WHERE { ?s p' ?o } on G that binds ?s to n and ?o to v, where p' is SPARQL surface syntax for p. SHACL List: A **SHACL list** in an RDF graph G is an IRI or a *blank node* that is either rdf:nil (provided that rdf:nil has no value for either rdf:first or rdf:rest in G), or has exactly one value for rdf:first in G and exactly one value for rdf:rest in G that is also a SHACL list in the graph and there is no non-empty path in G from the list back to itself where the predicates of the RDF triples in the path are each rdf:rest. The **members** of any SHACL list except rdf:nil in an RDF graph G consist of its value for rdf:first in G followed by the members in G of its value for rdf:rest in G. The SHACL list rdf:nil has no **members** in any RDF graph. SHACL Type and Expected Type: An RDF term n is a **SHACL instance** of an RDF term m in an RDF graph G if there is a path in G from n to m where the predicate of the first RDF triple in the path is rdf:type and the predicates of any other RDF triples in the path are rdfs:subClassOf. An RDF term n has an RDF term m as **SHACL type** in an RDF graph G if n is a SHACL instance of m in G. RDF terms have zero or more **expected types** in an RDF graph. Each expected type for an RDF term in an RDF graph G is the result of the RDF term being the object of an RDF triple in G with a particular predicate as described in this document. Data Graph: A **data graph** is any RDF graph. SHACL PROPERTY PATHS (Normative) A blank node is an **ill-formed property path** in an RDF graph G if it has a value for more than one of rdf:first, sh:alternativePath, sh:inversePath, sh:zeroOrMorePath, sh:oneOrMorePath, or sh:zeroOrOnePath in G. A blank node is an **ill-formed property path** in an RDF graph G if there is a path in G from the node back to itself where the sequence of predicates of the RDF triples in the path matches the regular expression ( ( rdf:rest* rdf:first ) | sh:alternativePath ( rdf:rest* rdf:first ) | sh:inversePath | sh:zeroOrMorePath | sh:oneOrMorePath | sh:zeroOrOnePath ) + An RDF term is an **ill-formed property path** in an RDF graph if it does not satisfy exactly one of the conditions in the mapping below. If an RDF term is not an ill-formed property path in an RDF graph then it is a **SHACL property path** in the graph. The **path mapping** in an RDF graph G of a RDF term p that is a SHACL property path in G, path(p,S), is a *SPARQL property path expression* defined as follows: 1/ If p is an IRI then path(p,S) is PredicatePath(p). 2/ If p is a blank node that is a SHACL list in G that has at least two members in G and none of these members are ill-formed property paths in G then path(p,S) is SequencePath(path(v1,S) ... path(vn,S)) where vi are the members of p in G, in order. 3/ If p is a blank node that has exactly one value for sh:alternativePath in G and that value is a SHACL list in G that has at least two members in G and none of the members in G are ill-formed property paths in G then path(p,S) is AlternativePath(path(v1,S) ... path(vn,S)) where vi are the members of the list in G, in order. 4/ If p is a blank node that has exactly one value v for sh:inversePath in G and v is not an ill-formed property path in G then path(p,S) is InversePath(path(v,S)). 5/ If p is a blank node that has exactly one value v for sh:zeroOrMorePath in G and v is not an ill-formed property path in G then path(p,S) is ZeroOrMorePath(path(v,S)). 6/ If p is a blank node that has exactly one value v for sh:oneOrMorePath in G and v is not an ill-formed property path in G then path(p,S) is OneOrMorePath(path(v,S)). 7/ If p is a blank node that has exactly one value v for sh:zeroOrOnePath in G and v is not an ill-formed property path in G then path(p,S) is ZeroOrOnePath(path(v,S)). SHACL property paths in same or different RDF graphs are **equivalent** if their path mappings in their graphs are the same. VALIDATION RESULTS AND VALIDATION REPORTS (Normative) A **results graph** is an RDF graph G where every *node* in G that has SHACL type sh:ValidationResult in G meets the following conditions - It has sh:ValidationResult as a value for rdf:type in G - It has exactly one value for sh:focusNode in G - It has at most one value for sh:valueNode in G - It has at most one value for sh:resultPath in G and this value if present is a SHACL property path in G - It has exactly one value for sh:sourceShape in G - It has exactly one value for sh:sourceConstraintComponent in G - It has exactly one value for sh:resultSeverity in G - Each of its values for sh:resultMessage in G is a language-tagged literal and each has a different language tag. - Each of its values for sh:detail in G has SHACL type sh:ValidationResult. - Each of its values for p in G where p is a list-taking parameter is a SHACL list in G. A **validation result** from RDF term f, optional RDF term v, data graph D, constraint c with type C, and shape s in shapes graph S is a node in a results graph G that meets the following conditions - It has sh:ValidationResult as a value for rdf:type in G - Its sole value for sh:focusNode in G is f - Its sole value for sh:valueNode in G is v if v is present, otherwise it has no value for sh:valueNode in G - Its sole value for sh:resultPath in G is a SHACL property path in G that is equivalent to the SHACL property path value of s for sh:path in S if there is one, otherwise it has no value for sh:resultPath in G - Its sole value for sh:sourceShape in G is s - Its sole value for sh:sourceConstraintComponent in G is C - Its sole value for sh:resultSeverity in G is the severity of s in S - Its values, if any, for p in G with p a non-list-taking parameter of C and X = { x | is a parameter value of c } are the elements of X - Its values, if any, for p in G with p a list-taking parameter of C and X = { x | is a parameter value of c } contain for each member of X a SHACL list in G whose elements in G are the elements of X in S A **results structure** is a results graph and a set of nodes from the graph each of which have SHACL type sh:ValidationResult in the graph. The set of nodes is called the **top-level validation results** of the results structure. A results structure **contains** a top-level validation result from f,v,D,c,s,S if its graph contains a node that is a validation result from f,v,D,c,s,S and that node is an element of its top-level validation results. A **validation report** V for a results structure R is any results graph containing at least the triples of R plus a new blank node n with sh:ValidationReport as a value for rdf:type in V; "false"^^xsd:boolean as sole value for sh:conforms in V if there R has any top-level validation results in R, and "true"^^xsd:boolean otherwise; and whose set of values for sh:result in V is the set of top-level validation results in R. The **combination** of a multiset of results structures is the union of the graphs of the results structures and the union of their sets of top-level validation results, provided that this is a results structure. Note (Informative): Combination does not use merging so that, for example, validation results and SHACL property paths do not have to be replicated. Care does need to be taken when different results structures share blank nodes so that invalid validation results or SHACL property paths do not result. Note (Informative): Validation reports are only required to contain top-level validation results from results graphs, i.e., the results for validating elements of the complete targets of a shape against the shape. Implementations are encouraged to provide interfaces that also retain other validation results and to use the property sh:detail to link from a validation result for a shape to validation results from subsidiary conformance checking such as is required for constraints of type sh:ShapeConstraintComponent. SHACL SHAPES (Normative) Shapes and shapes graphs: The **shapes** of an RDF graph are those nodes in the graph with SHACL or expected type sh:Shape in the graph. A **shapes graph** is an RDF graph containing no ill-formed shapes in the graph. **Ill-formed shapes** are described in the rest of this document. If s is a shape in an RDF graph with more than one value for sh:severity in the graph or a a value that is not sh:Info, sh:Warning, or sh:Violation then s is an **ill-formed shape** in the graph. The **severity** of a SHACL shape in a shapes graph S is its value for sh:severity in S, if present, otherwise sh:Violation Constraint components and constraints: A **constraint component** is one of the IRIs so-described in the rest of this document. Each constraint component has one or more **mandatory parameters**, each of which is a property. Each constraint component has zero or more **optional parameters**, each of which is a property. The **parameters** of a constraint component are its mandatory parameters plus its optional parameters. Some parameters of a constraint component are **list-taking parameters**. A parameter that forces expected type sh:Shape on objects of triples with with it as predicate or members of such objects is a **shape-inducing parameter**. For a constraint component C with mandatory parameters p1, ..., pn a shape s in a shapes graph S has a **constraint** of type C with **mandatory parameter values** , ..., in S when s has vi as a value for pi in S. If s in S has a constraint of type C in S then the **optional parameter values** of the constraint in S are all the where oi is an optional parameter of C and s has vi as a value for oi in S. The **parameter values** of a constraint are its manadatory parameter values and its optional parameter values. Recursive Shapes and Recursive Shapes Graphs: A shape s1 in an RDF graph **refers** to shape s2 in the graph if it has s2 as value for some non-list-taking, shape-inducing parameter of some constraint component or s2 as a member of the value for some list-taking, shape-inducing parameter of some constraint component. A shape in an RDF graph is **recursive** in the graph if it is related to itself by the transitive closure of the refers relationship in the graph. Shapes graphs that contain a shape recursive in the graph are **recursive**. Targets: If s is a shape in an RDF graph with a value for sh:targetNode in the graph that is not an IRI or *literal* then s is an **ill-formed shape** in the graph. If s is a shape in a shapes graph S and s has value t for sh:targetNode in S then { t } is a **target** from any data graph for s in S. If s is a shape in an RDF graph with a value for sh:targetClass in the graph that is not an IRI then s is an **ill-formed shape** in the graph. If s is a shape in a shapes graph S and s has value c for sh:targetClass in S then the set of SHACL instances of c in a data graph D is a **target** from D for s in S. If s is a shape in an RDF graph and s is also a SHACL instance of rdfs:Class in the graph and s is not an IRI then s is an **ill-formed shape** in the graph. If s is a shape in a shapes graph S and s is also a SHACL instance of rdfs:Class in S then the set of SHACL instances of s in a data graph D is a **target** from D for s in S. A shape in an RDF graph with a value for sh:targetSubjectsOf in the graph that is not an IRI is an **ill-formed** shape in the graph. If s is a shape in a shapes graph S and s has value p for sh:targetSubjectsOf in S then the set of nodes in a data graph D that are subjects of RDF triples in D with predicate p is a **target** from D for s in S. A shape in an RDF graph with a value for sh:targetObjectsOf in the graph that is not an IRI is an **ill-formed shape** in the graph. If s is a shape in a shapes graph S and s has value p for sh:targetObjectsOf in S then the set of nodes in a data graph D that are objects of RDF triples in D with predicate p is a **target** from D for s in S. The **complete targets** from a data graph for a shape in a shapes graph is the union of the targets from the data graph for the shape in the shapes graph defined above. Value Nodes: A shape in an RDF graph with a value for sh:path in the graph that is an ill-formed property path in the graph is an **ill-formed shape** in the graph. A shape in an RDF graph with more than one value for sh:path in the graph is an **ill-formed shape** in the graph. Given f an RDF term, D a data graph, and s a shape in S a shapes graph the **value nodes** of f with D for s in S is the set containing the values of f for path(p,S) in D if s has p as value for sh:path in S, or just f if s has no value for sh:path in S. VALIDATION AND CONFORMANCE CHECKING (Normative) Validation is the main relationship defined in SHACL, usually producing a validation report containing the results of the validation. There are generally many different possible validation reports for a particular validation. Conformance checking is a simplified version of validation, usually producing a boolean result. Validation and conformance checking can result in a failure. For example, a particular SHACL processor might allow recursive shapes but report a failure if it detects a loop. Failure can also be reported due to resource exhaustion. Failures are signalled through implementation-specific channels. Given G a data graph and S a shapes graph, a **results graph** for the validation of G against S is a combination of some multiset {{ R1, ..., Rn }} where { s1, ..., sn } is the set of shapes in S and Ri is a results graph for the validation of G against si in S. A **validation report** for the validation of G against S is a validation report for some results graph for the validation of G against S. A data graph **conforms** to a shapes graph if and only there is a results graph for the validation of the data graph against the shapes graph that contains no top-level validation results. Given G a data graph and s a shape in S a shapes graph, a **results graph** for the validation of G against s in S is a combination of some multiset {{ R1, ..., Rn }} where { t1, ..., tn } is the complete targets from G for s in S and Ri is a results graph for the validation of ti using G against s in S. A data graph **conforms** to a shape in a shapes graph if and only there is a results graph for the validation of the data graph against the shape in the shapes graph that contains no top-level validation results. Given f an RDF term, D a data graph, and s a shape in a shapes graph S a **results graph** for the validation of f using G against s in S is a combination of some multiset {{ R1, ..., Rn }} where { c1, ..., cn } is the constraints of s in S, Ri is an element of results(f,V,D,ci,s,S), and V is the value nodes of f with D for s in S. An RDF term and a data graph **conform** to a shape in a shapes graph if and only if there is a results graph for the validation of the RDF term using the data graph against the shape in the shapes graph that contains no top-level validation results. Note that although there can be multiple possible results graphs for a particular validation, if any results graph for the validation has no top-level validation results they will all have no top-level validation results. CONSTRAINT COMPONENTS AND VALIDATION (Normative) This section defines the SHACL constraint components along with their parameters and how they participate in validation. Given an RDF term f, a set of RDF terms V, a data graph D, a constraint c, and a shape s in a shapes graph S the possible **results of validating** f and v with D against c in S, results(f,V,D,c,s,S), is a set of results graphs as defined in this section. sh:ClassConstraintComponent is a **constraint component** with mandatory parameter sh:class A shape in an RDF graph with a value for sh:class in the graph that is not an IRI is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:ClassConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V that is not a SHACL instance of c in D and no other top-level validation results. sh:DatatypeConstraintComponent and sh:NodeKindConstraintComponent are similar to sh:ClassConstraintComponent sh:MinCountConstraintComponent is a **constraint component** with mandatory parameter sh:minCount A shape in an RDF graph with a value for sh:minCount in the graph that is not a literal with datatype xsd:integer is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:MinCountConstraintComponent and parameter values contains a single top-level validation result from f,D,c,s,S and no other top-level validation results if the cardinality of V is less than the *literal value* of i, and no top-level validation results otherwise. sh:MaxCountConstraintComponent similar to sh:MinCountConstraintComponent sh:MinExclusiveConstraintComponent is a **constraint component** with mandatory parameter sh:minExclusive A shape in an RDF graph with a value for sh:minExclusive in the graph that is not suitable for use in the *SPARQL operator <* is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:MinExclusiveConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V for which m < v returns false or produces an error in SPARQL and no other top-level validation results. sh:MinInclusiveConstraintComponent, sh:MaxExclusiveConstraintComponent, sh:MaxInclusiveConstraintComponent, sh:minLength, and sh:maxLength are similar to sh:MinExclusiveConstraintComponent sh:StemConstraintComponent and sh:LanguageInConstraintComponent are similar to sh:MinExclusiveConstraintComponent sh:PatternConstraintComponent is a **constraint component** with mandatory parameter sh:pattern and optional parameter sh:flags A shape in an RDF graph with a value for sh:pattern or sh:flags in the graph that is not a literal with datatype xsd:string is an **ill-formed shape** in the graph. A shape in an RDF graph with more than one value for sh:pattern or sh:flags in the graph is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:PatternConstraintComponent and mandatory parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V that is either a blank node or where the string representation (as defined by the SPARQL str function) does not match the given regular expression (as defined by the SPARQL REGEX function) and no other top-level validation results. If the constraint has optional parameter values then flags is used as the third argument of the SPARQL REGEX function, otherwise the third argument is the empty string. sh:UniqueLangConstraintComponent is a **constraint component** with mandatory parameter sh:uniqueLang A shape in an RDF graph with a value for sh:uniqueLang in the graph that is not "true"^^xsd:boolean is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:UniqueLangConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V that is is a language-tagged literal with the same language tag as some other element of V and no other top-level validation results. sh:EqualsConstraintComponent is a **constraint component** with mandatory parameter sh:equals A shape in an RDF graph with a value for sh:equals in the graph that is not an IRI is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:EqualsConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V that is not a value of f for p in D and for each value of f for p in D that is not in V and no other top-level validation results. sh:DisjointConstraintComponent is a **constraint component** with mandatory parameter sh:disjoint A shape in an RDF graph with a value for sh:disjoint in the graph that is not an IRI is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:DisjointConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V that is also a value of f for p in D and no other top-level validation results. sh:LessThanConstraintComponent and sh:LessThanOrEqualsConstraintComponent are similar to sh:EqualsConstraintComponent sh:ShapeConstraintComponent is a **constraint component** with mandatory parameter sh:shape A shape in an RDF graph with a value for sh:shape in the graph that is not an IRI or blank node is an **ill-formed shape** in the graph. If s is the object of an RDF triple in an RDF graph with predicate sh:shape then s has **expected type** sh:shape in the graph. Each results structure in results(f,V,D,c,s,S) where s is not recursive and c has type sh:ShapeConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V where v and D do not conform to x in S and no other top-level validation results. sh:NotConstraintComponent is similar to sh:ShapeConstraintComponent sh:AndConstraintComponent is a **constraint component** with mandatory list-taking parameter sh:and A shape in an RDF graph with a value for sh:and in the graph that is not a SHACL list in the graph whose members in the graph are all IRIs or blank nodes in the graph is an **ill-formed shape** in the graph. If s is a member of a SHACL list in an RDF graph that is the object of an RDF triple in the graph with predicate sh:and then s has **expected type** sh:shape in the graph. Each results structure in results(f,V,D,c,s,S) where s is not recursive and c has type sh:AndConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V where v and D do not conform to each element of l in S and no other top-level validation results. sh:OrConstraintComponent is similar to sh:AndConstraintComponent sh:QualifiedValueShapeConstraintComponent is a **constraint component** with mandatory parameter sh:qualifiedValueShape and optional parameters sh:qualifiedMinCount and sh:qualifiedMaxCount A shape in an RDF graph with a value for sh:qualifiedValueShape in the graph that is not an IRI or blank node is an **ill-formed shape** in the graph. A shape in an RDF graph with a value for sh:qualifiedMinCount or sh:qualifiedMaxCount in the graph that is not a literal with dataype xsd:integer is an **ill-formed shape** in the graph. A shape in an RDF graph with more than one value for sh:qualifiedValueShape, sh:qualifiedMinCount, or sh:qualifiedMaxCount in the graph is an **ill-formed shape** in the graph. A shape in an RDF graph that has a value for sh:qualifiedValueShape in the graph but no value for sh:qualifiedMinCount in the graph and no value for sh:qualifiedMaxCount in the graph is an **ill-formed shape** in the graph. If s is the object of an RDF triple in an RDF graph with predicate sh:qualifiedValueShape then s has **expected type** sh:shape in the graph. Each results structure in results(f,V,D,c,s,S) where s is not recursive and c has type sh:QualifiedValueShapeConstraintComponent and mandatory parameter values contains a single top-level validation result from f,D,c,s,S and no other top-level validation results if the number of elements v of V where where v and D conform to x in S is less than the value of min if is in the optional parameters of the constraint or is greater than the value of max if is in the optional parameters of the constraint, and no top-level validation results otherwise. sh:ClosedConstraintComponent is a **constraint component** with mandatory parameter sh:closed and optional list-taking parameter sh:ignoredProperties A shape in an RDF graph with a value for sh:closed in the graph that is not "true"^^xsd:boolean is an **ill-formed shape** in the graph. A shape in an RDF graph with a value for sh:ignoredProperties in the graph that is not a SHACL list in the graph whose members in the graph are all IRIs is an **ill-formed shape** in the graph. A shape in an RDF graph with more than one value for sh:closed or sh:ignoredProperties in the graph is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:ClosedConstraintComponent and mandatory parameter values contains a different top-level validation result from f,v,D,c,s,S for each RDF triple in D with subject f whose predicate is not a value of some value of s for sh:shape in D for sh:path in D and not a member of i in D if the constraint has optional parameter values and no other top-level validation results. sh:HasValueConstraintComponent is a **constraint component** with mandatory parameter sh:hasValue Each results structure in results(f,V,D,c,s,S) where c has type sh:HasValueConstraintComponent and mandatory parameter values contains a single top-level validation result from f,D,c,s,S and no other top-level validation results if x is not in V, and no top-level validation results otherwise. sh:InConstraintComponent is a **constraint component** with mandatory list-taking parameter sh:in A shape in an RDF graph with a value for sh:in in the graph that is not a SHACL list in the graph whose members in the graph are all IRIs or blank nodes in the graph is an **ill-formed shape** in the graph. Each results structure in results(f,V,D,c,s,S) where c has type sh:InConstraintComponent and parameter values contains a different top-level validation result from f,v,D,c,s,S for each v in V where v is not a member of x in S and no other top-level validation results. SHACL PROCESSORS (Normative) A SHACL processor MUST provide an interface that takes two RDF graphs---a data graph and a potential shapes graph. If the potential shapes graph is not a shapes graph the processor MUST signal an error. If the potential shapes graph is recursive the behaviour of the processor is not fully defined. Processors MAY signal an error if the potential shapes graph is recursive. Otherwise, unless the processor encounters a failure, it MUST create some representation of an RDF graph that is a validation report for the validation of the data graph against the potential shapes graph and return the representation or a location from which the representation can be retrieved. The representation can be a document in a syntax for RDF graphs, such as Turtle, or an RDF graph stored in a graph repository. A SHACL processor SHOULD provide an interface similar to above except that any return value is a boolean indicating whether the data graph conforms to the potential shapes graph. A SHACL processor MAY provide interfaces where the shapes graph is constructed by accessing locations that are values of RDF triples with predicate sh:shapesGraph in the data graph. A SHACL processor MAY provide interfaces that construct the potential shapes graph by taking a partial shapes graph and merging in other graphs accessible at locations that are values of RDF triples with predicate owl:imports in the potential shapes graph being consructed. If a SHACL processor accesses persistent representations of RDF graphs to validate a data graph against a potential shapes graph it MUST not change any of these representations. A SHACL processor MAY store any representation of a validation report that it constructs so long as the processor does not not violate the previous requirement.