OpenRiC Conformance
Version: 0.1.0-draft Status: Draft — open for comment Last updated: 2026-04-17
1. Purpose
Defines what it means for an implementation to be “OpenRiC-conformant.” Conformance is machine-checkable: a CLI validator runs against a live server and produces a pass/fail report.
This document specifies:
- The four conformance levels and their requirements.
- The SHACL shape files every implementation MUST validate its output against.
- The fixture pack (paired input / expected output pairs).
- The
openric-validateCLI and its exit semantics. - How implementations self-report conformance.
2. Conformance levels
| Level | Name | Requirement |
|---|---|---|
| L1 | Mapping conformance | The implementation translates each fixture input into RiC-O output that is isomorphic (per SPARQL graph equality) to the canonical expected output. |
| L2 | Viewing API conformance | All endpoints marked “REQUIRED” in Viewing API §4 are implemented, return correct content types, and pass their respective JSON Schemas. |
| L3 | Graph primitives conformance | All subgraph responses satisfy the six invariants in Graph Primitives §6. |
| L4 | Full conformance | L1 + L2 + L3, plus round-trip (input → RiC → subgraph → viewer-ready) passes with no data loss against the round-trip fixture set. |
Implementations advertise the highest level they claim. Claims are verifiable — the validator CLI reports actual level, which MUST match the claim.
3. Normative validation inputs
3.1 SHACL shapes — shapes/openric.shacl.ttl
Every RiC-O entity emitted MUST validate against the corresponding SHACL node shape. The shape file is versioned with the spec. Shapes use the sh: namespace per W3C SHACL 1.0.
The shape file defines, at minimum:
| Node shape | Target class | Key constraints |
|---|---|---|
:RecordSetShape |
rico:RecordSet |
rico:title required (1 string), rico:identifier recommended, rico:hasDateRangeSet recommended |
:RecordShape |
rico:Record |
As RecordSet; rico:isContainedIn required if not a root |
:AgentShape |
rico:Agent (and subclasses) |
rico:name required, rico:hasDateRangeSet with dateType=existence recommended |
:RepositoryShape |
rico:CorporateBody with openric:role=repository |
rico:name required, rico:hasPlace recommended |
:FunctionShape |
rico:Function |
rico:name required |
:DateRangeShape |
rico:DateRange |
At least one of rico:startDate / rico:endDate / rico:normalizedDate |
:ExtentShape |
rico:Extent |
rico:extentType required |
:LanguageShape |
rico:Language |
rico:languageCode required, MUST be ISO 639-3 |
Severity levels: sh:Violation (L1 fail), sh:Warning (advisory), sh:Info.
3.2 JSON Schemas — schemas/*.schema.json
Every endpoint response MUST validate against its JSON Schema. Schemas are JSON Schema 2020-12.
| Schema | Validates |
|---|---|
service-description.schema.json |
GET / |
vocabulary.schema.json |
GET /vocabulary |
record-list.schema.json |
GET /records |
record.schema.json |
GET /records/{id} |
agent-list.schema.json |
GET /agents |
agent.schema.json |
GET /agents/{id} |
repository-list.schema.json |
GET /repositories |
repository.schema.json |
GET /repositories/{id} |
subgraph.schema.json |
GET /graph and /records/{id}/export |
error.schema.json |
Any error response |
validation-report.schema.json |
POST /validate |
3.3 Fixture pack — fixtures/
The fixture pack is a directory of ~20 cases. Each case is a folder containing:
fixtures/fonds-with-series/
├── input.json # AtoM-shape input description
├── expected.jsonld # Canonical RiC-O JSON-LD output
├── expected-graph.json # Canonical Subgraph for /graph endpoint
└── notes.md # Explanation of what this case exercises
Initial fixture set covers:
fonds-minimal— fonds with title and creator onlyfonds-with-series— fonds + series + item hierarchyfonds-multilingual— fonds with en + fr + af titlesagent-person-simple— single person with datesagent-corporate-body— corporate body with mandates and placesagent-family— family with member relationshipsagent-with-relations— successor-of, predecessor-of chainsrepository-with-holdings— ISDIAH repo + 3 fondsfunction-with-activities— ISDF function with 2 activitiesevent-production— record with creation event → Productionevent-accumulation— record with accumulation eventrecord-with-digital-object— record + instantiation + mime-typerecord-in-container— record held inrico:Thing(box)record-security-classified— record with classification levelrecord-personal-data— record flaggedcontainsPersonalData=truerecord-with-access-restriction— record with restriction scopesubgraph-depth-1— graph endpoint, root + direct neighbourssubgraph-depth-2— graph endpoint, two-hop BFSsubgraph-filtered-by-type— graph endpoint withtypes=rico:Personvalidation-failure— deliberately broken input, expected SHACL failures
4. Graph equality
Two RiC-O graphs are equal (for L1 conformance) iff they are isomorphic under blank-node bijection. The validator uses SPARQL’s sh:equal semantics for concrete nodes and standard graph isomorphism for blank nodes.
JSON-LD framing order, property order within a node, and prefix choice are NOT significant. Only the resulting RDF graph matters.
5. The openric-validate CLI
A reference validator is published at https://github.com/openric/validator (pending).
5.1 Usage
openric-validate <server-base-url> [--level=L1|L2|L3|L4] [--fixtures=<dir>]
[--output=<json|junit|human>]
Examples:
# Validate a running server at L4
openric-validate https://archives.example.org/api/ric/v1 --level=L4
# Validate a specific record by URL
openric-validate --record https://archives.example.org/api/ric/v1/records/AHG-A001
# Validate local JSON-LD file against shapes
openric-validate --file my-record.jsonld --shapes shapes/openric.shacl.ttl
5.2 Exit codes
| Code | Meaning |
|---|---|
0 |
All checks passed at the requested level |
1 |
One or more violations (check report) |
2 |
Warnings only (useful in strict mode) |
3 |
Server unreachable |
4 |
Invalid invocation |
5.3 Report format
JUnit XML and JSON are supported for CI integration. Human-readable format for interactive use.
{
"openric_version": "0.1.0",
"level_claimed": "L4",
"level_achieved": "L3",
"passed": 47,
"failed": 3,
"warnings": 12,
"failures": [
{
"fixture": "agent-family",
"endpoint": "/agents/smuts-family",
"check": "SHACL:AgentShape",
"severity": "Violation",
"message": "rico:name required but missing"
}
]
}
6. Self-reporting
Every conformant server SHOULD expose its achieved level in the service-description endpoint:
GET /api/ric/v1/
→ { "openric:conformance": ["L1", "L2", "L3"], … }
Additionally, a conformance badge MAY be displayed in the server’s web UI or README:

(Badge endpoint is aspirational — not yet live.)
7. Certification
There is no certification authority. Conformance is self-asserted and independently verifiable via the CLI. This mirrors IIIF’s approach and keeps the ecosystem open.
Spec editors may, at their discretion, list third-party implementations on openric.org alongside Heratio once they pass the CLI at the claimed level.
8. Testing your implementation
The minimum to claim L1 conformance:
- Clone
https://github.com/openric/spec(this repo). - For each fixture in
fixtures/, feedinput.jsonthrough your mapping. - Compare your output against
expected.jsonldusing the validator’s graph-equality mode. - Fix discrepancies until all 20 fixtures pass.
L2 additionally requires a running HTTP endpoint. L3 additionally requires graph responses that satisfy the six invariants in Graph Primitives §6. L4 additionally requires round-trip preservation.
9. Versioning
This conformance document and the associated shapes/schemas/fixtures are versioned together. Conformance is stated against a specific spec version:
Heratio 0.94.0 passes OpenRiC 0.1.0 at L3.
Minor version bumps (0.1.x) may add fixtures or tighten shapes but never break passing implementations. Major version bumps (1.0 → 2.0) may.
10. Change log
| Version | Date | Notes |
|---|---|---|
| 0.1.0-draft | 2026-04-17 | Initial draft. SHACL shapes derived from Heratio’s ric_shacl_shapes.ttl. |