Ontology engineering · controlled vocabularies

A vocabulary you can govern.

Code lists, taxonomies, thesauri and glossaries are all the same thing — governed sets of values. This is how to model them in SKOS, keep them out of the class hierarchy, and let any domain team extend them without touching yours.

Written for Vocabulary authors Domain teams extending reference data

Why a controlled vocabulary at all

A controlled vocabulary is the fixed set of values a field is allowed to take — the perils you underwrite, the statuses a claim moves through, the currencies you settle in, the lines of business you write. It is agreed once, governed centrally, and reused everywhere. It is not the shape of the model; it is the content that fills it.

Thesis

A class says what a thing is; a controlled vocabulary says which value it holds. Confuse the two and every code becomes a class — the hierarchy explodes, the reasoner slows, and the business can no longer add a peril without a modelling change. Keep them apart, and the vocabulary becomes what it should be: governed data the ontology points at, that anyone can grow.

The tool for this is SKOS — the W3C Simple Knowledge Organization System, built for exactly one job: representing the code lists, taxonomies, thesauri and glossaries that classify things, as a graph of concepts rather than a hierarchy of logical classes.

This brief is the companion to the namespace policy: that one fixes where a scheme’s IRIs live (the /vocabulary/ root); this one shows how to build what lives there — and, most of all, how a second team extends a vocabulary it does not own.

01 — THE CHOICE

Values are concepts, not classes

The instinct is to model each code as an owl:ClassFlood, Fire, Windstorm all under a Peril class. It reads well and it is wrong for four reasons:

  • Class explosion. A few hundred perils, statuses and industry codes become a few hundred near-empty classes cluttering the T-Box, each existing only to be a label.
  • Reasoner burden. A DL reasoner must classify every one of them. Values carry no logical structure worth reasoning over, so the cost buys nothing.
  • Governance friction. The business cannot add “Storm Surge” without an ontology change, a review and a release. Reference data should move on its own clock, not the model’s.
  • Profile risk. Bending classes to carry synonyms, multilingual labels and ordering drags the model toward OWL Full — against an OWL 2 DL profile.

SKOS answers all four. A code is a skos:Concept — an individual, not a class — gathered into a skos:ConceptScheme. Concepts carry labels, notations, hierarchy and definitions without ever entering the class hierarchy the reasoner classifies. The vocabulary lives in its own graph and its own file; the ontology references it. The T-Box stays small and DL-clean; the value set grows freely.

One code list, three ways to model it

ConcernFree-text stringOWL class per codeSKOS concept  ✓
Stable identity (IRI)none — just textyesyes
Synonyms & abbreviationsnoawkward (extra labels)skos:altLabel
Multilingual labelsnordfs:label hacksprefLabel per language
HierarchynosubClassOf (reasoned)skos:broader (asserted, cheap)
Definitions & notesnordfs:commentdefinition, scopeNote
Governance clockn/atied to the ontology releaseindependent, per scheme
Reasoner costnone (and no meaning)classifies every codeconcepts are individuals — no class-hierarchy cost
Business adds a valuen/aneeds a modelling changeadd a concept — no T-Box change

// a concept lives under the /vocabulary/ root — see the namespace policy, §04

https://data.chubb.com/host · https
vocabulary/root · skos
ins/layer
peril/scheme
Floodconcept
02 — THE CONTINUUM

Four shapes, one mechanism

Code list, taxonomy, thesaurus and glossary are not four technologies. They are four points on a single SKOS continuum. Every one is a skos:ConceptScheme of skos:Concepts — they differ only in which SKOS properties you switch on. That is the quiet superpower here: a flat code list can grow into a full thesaurus without re-platforming, keeping the same IRIs the whole way.

1

Code list

A flat, finite set of values. Each concept is a top concept; no relations between them.

Uses: Concept, prefLabel, notation, topConceptOf

2

Taxonomy

A code list with a tree (or poly‑hierarchy) — broader/narrower classification.

