Design document · ontology project conventions

One graph, many projections.

How the ontologies, vocabularies, shapes, competency questions, and samples are organized and encoded — why Turtle is the source of truth, where JSON-LD belongs, and how all five stay in sync.

5 artifact types Turtle canonical · JSON-LD at the edge CI-enforced sync
01 — PRINCIPLES

Five ideas the whole design rests on

one substrate

Everything is RDF

Ontologies, code lists, shapes, competency questions, and sample data are all RDF graphs. One data model underneath means one toolchain and lossless conversion between serializations.

one source

Single source of truth

Each fact is authored in exactly one place, in one format. Everything a consumer needs in another format is generated from it — never hand-maintained in parallel.

fit the reader

Encode for the audience

Authors and reasoners read Turtle. Applications read JSON. The format is chosen per audience, not once for the whole project.

separation

Meaning, constraint & data are distinct

What a thing means (OWL), what valid data must look like (SHACL), and the instances themselves (ABox) are different jobs with different lifecycles — kept in different files.

traceable

Everything traces to a CQ

No class, shape, or sample exists without a competency question that needs it. The CQ suite is also the test suite that proves the artifacts agree.

generated

Generate, don’t duplicate

JSON-LD contexts and documentation are build outputs of the ontology. If two files must say the same thing, one is derived from the other.

02 — THE ARTIFACTS

The five artifact types & their jobs

Each type answers a different question, works under a different logical regime, and therefore lives in its own file — even when they describe the same concept.

ArtifactAnswersLogicLanguageEncoding
Ontology
TBox
What does this mean? What can be inferred? Open-world (OWL 2 DL) OWL .ttl
Vocabulary
code lists
What are the allowed values? (statuses, perils, LOBs) Reference data SKOS .ttl
Shapes
constraints
Is this data valid & complete? Closed-world (validation) SHACL .ttl
Competency Qs
requirements
What must the model be able to answer? Tests Custom cq: + SPARQL .ttl
Samples
ABox
What does a real instance look like? Fixtures / examples Instance RDF .ttl + .jsonld

The distinction newcomers miss

OWL is not a schema validator. OWL reasons under the open-world assumption — a missing property is “unknown,” not “invalid.” When you need “every Policy must have exactly one policy number or reject it,” that is a SHACL job, not an OWL cardinality axiom. Model meaning in OWL; enforce data quality in SHACL. Keeping them in separate files is what makes that separation real.

Likewise, controlled values — policy:PolicyStatus, claim statuses, perils, lines of business — are SKOS concept schemes, not OWL classes. They change on a business cadence (new peril codes) independent of the model, so they live in their own vocabulary/ files and are referenced by both the ontology (as ranges) and the shapes (as sh:in value sets).

03 — ORGANIZATION

How the project is laid out

Two axes compete: group by module (everything about Policy together) or by artifact type (all shapes together). The artifacts have very different import scopes and lifecycles — the TBox is imported everywhere; shapes and samples are imported nowhere — so the top level is organized by type. Cohesion is recovered through a shared filename stem, so one grep policy.* finds every artifact for a module.

ontology/ # TBox — OWL 2 DL, the model fnd/ core.ttl agreement.ttl identifier.ttl location.ttl time.ttl org.ttl ins/ policy.ttl claim.ttl coverage.ttl business.ttl vocabulary/ # SKOS code lists — reference data policy-status.ttl claim-status.ttl peril.ttl line-of-business.ttl shapes/ # SHACL — validation & API contracts policy.shapes.ttl claim.shapes.ttl coverage.shapes.ttl competency/ # requirements / acceptance tests competency.ttl # the cq: meta-model (was misc/) policy.cq.ttl claim.cq.ttl coverage.cq.ttl samples/ # ABox — canonical Turtle fixtures policy-example.ttl claim-example.ttl context/ # JSON-LD @context — generated, served policy.context.jsonld chubb.context.jsonld