+ adds: skos:broader / narrower (& broaderTransitive)

3

Thesaurus

A taxonomy plus synonyms, entry terms, associative links and cross‑scheme mappings.

+ adds: related, altLabel, hiddenLabel, *Match

4

Glossary

Concepts whose point is the definition. Meaning lives in the notes; terms are the entries.

+ adds: definition, scopeNote, example

The reason it’s a continuum, not four boxes

You never migrate between them. A currency code list that later needs regional groupings just gains skos:broader. A peril list that later needs a definition just gains skos:definition. Same scheme, same IRIs, richer structure — because underneath, it was always concepts in a scheme.

Shape 1 — code list

Flat and finite. Every concept is a skos:topConceptOf the scheme; there is no broader. The skos:notation carries the machine code the business already uses.

# /vocabulary/ins/claim-status/ — a flat code list
@prefix cstat: <https://data.chubb.com/vocabulary/ins/claim-status/> .
@prefix skos:  <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:   <http://purl.org/dc/terms/> .

cstat:  a skos:ConceptScheme ;
        dct:title "Chubb Claim Status"@en ;
        owl:versionInfo "0.1" .

cstat:Open   a skos:Concept ; skos:topConceptOf cstat: ;
        skos:prefLabel "Open"@en ;   skos:notation "OPN" .
cstat:Closed a skos:Concept ; skos:topConceptOf cstat: ;
        skos:prefLabel "Closed"@en ; skos:notation "CLS" .
cstat:Reopened a skos:Concept ; skos:topConceptOf cstat: ;
        skos:prefLabel "Reopened"@en ; skos:notation "ROP" .

Shape 2 — taxonomy

Add skos:broader / skos:narrower (they are inverses) to classify. For “all descendants” queries use the transitive super‑properties skos:broaderTransitive / narrowerTransitivebroader itself is deliberately not transitive, so you assert one level and query many.

# /vocabulary/ins/line-of-business/ — a classification tree
@prefix lob: <https://data.chubb.com/vocabulary/ins/line-of-business/> .

lob: a skos:ConceptScheme ; dct:title "Chubb Lines of Business"@en .

lob:Property a skos:Concept ; skos:topConceptOf lob: ;
        skos:prefLabel "Property"@en .

lob:CommercialProperty a skos:Concept ; skos:inScheme lob: ;
        skos:prefLabel "Commercial Property"@en ;
        skos:broader   lob:Property .          # one level asserted…

lob:CommercialFlood a skos:Concept ; skos:inScheme lob: ;
        skos:prefLabel "Commercial Flood"@en ;
        skos:broader   lob:CommercialProperty . # …descendants inferred via broaderTransitive

Shape 3 — thesaurus

A taxonomy that also captures how people say things and how concepts relate: skos:altLabel for synonyms and abbreviations, skos:hiddenLabel for misspellings and retired forms (indexed for search but never shown), and skos:related for a non‑hierarchical association. This is the ISO‑25964 thesaurus, expressed in SKOS.

# /vocabulary/ins/peril/ — hierarchy + synonyms + association
@prefix peril: <https://data.chubb.com/vocabulary/ins/peril/> .

peril:Flood a skos:Concept ; skos:inScheme peril: ;
        skos:prefLabel   "Flood"@en ;
        skos:altLabel    "Inundation"@en ;    # a synonym — searchable, shown
        skos:hiddenLabel "Flud"@en ;          # a misspelling — searchable, never shown
        skos:notation    "FLD" ;
        skos:broader     peril:WaterDamage ;    # hierarchical (BT/NT)
        skos:related     peril:StormSurge ;     # associative (RT)
        skos:definition  "A temporary covering by water of land not normally covered by water."@en .

Shape 4 — glossary

Here the concept exists for its definition. The term is the headword; the meaning is carried in the SKOS documentation properties — skos:definition, skos:scopeNote (how and where to use it), skos:example, and the editorial notes. A glossary is a thesaurus whose centre of gravity is the note, not the hierarchy.

# /vocabulary/ins/glossary/ — definitional concepts
@prefix term: <https://data.chubb.com/vocabulary/ins/glossary/> .

term: a skos:ConceptScheme ; dct:title "Chubb Insurance Glossary"@en .

term:Subrogation a skos:Concept ; skos:inScheme term: ;
        skos:prefLabel  "Subrogation"@en ;
        skos:definition "The insurer's right, after paying a claim, to pursue a third party that caused the loss."@en ;
        skos:scopeNote  "Used in claims recovery; distinct from salvage."@en ;
        skos:example    "After settling a fire claim, the insurer subrogates against the negligent contractor."@en ;
        skos:related    term:Salvage .
03 — THE BUILDING BLOCKS

The SKOS vocabulary, on one page

Everything above is built from a small, fixed set of terms. This is the whole toolkit — group it in your head as scheme, labels, relations, notes, grouping and mapping.

GroupTermUse it for
Scheme & membershipskos:ConceptSchemethe vocabulary itself — one per file, its own namespace
skos:inSchemea concept’s membership in a scheme
skos:topConceptOf / hasTopConceptthe entry points (roots) of the scheme
Labelsskos:prefLabelthe display name — exactly one per language per concept
skos:altLabelsynonyms, abbreviations, trade names (searchable, showable)
skos:hiddenLabelmisspellings, deprecated spellings (searchable, never shown)
Notationskos:notationthe machine/business code — not the IRI local name
Relationsskos:broader / narrowerhierarchy (BT/NT) — asserted one level at a time
skos:broaderTransitive…the transitive closure — query with these, don’t assert them
skos:relatedassociative link (RT) — symmetric, non‑hierarchical
Documentationskos:definition / scopeNote / examplemeaning, usage boundary, worked instance
skos:note / historyNote / editorialNote / changeNoteprovenance & lifecycle annotations
Groupingskos:Collection / OrderedCollectionfacets and ordered lists (e.g. severity) — not hierarchy
Mapping (cross‑scheme)exactMatch, closeMatch, broadMatch, narrowMatch, relatedMatchlinking your concepts to another team’s scheme — see §05

The integrity rules that keep a scheme consistent

  • One prefLabel per language. A concept may have many altLabels but only a single preferred label in each language.
  • The three label types are disjoint. A given string is a prefLabel, an altLabel or a hiddenLabel — never two at once on the same concept.
  • Associative and hierarchical don’t overlap. skos:related is disjoint from broaderTransitive — two concepts are either ancestor/descendant or associates, not both.
  • The code goes in skos:notation, the token in the IRI. …/peril/Flood is a readable, permanent handle; "FLD" is the governed business code that may have its own datatype.
  • exactMatch is transitive and symmetric; closeMatch is neither. Don’t chain a run of closeMatch links and treat the ends as equivalent.

When a label itself needs metadata

If a label must carry its own provenance, source or deprecation date, reify it with SKOS‑XL (skosxl:Label, skosxl:literalForm). It is heavier — reach for it only when a plain literal label genuinely can’t hold what you need.

04 — THE SEAM

How the ontology references a scheme

The T-Box never contains the codes; it points at them. A property ranges over skos:Concept, an instance links to a shared concept, and the code list evolves on its own without a single edit to the model. OWL’s rdfs:range can only say “a concept”; to say “a concept from this scheme” use a SHACL shape — validation, not schema — which is exactly what a shapes/ layer is for.

# T-Box (claim.ttl) — reference the scheme by range; don't embed the codes
claim:hasPeril  a owl:ObjectProperty ;
        rdfs:range skos:Concept .

# SHACL (shapes/) — the value must be a peril concept, drawn from peril:
claim:ClaimShape a sh:NodeShape ; sh:targetClass claim:Claim ;
    sh:property [ sh:path claim:hasPeril ;
                  sh:class skos:Concept ;
                  sh:node [ sh:property [ sh:path skos:inScheme ;
                                          sh:hasValue peril: ] ] ] .