This is an evolution of the current fnd/ ins/ misc/ resource/ layout: misc/→competency/, resource/→samples/, and the new vocabulary/ shapes/ context/ trees. The IRI schemes extend the ones already in use:

ArtifactNamespace pattern
Ontology (TBox)https://data.chubb.com/ontology/{fnd|ins}/<module>/
Vocabulary (SKOS)https://data.chubb.com/vocabulary/<scheme>/
Shapes (SHACL)https://data.chubb.com/shapes/<module>/
Competency questionshttps://data.chubb.com/resource/<module>/cq/
Samples / instances (ABox)https://data.chubb.com/resource/<module>/
JSON-LD contexthttps://data.chubb.com/context/<module>.jsonld (dereferenceable)

The existing header directives (# baseURI / # prefix / # imports) and owl:versionIRI conventions carry over unchanged — they remain the metadata that must mirror the real owl:imports.

04 — ENCODING

Why Turtle is the canonical format

All authored artifacts are RDF, and RDF has several serializations. We author every one of them in Turtle and treat that as the source of truth. The reasoning:

readable

Written for humans

Turtle’s prefixed names and predicate lists read like prose next to RDF/XML. Ontology work is editing done by people — legibility is a feature, not a luxury.

diffable

Reviews & merges cleanly

One statement per line, stable ordering → git diffs are meaningful and merge conflicts are local. RDF/XML and pretty-printed JSON-LD both produce noisy, unreviewable diffs.

expressive

Handles the hard parts

OWL restrictions, intersections, and blank-node-heavy axioms are natural in Turtle. They are awkward-to-unwritable in hand-authored JSON-LD.

supported

Native to the tools

Protégé, TopBraid, Jena, rdflib, and every SHACL/SPARQL engine read and write Turtle first-class. It is the lingua franca of the RDF toolchain.

Because all five artifacts share the RDF substrate, a single format for all of them keeps the mental model and the tooling uniform: the same editor, the same diff, the same loader for a shape, a code list, a CQ, and a sample. Turtle is the authoring surface; any other serialization a consumer needs is produced by conversion, losslessly.

Rule of thumb

If a human authors it or a reasoner consumes it → Turtle. If an application consumes it → JSON-LD, generated. RDF/XML is emitted only if a legacy tool demands it — never authored.

05 — JSON-LD

How & when JSON-LD is used

JSON-LD is JSON that is RDF. A @context maps ordinary JSON keys to ontology IRIs, so an application developer consumes idiomatic JSON while the payload remains a precise RDF graph. That makes JSON-LD the format of the boundary — where the semantic core meets applications that speak JSON — not of the core itself.

The same graph, two serializations

Canonical — samples/policy-example.ttl

@prefix policy: <…/ontology/ins/policy/> .
@prefix res: <…/resource/> .

res:policy/PN-100
  a policy:Policy ;
  policy:policyNumber "PN-100" ;
  policy:producer     res:party/acme ;
  coverage:hasCoverage res:cov/c1 .

Served — GET /policy/PN-100 (Accept: json)

{
  "@context": "…/context/policy.jsonld",
  "id": "…/resource/policy/PN-100",
  "type": "Policy",
  "policyNumber": "PN-100",
  "producer": "…/resource/party/acme",
  "hasCoverage": "…/resource/cov/c1"
}

Both expand to the identical triples. The bridge is the context — itself a small, versioned, generated artifact that maps friendly keys to ontology terms:

// context/policy.context.jsonld — generated from policy.ttl, served at a stable URL
{
  "@context": {
    "policy":   "https://data.chubb.com/ontology/ins/policy/",
    "coverage": "https://data.chubb.com/ontology/ins/coverage/",
    "id": "@id", "type": "@type",
    "Policy":        "policy:Policy",
    "policyNumber":  "policy:policyNumber",
    "producer":     { "@id": "policy:producer",      "@type": "@id" },
    "hasCoverage":  { "@id": "coverage:hasCoverage", "@type": "@id" }
  }
}
USE JSON-LD FOR

The edge

  • API responses & event payloads serving instance data to apps.
  • The @context — the published contract between JSON keys and ontology IRIs.
  • Framing to shape nested, tree-like JSON views for a specific consumer.
  • Developer-facing samples that double as API-contract examples.
DON’T USE IT FOR

The core

  • Authoring the ontology — OWL axioms and blank nodes fight the JSON shape.
  • SHACL shapes — author in Turtle; validate Turtle or JSON-LD data alike.
  • Reasoning & review — diffs and DL tooling want Turtle.

In practice a single resource is served in either format by content negotiation: Accept: text/turtle returns the Turtle, Accept: application/ld+json returns the JSON-LD — two projections of one stored graph, so they can never disagree.

06 — SYNC

How the five are kept in sync

Five artifacts describing the same concepts will drift unless drift is made to fail loudly. Two mechanisms enforce it: a dependency direction (derived artifacts point at the ontology, never the reverse) and an executable check for every dependency, run in CI.

The dependency rules & their enforcement

ArtifactMust stay consistent withCheck that enforces it
Ontology(the source of truth)DL reasoner: consistent & every class satisfiable
VocabularyOntology (schemes used as ranges)every skos:Concept a range/shape expects actually exists
ShapesOntology (paths, targets) + Vocabulary (sh:in)shape-lint: every sh:path/targetClass/sh:in term resolves
Competency QsOntology + Samplesrun the SPARQL → expected rows come back
SamplesOntology + Shapesreasoner-consistent and SHACL-conformant
JSON-LD contextOntology (term → IRI map)context-lint: every mapped IRI exists (ideally generated)

The CI pipeline that runs those checks

Parse (syntax) Merge graph · imports resolve Reason · DL consistency SHACL · samples conform Run CQs · SPARQL Lint context Bundle & version

There is no CI committed today — adding this pipeline is the single highest-leverage step. Loading all modules into one graph at the “merge” stage is what catches dangling IRIs and orphan imports (the kind of defect the identifier.ttl orphan represents).

The competency-question suite is the linchpin

Because each CQ’s SPARQL touches real ontology terms, resolved through real shapes, over real samples, running the CQ suite exercises the entire chain at once. When a property is renamed and someone forgets the shape or the context, a CQ goes red. The tests you already write for requirements double as the drift detector.

Governance: one change obliges its dependents

The rules become a PR checklist. Adding a property is never a one-file edit — it cascades:

  • Ontology — declare the property, its domain/range, axioms.
  • Shapes — add/adjust the constraint that governs it.
  • Vocabulary — if its values are enumerated, add the code list.
  • Competency question — add the CQ that justifies it (or it shouldn’t exist).
  • Sample — extend a fixture so the CQ has data to bind.
  • Context & docs — regenerate; bump owl:versionInfo.

Modules are versioned together via owl:versionIRI/versionInfo; a tagged release bundles version-stamped files, with the matching JSON-LD contexts and generated docs shipped alongside so a consumer of version N gets a context that agrees with ontology N.

07 — AT A GLANCE

The design in one screen

ArtifactDirLanguageAuthoredServedFilename stem
Ontologyontology/OWLTurtleTurtle / JSON-LDpolicy.ttl
Vocabularyvocabulary/SKOSTurtleTurtle / JSON-LDpolicy-status.ttl
Shapesshapes/SHACLTurtlenot servedpolicy.shapes.ttl
Competency Qscompetency/cq: + SPARQLTurtleinternalpolicy.cq.ttl
Samplessamples/Instance RDFTurtleTurtle / JSON-LDpolicy-example.ttl
Contextcontext/JSON-LDgeneratedJSON-LDpolicy.context.jsonld

The whole design in one sentence: author every artifact once, in Turtle, as RDF; let competency questions prove they agree; and project to JSON-LD only at the edge, from a generated context that is versioned with the model.