# A-Box (resource/) — the fact points at the shared concept
ex:Claim-100  a claim:Claim ;
        claim:hasPeril peril:Flood .   # the same IRI the whole enterprise uses

Concept or class? The boundary

Not every domain notion is a value. Use this test when you’re unsure which side of the seam a thing belongs on:

Model it as a SKOS concept

  • It only ever labels or classifies an instance.
  • The list is long, and the business governs it.
  • Values are added and retired without logical consequence.
  • You want synonyms, notations and multilingual labels.

Promote it to an OWL class

  • It has its own structure — properties, restrictions.
  • It participates in axioms a reasoner must use.
  • Membership is inferred, not asserted by a code.
  • The set is small, stable and part of the model’s backbone.

Most domains need both: a small class backbone in OWL and a large governed value list in SKOS, joined at the seam. Keep concepts as individuals — do not pun a concept as a class — and the model stays in OWL 2 DL.

05 — EXTENSION

Extending a vocabulary you don’t own

This is where controlled vocabularies most often go wrong. A regional team, a new line of business or a partner needs to add or refine values — and reaches into the enterprise scheme to do it. Don’t. The same golden rule that governs ontology extensions governs vocabularies: mint in your own scheme, and link across.

The golden rule

Never add, renumber or delete a concept in a scheme you don’t govern. Create your concepts in your own /vocabulary/ namespace, then connect them to the base scheme with SKOS mapping properties — the cross‑scheme analogues of broader / narrower / related.

The four mapping properties — and what each claims

You assertMeaningStrength
yours skos:broadMatch baseyour concept is narrower than the base concepthierarchical, one‑way
yours skos:narrowMatch baseyour concept is broader than the base concepthierarchical, one‑way
yours skos:exactMatch baseinterchangeable — same meaningstrong: transitive & symmetric
yours skos:closeMatch baseclose, but not interchangeablesafe default: not transitive
yours skos:relatedMatch baseassociated across schemesassociative

Reserve exactMatch for genuine equivalence — because it is transitive, a careless one propagates. When two concepts are “basically the same” but you’re not certain, closeMatch is the honest choice.

The pattern in Turtle

A UK flood team needs finer perils than the enterprise scheme carries. It builds its own hierarchy and hangs the roots under the enterprise concept — without ever writing into peril:.

# /vocabulary/uk/peril/ — a regional refinement, in its own namespace
@prefix ukp:   <https://data.chubb.com/vocabulary/uk/peril/> .
@prefix peril: <https://data.chubb.com/vocabulary/ins/peril/> .   # the enterprise scheme — read-only to us

ukp: a skos:ConceptScheme ; dct:title "UK Flood Perils"@en ; owl:versionInfo "0.1" .

ukp:CoastalFlood a skos:Concept ; skos:inScheme ukp: ;
        skos:prefLabel  "Coastal Flood"@en ;
        skos:broadMatch peril:Flood .          # root of my tree hangs under theirs

ukp:StormSurge a skos:Concept ; skos:inScheme ukp: ;
        skos:prefLabel  "Storm Surge"@en ; skos:notation "STS" ;
        skos:broader    ukp:CoastalFlood ;     # hierarchy *within* my scheme
        skos:broadMatch peril:Flood .          # …and anchored to the enterprise concept

Why mapping, not merging, is the whole game

The enterprise peril scheme has one owner and one meaning of “Flood”. Ten regional teams can each grow their own precision beneath it and still roll up to that one concept for reporting — because they point at peril:Flood, they don’t copy it. Merge instead of map, and you get ten incompatible “Flood”s and no enterprise total.

Two ways to extend — one right, one wrong

Editing the shared scheme

  • Squatting. Adding StormSurge straight into peril: — a scheme you don’t own.
  • Renumbering. Changing another team’s notations to fit yours.
  • Forking. Copying peril.ttl and diverging under the same IRIs.
  • Deleting. Removing a retired peril others still reference.

Extending from your own scheme

  • Own namespace. Concepts in …/uk/peril/, versioned on your clock.
  • Map upward. broadMatch / exactMatch to the enterprise concept.
  • Grow inward. Your own broader hierarchy, rooted at the base.
  • Deprecate, never delete. Retire with a note; keep the IRI stable.

When the value is genuinely enterprise-wide

Sometimes a “regional” concept turns out to belong to everyone. That is a change request to the base scheme’s steward — proposed, reviewed and versioned against the enterprise scheme on its own track — not something you keep private forever, and not something you graft in yourself. Extend in your namespace now; propose the promotion deliberately.

06 — THE POLICY

Ten rules for a controlled vocabulary

Normative. MUST rules are invariants a reviewer or a SHACL shape can check; SHOULD rules are strong defaults you break only with a recorded reason.

CV-1

MUSTModel a controlled vocabulary as a skos:ConceptScheme of skos:Concepts — never as a hierarchy of OWL classes.

CV-2

MUSTOne scheme per file, in its own /vocabulary/ namespace, versioned and prefixed exactly like an ontology module (see the namespace policy, NS-4–NS-8).

CV-3

MUSTGive every concept one skos:prefLabel per language and a scheme linkskos:inScheme (or skos:topConceptOf for a root).

CV-4

MUSTCarry the business code in skos:notation, not the IRI. The local name is a stable, readable token; the notation is the governed code.

CV-5

SHOULDUse skos:altLabel for synonyms and skos:hiddenLabel for misspellings & retired forms — and keep the three label types disjoint.

CV-6

MUSTExpress hierarchy with skos:broader/narrower and association with skos:related — never assert both between the same pair.

CV-7

MUSTReference a scheme from the ontology by range over skos:Concept, constrained in SHACL — never embed codes as classes in a T-Box module.

CV-8

MUSTExtend a scheme you don’t own from your own scheme, linking with broadMatch / exactMatch / closeMatch / relatedMatch — never add, renumber or delete another team’s concepts.

CV-9

MUSTDeprecate, don’t delete. Retire a concept with owl:deprecated + a skos:historyNote/changeNote, keeping its IRI and notation stable forever.

CV-10

SHOULDRecord provenance and lifecycle on the schemedct:creator, dct:issued, dct:modified, owl:versionInfo, and a named steward.

07 — A STARTER SET

The schemes the Chubb ontology should carry

Concrete first schemes to mint under /vocabulary/, with the shape each naturally takes. The green rows sit in the foundation layer because they’re standards‑based and shared across every domain.

SchemeNamespaceShapeSample concepts
peril…/vocabulary/ins/peril/thesaurusFlood, Fire, Windstorm, Storm Surge
claim-status…/vocabulary/ins/claim-status/code listOpen, Closed, Reopened, Denied
line-of-business…/vocabulary/ins/line-of-business/taxonomyProperty › Commercial Property
cause-of-loss…/vocabulary/ins/cause-of-loss/taxonomyNatural › Weather › Hail
coverage-type…/vocabulary/ins/coverage-type/taxonomyLiability, Physical Damage
glossary…/vocabulary/ins/glossary/glossarySubrogation, Indemnity, Salvage
currency…/vocabulary/fnd/currency/code list (ISO 4217)USD, GBP, EUR
country / region…/vocabulary/fnd/country/code list (ISO 3166)US, GB, FR

Reuse before you mint — the standards case

For published standards like ISO 4217 currencies or ISO 3166 countries, prefer an existing SKOS publication. Where you must mint local concepts, carry the standard code in skos:notation and add skos:exactMatch to the published concept — the same reuse‑first discipline the foundation applies to external ontologies.

Every one of these is the same machine underneath: a scheme, some concepts, the right SKOS properties switched on for the job — governed as data, referenced by the model, and open for any domain team to extend from its own namespace.