feat: Add MainPart and OutputData classes with detailed specifications

- Introduced MainPart class to represent principal portions with quantified values, including attributes for part type and currency code.
- Added OutputData class to specify output characteristics from devices/services, including format, description, and destination URL.
- Created canonical_value, capacity, capacity_type, and capacity_value slots for enhanced data representation.
- Archived and migrated various slots related to data sensitivity, dataset descriptions, and titles to align with new structures.
- Implemented has_or_had_caption and has_or_had_main_part slots to support media accessibility and primary portion representation.
- Enhanced data license policy slot to define custodian data licensing and openness policies.
This commit is contained in:
kempersc 2026-01-23 11:04:15 +01:00
parent 479ceae715
commit 6bb8ac20ba
60 changed files with 3221 additions and 422 deletions

View file

@ -1,12 +1,12 @@
{
"generated": "2026-01-22T21:19:53.129Z",
"generated": "2026-01-23T09:51:31.737Z",
"schemaRoot": "/schemas/20251121/linkml",
"totalFiles": 3037,
"totalFiles": 3036,
"categoryCounts": {
"main": 4,
"class": 970,
"class": 980,
"enum": 155,
"slot": 1904,
"slot": 1893,
"module": 4
},
"categories": [
@ -565,6 +565,11 @@
"path": "modules/classes/CallForApplication.yaml",
"category": "class"
},
{
"name": "CanonicalForm",
"path": "modules/classes/CanonicalForm.yaml",
"category": "class"
},
{
"name": "CantonalArchive",
"path": "modules/classes/CantonalArchive.yaml",
@ -585,6 +590,21 @@
"path": "modules/classes/Capacity.yaml",
"category": "class"
},
{
"name": "CapacityType",
"path": "modules/classes/CapacityType.yaml",
"category": "class"
},
{
"name": "CapacityTypes",
"path": "modules/classes/CapacityTypes.yaml",
"category": "class"
},
{
"name": "Caption",
"path": "modules/classes/Caption.yaml",
"category": "class"
},
{
"name": "CareerEntry",
"path": "modules/classes/CareerEntry.yaml",
@ -1260,11 +1280,26 @@
"path": "modules/classes/DarkArchiveRecordSetTypes.yaml",
"category": "class"
},
{
"name": "DataFormat",
"path": "modules/classes/DataFormat.yaml",
"category": "class"
},
{
"name": "DataFormatTypes",
"path": "modules/classes/DataFormatTypes.yaml",
"category": "class"
},
{
"name": "DataLicensePolicy",
"path": "modules/classes/DataLicensePolicy.yaml",
"category": "class"
},
{
"name": "DataSensitivityLevel",
"path": "modules/classes/DataSensitivityLevel.yaml",
"category": "class"
},
{
"name": "DataServiceEndpoint",
"path": "modules/classes/DataServiceEndpoint.yaml",
@ -2390,6 +2425,11 @@
"path": "modules/classes/MailingListArchiveRecordSetTypes.yaml",
"category": "class"
},
{
"name": "MainPart",
"path": "modules/classes/MainPart.yaml",
"category": "class"
},
{
"name": "MappingType",
"path": "modules/classes/MappingType.yaml",
@ -2880,6 +2920,11 @@
"path": "modules/classes/OutdoorSite.yaml",
"category": "class"
},
{
"name": "OutputData",
"path": "modules/classes/OutputData.yaml",
"category": "class"
},
{
"name": "Overview",
"path": "modules/classes/Overview.yaml",
@ -4210,6 +4255,11 @@
"path": "modules/classes/Timestamp.yaml",
"category": "class"
},
{
"name": "Title",
"path": "modules/classes/Title.yaml",
"category": "class"
},
{
"name": "TitleType",
"path": "modules/classes/TitleType.yaml",
@ -5737,46 +5787,6 @@
"path": "modules/slots/begin_of_the_end.yaml",
"category": "slot"
},
{
"name": "canonical_value",
"path": "modules/slots/canonical_value.yaml",
"category": "slot"
},
{
"name": "capacity",
"path": "modules/slots/capacity.yaml",
"category": "slot"
},
{
"name": "capacity_type",
"path": "modules/slots/capacity_type.yaml",
"category": "slot"
},
{
"name": "capacity_value",
"path": "modules/slots/capacity_value.yaml",
"category": "slot"
},
{
"name": "capital_budget",
"path": "modules/slots/capital_budget.yaml",
"category": "slot"
},
{
"name": "caption_available",
"path": "modules/slots/caption_available.yaml",
"category": "slot"
},
{
"name": "card_description",
"path": "modules/slots/card_description.yaml",
"category": "slot"
},
{
"name": "card_description_en",
"path": "modules/slots/card_description_en.yaml",
"category": "slot"
},
{
"name": "card_image_url",
"path": "modules/slots/card_image_url.yaml",
@ -6497,31 +6507,11 @@
"path": "modules/slots/custody_received_by.yaml",
"category": "slot"
},
{
"name": "cut_count",
"path": "modules/slots/cut_count.yaml",
"category": "slot"
},
{
"name": "data_format",
"path": "modules/slots/data_format.yaml",
"category": "slot"
},
{
"name": "data_license_policy",
"path": "modules/slots/data_license_policy.yaml",
"category": "slot"
},
{
"name": "data_repository",
"path": "modules/slots/data_repository.yaml",
"category": "slot"
},
{
"name": "data_sensitivity",
"path": "modules/slots/data_sensitivity.yaml",
"category": "slot"
},
{
"name": "data_source_whatsapp",
"path": "modules/slots/data_source_whatsapp.yaml",
@ -6532,21 +6522,6 @@
"path": "modules/slots/data_tier.yaml",
"category": "slot"
},
{
"name": "dataset_description",
"path": "modules/slots/dataset_description.yaml",
"category": "slot"
},
{
"name": "dataset_identifier",
"path": "modules/slots/dataset_identifier.yaml",
"category": "slot"
},
{
"name": "dataset_title",
"path": "modules/slots/dataset_title.yaml",
"category": "slot"
},
{
"name": "date",
"path": "modules/slots/date.yaml",
@ -9067,6 +9042,11 @@
"path": "modules/slots/has_or_had_capacity.yaml",
"category": "slot"
},
{
"name": "has_or_had_caption",
"path": "modules/slots/has_or_had_caption.yaml",
"category": "slot"
},
{
"name": "has_or_had_category",
"path": "modules/slots/has_or_had_category.yaml",
@ -9492,6 +9472,11 @@
"path": "modules/slots/has_or_had_location.yaml",
"category": "slot"
},
{
"name": "has_or_had_main_part",
"path": "modules/slots/has_or_had_main_part.yaml",
"category": "slot"
},
{
"name": "has_or_had_managed_by_cm",
"path": "modules/slots/has_or_had_managed_by_cm.yaml",
@ -9622,6 +9607,11 @@
"path": "modules/slots/has_or_had_organizer.yaml",
"category": "slot"
},
{
"name": "has_or_had_output",
"path": "modules/slots/has_or_had_output.yaml",
"category": "slot"
},
{
"name": "has_or_had_owner",
"path": "modules/slots/has_or_had_owner.yaml",
@ -10077,6 +10067,11 @@
"path": "modules/slots/has_or_had_timestamp.yaml",
"category": "slot"
},
{
"name": "has_or_had_title",
"path": "modules/slots/has_or_had_title.yaml",
"category": "slot"
},
{
"name": "has_or_had_token",
"path": "modules/slots/has_or_had_token.yaml",

View file

@ -24,7 +24,9 @@ imports:
- ../slots/has_or_had_status
- ./BudgetStatus
- ../slots/has_or_had_type
- ../slots/capital_budget
# MIGRATED 2026-01-22: capital_budget → has_or_had_main_part + MainPart per slot_fixes.yaml revision
- ../slots/has_or_had_main_part
- ./MainPart
- ./BudgetType
- ../slots/digitization_budget
- ../slots/documented_by
@ -115,7 +117,8 @@ classes:
# - budget_status
- has_or_had_status
- has_or_had_type
- capital_budget
# MIGRATED 2026-01-22: capital_budget → has_or_had_main_part + MainPart per slot_fixes.yaml revision
- has_or_had_main_part
- digitization_budget
- documented_by
- endowment_draw
@ -258,9 +261,22 @@ classes:
operating_budget:
range: decimal
required: false
capital_budget:
range: decimal
# MIGRATED 2026-01-22: capital_budget → has_or_had_main_part + MainPart per slot_fixes.yaml revision
has_or_had_main_part:
range: MainPart
inlined: true
required: false
description: |
Capital budget allocation (infrastructure, equipment, major purchases).
MIGRATED from capital_budget per slot_fixes.yaml (Rule 53, 2026-01-22).
MainPart provides structured representation with Quantity for amount and currency metadata.
examples:
- value:
has_or_had_quantity:
quantity_value: 3000000.0
part_type: capital_budget
currency_code: EUR
description: Capital budget of 3 million EUR
has_or_had_acquisition_budget:
range: decimal
required: false
@ -389,7 +405,11 @@ classes:
has_or_had_label: Euro
currency_symbol:
operating_budget: 38000000.0
capital_budget: 3000000.0
has_or_had_main_part:
has_or_had_quantity:
quantity_value: 3000000.0
part_type: capital_budget
currency_code: EUR
acquisition_budget: 2000000.0
personnel_budget: 22000000.0
preservation_budget: 1500000.0
@ -421,7 +441,11 @@ classes:
has_or_had_label: Euro
currency_symbol:
operating_budget: 7500000.0
capital_budget: 500000.0
has_or_had_main_part:
has_or_had_quantity:
quantity_value: 500000.0
part_type: capital_budget
currency_code: EUR
personnel_budget: 5200000.0
digitization_budget: 800000.0
external_funding: 6000000.0

View file

@ -0,0 +1,99 @@
id: https://nde.nl/ontology/hc/class/CanonicalForm
name: canonical_form_class
title: Canonical Form Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
skos: http://www.w3.org/2004/02/skos/core#
schema: http://schema.org/
dcterms: http://purl.org/dc/terms/
imports:
- linkml:types
- ../slots/has_or_had_label
- ./Label
default_prefix: hc
classes:
CanonicalForm:
class_uri: skos:Concept
description: >-
Represents the canonical/normalized form of an identifier or value.
**PURPOSE**:
While original values may vary in format (spaces, prefixes, case),
CanonicalForm provides a standardized representation for:
- Consistent storage
- Deduplication and matching
- Database joins and lookups
- Cross-system interoperability
**NORMALIZATION RULES BY STANDARD**:
| Standard | Original | Canonical |
|----------|----------|-----------|
| ISNI | "0000 0001 2146 5765" | "0000000121465765" |
| Wikidata | "http://wikidata.org/entity/Q190804" | "Q190804" |
| VIAF | "viaf.org/viaf/148691498" | "148691498" |
| DOI | "https://doi.org/10.1234/Ex" | "10.1234/ex" |
| ISIL | "NL-AmRMA" | "NL-AmRMA" (already canonical) |
**ONTOLOGY ALIGNMENT**:
| Ontology | Mapping | Rationale |
|----------|---------|-----------|
| SKOS | skos:Concept | Conceptual representation |
| Schema.org | schema:PropertyValue | Name-value pair |
MIGRATED 2026-01-22: Created per slot_fixes.yaml feedback to replace
simple canonical_value string with structured class.
exact_mappings:
- skos:Concept
close_mappings:
- schema:PropertyValue
slots:
- has_or_had_label
slot_usage:
has_or_had_label:
range: Label
required: true
inlined: true
description: >-
The canonical/normalized value as a Label.
Label.has_or_had_text contains the actual normalized string.
attributes:
normalization_rule:
range: string
required: false
description: >-
The rule or standard used to normalize this value.
E.g., "ISNI_REMOVE_SPACES", "WIKIDATA_EXTRACT_QID", "DOI_LOWERCASE"
source_format:
range: string
required: false
description: >-
The original format/scheme before normalization.
E.g., "ISNI_DISPLAY", "WIKIDATA_URI", "DOI_URL"
examples:
- value:
has_or_had_label:
has_or_had_text: "0000000121465765"
normalization_rule: "ISNI_REMOVE_SPACES"
source_format: "ISNI_DISPLAY"
description: ISNI canonical form (spaces removed)
- value:
has_or_had_label:
has_or_had_text: "Q190804"
normalization_rule: "WIKIDATA_EXTRACT_QID"
source_format: "WIKIDATA_URI"
description: Wikidata canonical form (Q-number extracted)
- value:
has_or_had_label:
has_or_had_text: "10.1234/example"
normalization_rule: "DOI_LOWERCASE_NO_PREFIX"
source_format: "DOI_URL"
description: DOI canonical form (lowercase, no resolver prefix)
annotations:
specificity_score: 0.30
specificity_rationale: >-
Canonical forms are relevant for identifier lookup across all heritage sectors.

View file

@ -9,7 +9,7 @@ prefixes:
dcterms: http://purl.org/dc/terms/
imports:
- linkml:types
# Enums
# Enums (kept for backward compatibility)
- ../enums/CapacityTypeEnum
# RiC-O style generic slots
- ../slots/has_or_had_identifier
@ -20,9 +20,12 @@ imports:
- ../slots/temporal_extent
- ../slots/specificity_annotation
- ../slots/has_or_had_score # was: template_specificity - migrated per Rule 53 (2026-01-17)
# Capacity-specific slots
- ../slots/capacity_value
- ../slots/capacity_type
# MIGRATED 2026-01-22: capacity_type → has_or_had_type + CapacityType (Rule 53)
- ../slots/has_or_had_type
# MIGRATED 2026-01-22: capacity_value → has_or_had_quantity + Quantity (Rule 53)
- ../slots/has_or_had_unit
- ./Unit
# Capacity-specific slots (capacity_value removed - use has_or_had_quantity)
- ../slots/is_estimate
# Class imports
- ./MeasureUnit
@ -30,10 +33,11 @@ imports:
- ./TimeSpan
- ./SpecificityAnnotation
- ./TemplateSpecificityScore # was: TemplateSpecificityScores - migrated per Rule 53 (2026-01-17)
- ./TemplateSpecificityType
- ./TemplateSpecificityTypes
# MIGRATED 2026-01-22: capacity_type → has_or_had_type + CapacityType (Rule 53)
- ./CapacityType
- ./CapacityTypes
default_prefix: hc
classes:
Capacity:
@ -66,37 +70,37 @@ classes:
| WEIGHT | Weight capacity | kg, tons |
| SEATING | Seating capacity | seats, persons |
**EXAMPLES**:
**EXAMPLES** (MIGRATED 2026-01-22: capacity_value → has_or_had_quantity):
Archive depot (linear meters):
```yaml
has_or_had_capacity:
- capacity_value: 8000.0
capacity_type: SHELF_LENGTH
has_or_had_measurement_unit:
has_or_had_type: LINEAR_METER
has_or_had_symbol: "m"
- has_or_had_quantity:
quantity_value: 8000.0
has_or_had_unit:
unit_value: "linear_meter"
has_or_had_type: ShelfLengthCapacity
has_or_had_description: Total linear meters of shelving capacity
```
Cold storage (volume):
```yaml
has_or_had_capacity:
- capacity_value: 2500.0
capacity_type: VOLUME
has_or_had_measurement_unit:
has_or_had_type: CUBIC_METER
has_or_had_symbol: "m³"
- has_or_had_quantity:
quantity_value: 2500.0
has_or_had_unit:
unit_value: "cubic_meter"
has_or_had_type: VolumeCapacity
```
Archive box storage (items):
```yaml
has_or_had_capacity:
- capacity_value: 50000
capacity_type: ITEM_COUNT
has_or_had_measurement_unit:
has_or_had_type: ITEM
has_or_had_symbol: "archive boxes"
- has_or_had_quantity:
quantity_value: 50000
has_or_had_unit:
unit_value: "item"
has_or_had_type: ItemCountCapacity
```
exact_mappings:
- hc:Capacity
@ -109,10 +113,12 @@ classes:
- premis:StorageLocation
slots:
- has_or_had_identifier
- capacity_value
- capacity_type
- has_or_had_measurement_unit
# MIGRATED 2026-01-22: capacity_value → has_or_had_quantity + Quantity (Rule 53)
- has_or_had_quantity
# MIGRATED 2026-01-22: capacity_type → has_or_had_type + CapacityType (Rule 53)
- has_or_had_type
- has_or_had_measurement_unit
- has_or_had_unit
- has_or_had_description
- temporal_extent
- is_estimate
@ -127,30 +133,25 @@ classes:
examples:
- value: https://nde.nl/ontology/hc/capacity/na-depot-b-shelving
description: National Archives depot B shelf capacity
capacity_value:
range: float
required: true
description: >-
The numeric value of the capacity.
MIGRATED from capacity_cubic_meters, capacity_linear_meters,
capacity_item per slot_fixes.yaml (Rule 53).
examples:
- value: 8000.0
description: 8,000 linear meters
- value: 2500.0
description: 2,500 cubic meters
- value: 50000
description: 50,000 archive boxes
capacity_type:
range: CapacityTypeEnum
# MIGRATED 2026-01-22: capacity_value → has_or_had_quantity + Quantity (Rule 53)
# capacity_value slot removed - use has_or_had_quantity with quantity_value inside
# MIGRATED 2026-01-22: capacity_type → has_or_had_type + CapacityType (Rule 53)
has_or_had_type:
range: CapacityType
required: false
description: >-
The type of capacity measurement (volume, length, count, etc.).
MIGRATED from capacity_type per slot_fixes.yaml (Rule 53, 2026-01-22).
Uses CapacityType class hierarchy instead of CapacityTypeEnum.
examples:
- value: SHELF_LENGTH
- value: VOLUME
- value: ITEM_COUNT
- value: FLOOR_AREA
- value: ShelfLengthCapacity
description: Linear shelf capacity
- value: VolumeCapacity
description: Cubic volume capacity
- value: ItemCountCapacity
description: Item count capacity
- value: FloorAreaCapacity
description: Floor area capacity
has_or_had_measurement_unit:
range: MeasureUnit
required: false
@ -171,18 +172,31 @@ classes:
has_or_had_type: ITEM
has_or_had_symbol: "archive boxes"
description: Item count
# MIGRATED 2026-01-22: capacity_value → has_or_had_quantity + Quantity (Rule 53)
has_or_had_quantity:
range: Quantity
required: false
required: true
inlined: true
description: >-
Alternative structured quantity representation.
Use for complex measurements requiring full Quantity semantics.
The capacity measurement as a structured Quantity.
MIGRATED from capacity_value per slot_fixes.yaml (Rule 53, 2026-01-22).
Contains quantity_value (numeric), and can include unit via has_or_had_unit.
examples:
- value:
quantity_value: 8000.0
quantity_type: CAPACITY
quantity_unit: "linear meters"
has_or_had_unit:
unit_value: "linear_meter"
description: 8,000 linear meters of shelving
- value:
quantity_value: 2500.0
has_or_had_unit:
unit_value: "cubic_meter"
description: 2,500 cubic meters of storage
- value:
quantity_value: 50000
has_or_had_unit:
unit_value: "item"
description: 50,000 archive boxes
has_or_had_description:
range: string
required: false
@ -218,29 +232,31 @@ classes:
- http://qudt.org/schema/qudt/Quantity
- https://schema.org/QuantitativeValue
examples:
# MIGRATED 2026-01-22: capacity_value → has_or_had_quantity + Quantity (Rule 53)
# MIGRATED 2026-01-22: capacity_type → has_or_had_type + CapacityType class (Rule 53)
- value:
has_or_had_identifier: https://nde.nl/ontology/hc/capacity/rijksmuseum-depot-shelving
capacity_value: 8000.0
capacity_type: SHELF_LENGTH
has_or_had_measurement_unit:
has_or_had_type: LINEAR_METER
has_or_had_symbol: "m"
has_or_had_quantity:
quantity_value: 8000.0
has_or_had_unit:
unit_value: "linear_meter"
has_or_had_type: ShelfLengthCapacity
has_or_had_description: Total linear shelf capacity in Depot Amersfoort
is_estimate: false
description: Archive depot shelf capacity (was capacity_linear_meters)
- value:
capacity_value: 2500.0
capacity_type: VOLUME
has_or_had_measurement_unit:
has_or_had_type: CUBIC_METER
has_or_had_symbol: "m³"
has_or_had_quantity:
quantity_value: 2500.0
has_or_had_unit:
unit_value: "cubic_meter"
has_or_had_type: VolumeCapacity
description: Cold storage volume capacity (was capacity_cubic_meters)
- value:
capacity_value: 50000
capacity_type: ITEM_COUNT
has_or_had_measurement_unit:
has_or_had_type: ITEM
has_or_had_symbol: "archive boxes"
has_or_had_quantity:
quantity_value: 50000
has_or_had_unit:
unit_value: "item"
has_or_had_type: ItemCountCapacity
has_or_had_description: Capacity for 50,000 standard archive boxes
description: Archive box storage capacity (was capacity_item)
- value:

View file

@ -0,0 +1,80 @@
# CapacityType class (abstract base)
# Created 2026-01-22 per slot_fixes.yaml revision for capacity_type (Rule 53)
# Following Rule 0b: Type/Types naming convention
id: https://nde.nl/ontology/hc/class/CapacityType
name: capacity_type_class
title: Capacity Type Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
skos: http://www.w3.org/2004/02/skos/core#
qudt: http://qudt.org/schema/qudt/
default_prefix: hc
imports:
- linkml:types
- ../slots/has_or_had_label
- ../slots/has_or_had_description
classes:
CapacityType:
class_uri: skos:Concept
abstract: true
description: |
Abstract base class for capacity measurement types.
**RULE 0b COMPLIANT**:
This is the ABSTRACT BASE CLASS (singular "Type") defining the taxonomy.
Concrete subclasses are defined in `CapacityTypes.yaml` (plural).
**CAPACITY TYPE HIERARCHY**:
| Type | Description | Unit Examples |
|------|-------------|---------------|
| VOLUME | Cubic capacity | m³, ft³ |
| SHELF_LENGTH | Linear shelf meters | m, ft |
| FLOOR_AREA | Floor space | m², ft² |
| ITEM_COUNT | Number of items | boxes, folders |
| WEIGHT | Weight capacity | kg, tons |
| SEATING | Seating capacity | seats, persons |
| DISPLAY_AREA | Exhibition space | m² |
| RACK_SLOTS | Rack/shelf slots | count |
| DRAWER_UNITS | Drawer units | count |
| CABINET_UNITS | Cabinet/storage units | count |
**QUDT ALIGNMENT**:
Capacity types align with QUDT quantity kinds for interoperability
with scientific measurement systems.
Created as part of capacity_type migration per slot_fixes.yaml (Rule 53).
exact_mappings:
- skos:Concept
close_mappings:
- qudt:QuantityKind
slots:
- has_or_had_label
- has_or_had_description
slot_usage:
has_or_had_label:
description: Human-readable label for this capacity type.
has_or_had_description:
description: Description of what this capacity type measures.
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Capacity types apply to all storage facilities.
specificity_score: 0.55
specificity_rationale: Specialized taxonomy for storage capacity measurements.
comments:
- "Abstract base class - see CapacityTypes.yaml for concrete subclasses"
- "Per Rule 0b: Type (singular) = abstract base, Types (plural) = concrete"
- "Created 2026-01-22 per slot_fixes.yaml capacity_type migration"

View file

@ -0,0 +1,140 @@
# CapacityTypes class (concrete subclasses)
# Created 2026-01-22 per slot_fixes.yaml revision for capacity_type (Rule 53)
# Following Rule 0b: Type/Types naming convention
id: https://nde.nl/ontology/hc/class/CapacityTypes
name: capacity_types_class
title: Capacity Types Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
qudt: http://qudt.org/schema/qudt/
default_prefix: hc
imports:
- linkml:types
- ./CapacityType
classes:
VolumeCapacity:
is_a: CapacityType
class_uri: hc:VolumeCapacity
description: |
Cubic volume capacity measurement (e.g., cubic meters).
Used for storage depots, vaults, and enclosed spaces.
annotations:
qudt_kind: "qudt:Volume"
typical_units: "m³, ft³, liters"
comments:
- "Replaces CapacityTypeEnum.VOLUME"
ShelfLengthCapacity:
is_a: CapacityType
class_uri: hc:ShelfLengthCapacity
description: |
Linear shelf or storage length capacity (e.g., linear meters).
Standard measurement for archive depots.
annotations:
qudt_kind: "qudt:Length"
typical_units: "m, ft, km"
comments:
- "Replaces CapacityTypeEnum.SHELF_LENGTH"
- "Primary metric for archival storage"
FloorAreaCapacity:
is_a: CapacityType
class_uri: hc:FloorAreaCapacity
description: |
Floor space area capacity (e.g., square meters).
Used for storage rooms, galleries, and exhibition spaces.
annotations:
qudt_kind: "qudt:Area"
typical_units: "m², ft²"
comments:
- "Replaces CapacityTypeEnum.FLOOR_AREA"
ItemCountCapacity:
is_a: CapacityType
class_uri: hc:ItemCountCapacity
description: |
Number of items that can be stored.
Used for boxes, folders, objects, artworks.
annotations:
qudt_kind: "qudt:Dimensionless"
typical_units: "boxes, folders, objects, items"
comments:
- "Replaces CapacityTypeEnum.ITEM_COUNT"
WeightCapacity:
is_a: CapacityType
class_uri: hc:WeightCapacity
description: |
Weight or mass capacity (e.g., kilograms, tons).
Important for floor load limits and transport.
annotations:
qudt_kind: "qudt:Mass"
typical_units: "kg, tons, lbs"
comments:
- "Replaces CapacityTypeEnum.WEIGHT"
SeatingCapacity:
is_a: CapacityType
class_uri: hc:SeatingCapacity
description: |
Seating capacity for venues and event spaces.
Number of seats or persons allowed.
annotations:
qudt_kind: "qudt:Dimensionless"
typical_units: "seats, persons"
comments:
- "Replaces CapacityTypeEnum.SEATING"
DisplayAreaCapacity:
is_a: CapacityType
class_uri: hc:DisplayAreaCapacity
description: |
Exhibition or display area capacity.
Used for galleries and exhibition halls.
annotations:
qudt_kind: "qudt:Area"
typical_units: "m², ft²"
comments:
- "Replaces CapacityTypeEnum.DISPLAY_AREA"
RackSlotCapacity:
is_a: CapacityType
class_uri: hc:RackSlotCapacity
description: |
Number of rack or shelf slots available.
Used for modular storage systems.
annotations:
qudt_kind: "qudt:Dimensionless"
typical_units: "slots, positions"
comments:
- "Replaces CapacityTypeEnum.RACK_SLOTS"
DrawerUnitCapacity:
is_a: CapacityType
class_uri: hc:DrawerUnitCapacity
description: |
Number of drawer units available.
Used for flat file storage and specimen collections.
annotations:
qudt_kind: "qudt:Dimensionless"
typical_units: "drawers, units"
comments:
- "Replaces CapacityTypeEnum.DRAWER_UNITS"
CabinetUnitCapacity:
is_a: CapacityType
class_uri: hc:CabinetUnitCapacity
description: |
Number of cabinet or storage units available.
Used for modular cabinet systems.
annotations:
qudt_kind: "qudt:Dimensionless"
typical_units: "cabinets, units"
comments:
- "Replaces CapacityTypeEnum.CABINET_UNITS"

View file

@ -0,0 +1,97 @@
id: https://nde.nl/ontology/hc/class/Caption
name: caption_class
title: Caption Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
dcterms: http://purl.org/dc/terms/
imports:
- linkml:types
- ../slots/has_or_had_label
- ../slots/language
- ./Label
default_prefix: hc
classes:
Caption:
class_uri: schema:caption
description: >-
Represents accessibility caption/subtitle information for media content.
**PURPOSE**:
Caption provides structured representation of video/audio captions for:
- WCAG accessibility compliance
- Multilingual subtitle support
- Caption metadata (language, format, availability)
**ONTOLOGY ALIGNMENT**:
| Ontology | Mapping | Rationale |
|----------|---------|-----------|
| Schema.org | schema:caption | Media caption/subtitle |
**USE CASES**:
- Video captions for hearing accessibility
- Subtitles for multilingual content
- Closed captions vs. open captions distinction
MIGRATED 2026-01-22: Created per slot_fixes.yaml feedback to replace
simple caption_available string with structured class.
exact_mappings:
- schema:caption
slots:
- has_or_had_label
- language
slot_usage:
has_or_had_label:
range: Label
required: false
inlined: true
description: >-
Caption text content. Label.has_or_had_text contains the actual caption.
language:
range: string
required: false
description: >-
ISO 639-1 language code for the caption (e.g., "en", "nl", "de").
attributes:
caption_format:
range: string
required: false
description: >-
Caption format (e.g., "SRT", "VTT", "TTML", "closed_caption", "open_caption").
is_available:
range: boolean
required: false
description: >-
Whether captions are available for this media.
Replaces simple caption_available boolean/string.
caption_url:
range: uri
required: false
description: >-
URL to external caption file (for SRT, VTT, etc.).
examples:
- value:
is_available: true
language: en
caption_format: closed_caption
description: English closed captions available
- value:
is_available: true
language: nl
caption_format: SRT
caption_url: https://example.org/video/captions_nl.srt
description: Dutch subtitles in SRT format
- value:
has_or_had_label:
has_or_had_text: "Video beschrijving voor slechthorenden"
language: nl
is_available: true
description: Dutch caption with descriptive text
annotations:
specificity_score: 0.60
specificity_rationale: >-
Captions are specific to media content, moderately relevant for digital heritage.

View file

@ -31,7 +31,7 @@ imports:
- ../slots/identifier
- ../slots/created
- ../slots/modified
- ../slots/data_license_policy
- ../slots/has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- ../slots/has_or_had_safeguard
- ../slots/temporal_extent # was: time_of_destruction - migrated per Rule 53 (2026-01-15)
# MIGRATED 2026-01-22: conflict_status → is_or_was_involved_in + Conflict (Rule 53)
@ -195,7 +195,7 @@ classes:
- is_or_was_involved_in
- created
- has_or_had_custodian_type
- data_license_policy
- has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- digital_platform
- is_or_was_encompassed_by # was: encompassing_body - migrated per Rule 53 (2025-01-15)
- has_or_had_exhibition
@ -266,9 +266,12 @@ classes:
description: |
Governance bodies that encompass this custodian.
MIGRATED from encompassing_body slot per slot_fixes.yaml (Rule 53, 2025-01-15).
data_license_policy:
range: DataLicensePolicy
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
range: DataLicensePolicy # Narrowed from Policy base class
required: false
description: |
Data licensing and openness policy for this custodian.
MIGRATED from data_license_policy per slot_fixes.yaml (Rule 53).
has_or_had_participated_in_project:
range: Project
multivalued: true

View file

@ -20,7 +20,8 @@ imports:
- ../slots/has_or_had_business_criticality # was: business_criticality - migrated per Rule 53/56/57 (2026-01-17)
- ./BusinessCriticality
- ../slots/creating_function
- ../slots/data_sensitivity
- ../slots/has_or_had_level # was: data_sensitivity - migrated per Rule 53/56/57 (2026-01-23)
- ./DataSensitivityLevel
- ../slots/estimated_volume
- ../slots/expected_transfer_date
- ../slots/gdpr_relevant
@ -116,7 +117,7 @@ classes:
- has_or_had_status
- has_or_had_business_criticality # was: business_criticality - migrated per Rule 53/56/57 (2026-01-17)
- creating_function
- data_sensitivity
- has_or_had_level # was: data_sensitivity - migrated per Rule 53/56/57 (2026-01-23)
- estimated_volume
- expected_transfer_date
- gdpr_relevant
@ -211,11 +212,19 @@ classes:
examples:
- value: '2027-01-01'
description: Oldest records eligible for transfer in 2027
data_sensitivity:
range: string
has_or_had_level: # was: data_sensitivity - migrated per Rule 53/56/57 (2026-01-23)
range: DataSensitivityLevel
inlined: true
required: false
description: >-
Data sensitivity classification level.
Standard codes: PUBLIC, INTERNAL, CONFIDENTIAL, STRICTLY_CONFIDENTIAL,
PERSONAL_DATA, SPECIAL_CATEGORY
examples:
- value: CONFIDENTIAL - Personnel data
- value:
has_or_had_label: Confidential
has_or_had_short_code: CONFIDENTIAL
has_or_had_description: Personnel data - need-to-know basis
description: HR files classification
gdpr_relevant:
range: boolean
@ -314,7 +323,10 @@ classes:
retention_schedule: Museum Retention Schedule 2020, cat. 1.1
retention_period_years: 10
expected_transfer_date: '2028-01-01'
data_sensitivity: CONFIDENTIAL
has_or_had_level: # was: data_sensitivity
has_or_had_label: Confidential
has_or_had_short_code: CONFIDENTIAL
has_or_had_description: Confidential correspondence - need-to-know basis
gdpr_relevant: true
has_or_had_business_criticality: # was: business_criticality - migrated to BusinessCriticality class
has_or_had_label: HIGH
@ -344,7 +356,10 @@ classes:
primary_system: https://nde.nl/ontology/hc/platform/rm-workday
retention_schedule: Museum Retention Schedule 2020, cat. 3.2
retention_period_years: 20
data_sensitivity: SPECIAL_CATEGORY - Personnel data
has_or_had_level: # was: data_sensitivity
has_or_had_label: Special Category Data
has_or_had_short_code: SPECIAL_CATEGORY
has_or_had_description: Personnel data - GDPR Article 9 sensitive personal data
gdpr_relevant: true
has_or_had_business_criticality: # was: business_criticality - migrated to BusinessCriticality class
has_or_had_label: CRITICAL
@ -376,7 +391,10 @@ classes:
- https://nde.nl/ontology/hc/platform/rm-adlib
retention_schedule: Permanent - linked to collection objects
retention_period_years: null
data_sensitivity: INTERNAL
has_or_had_level: # was: data_sensitivity
has_or_had_label: Internal
has_or_had_short_code: INTERNAL
has_or_had_description: For internal staff use only
gdpr_relevant: false
has_or_had_business_criticality: # was: business_criticality - migrated to BusinessCriticality class
has_or_had_label: HIGH

View file

@ -0,0 +1,153 @@
# DataFormat - Class for data format specifications
#
# Created per slot_fixes.yaml migration for: data_format
# Creation date: 2026-01-22
# Rule compliance: 39 (RiC-O naming), 50 (ontology mapping), 53 (generic slot reuse), 0b (Type/Types)
id: https://nde.nl/ontology/hc/class/DataFormat
name: data_format_class
title: Data Format
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
dct: http://purl.org/dc/terms/
default_prefix: hc
imports:
- linkml:types
- ../slots/has_or_had_type
- ../slots/has_or_had_label
- ../slots/has_or_had_description
classes:
DataFormat:
class_uri: hc:DataFormat
description: |
Specification of a data format for files, APIs, or data streams.
**DEFINITION**:
DataFormat captures format characteristics including type, media type,
schema references, and encoding specifications.
**USAGE**:
- API response formats (JSON, XML, RDF)
- File formats (CSV, Excel, PDF, TIFF)
- Streaming protocols (MQTT, WebSocket payloads)
- Archival formats (METS, EAD, MARC)
**ONTOLOGY ALIGNMENT**:
- **Primary** (`class_uri`): `hc:DataFormat` - Heritage Custodian class
- **Close**: `dct:MediaTypeOrExtent` - Dublin Core media type
- **Close**: `schema:encodingFormat` - Schema.org encoding
**Common Format Types**:
| Type | Media Type | Use Case |
|------|------------|----------|
| JSON | application/json | API responses, config |
| XML | application/xml | Legacy APIs, metadata |
| CSV | text/csv | Data exports, tabular |
| RDF | application/rdf+xml | Linked data |
| SensorML | application/xml | Sensor metadata |
**Example**:
```yaml
has_or_had_format:
has_or_had_type: JsonFormat
has_or_had_media_type: "application/json"
has_or_had_encoding: "UTF-8"
```
close_mappings:
- dct:MediaTypeOrExtent
- schema:encodingFormat
slots:
- has_or_had_type
- has_or_had_label
- has_or_had_description
- has_or_had_media_type
- has_or_had_encoding
- has_or_had_schema_url
slot_usage:
has_or_had_type:
range: DataFormatType
description: |
The format type classification.
Links to DataFormatType taxonomy (JSON, XML, CSV, etc.).
examples:
- value: JsonFormat
description: JSON format type
- value: CsvFormat
description: CSV format type
has_or_had_label:
range: Label
inlined: true
description: Human-readable name for the format.
examples:
- value:
label_text: "JSON"
description: Format label
has_or_had_media_type:
range: string
description: |
IANA media type (MIME type) for the format.
See: https://www.iana.org/assignments/media-types/
examples:
- value: "application/json"
description: JSON media type
- value: "text/csv"
description: CSV media type
has_or_had_encoding:
range: string
description: Character encoding used (e.g., UTF-8, ISO-8859-1).
examples:
- value: "UTF-8"
description: Unicode encoding
has_or_had_schema_url:
range: uri
description: URL to schema definition (JSON Schema, XSD, etc.).
examples:
- value: "https://api.museum.nl/schemas/v1/climate.json"
description: JSON Schema URL
attributes:
has_or_had_media_type:
range: string
description: IANA media type (MIME type).
has_or_had_encoding:
range: string
description: Character encoding (e.g., UTF-8).
has_or_had_schema_url:
range: uri
description: URL to schema definition.
annotations:
custodian_types: '["*"]'
custodian_types_rationale: "Data format specifications apply to all custodian types with digital systems."
specificity_score: 0.55
specificity_rationale: "Moderately specific to digital platform and API contexts."
# Type class for format taxonomy (Rule 0b: Type/Types pattern)
DataFormatType:
class_uri: hc:DataFormatType
abstract: true
description: |
Abstract base class for data format type taxonomy.
**Type/Types Pattern** (Rule 0b):
- `DataFormatType` (this file): Abstract base class
- `DataFormatTypes.yaml`: Concrete subclasses (JsonFormat, XmlFormat, etc.)
Subclasses define specific format types used in heritage data systems.
slots:
- has_or_had_label
- has_or_had_description
annotations:
custodian_types: '["*"]'
custodian_types_rationale: "Format types applicable universally."

View file

@ -0,0 +1,217 @@
# DataFormatTypes - Concrete subclasses for data format taxonomy
#
# Created per slot_fixes.yaml migration for: data_format
# Creation date: 2026-01-22
# Rule compliance: 0b (Type/Types pattern), 39 (RiC-O naming)
id: https://nde.nl/ontology/hc/class/DataFormatTypes
name: data_format_types
title: Data Format Types
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
default_prefix: hc
imports:
- linkml:types
- ./DataFormat
classes:
# ===== Common Data Interchange Formats =====
JsonFormat:
is_a: DataFormatType
class_uri: hc:JsonFormat
description: |
JavaScript Object Notation (JSON) format.
Media type: application/json
Common for APIs, configuration, and data exchange.
annotations:
media_type: "application/json"
XmlFormat:
is_a: DataFormatType
class_uri: hc:XmlFormat
description: |
Extensible Markup Language (XML) format.
Media type: application/xml
Common for legacy APIs, metadata standards.
annotations:
media_type: "application/xml"
CsvFormat:
is_a: DataFormatType
class_uri: hc:CsvFormat
description: |
Comma-Separated Values (CSV) format.
Media type: text/csv
Common for tabular data exports.
annotations:
media_type: "text/csv"
# ===== Linked Data Formats =====
RdfXmlFormat:
is_a: DataFormatType
class_uri: hc:RdfXmlFormat
description: |
RDF/XML serialization format.
Media type: application/rdf+xml
W3C standard for RDF serialization.
annotations:
media_type: "application/rdf+xml"
TurtleFormat:
is_a: DataFormatType
class_uri: hc:TurtleFormat
description: |
Turtle (Terse RDF Triple Language) format.
Media type: text/turtle
Human-readable RDF serialization.
annotations:
media_type: "text/turtle"
JsonLdFormat:
is_a: DataFormatType
class_uri: hc:JsonLdFormat
description: |
JSON for Linked Data (JSON-LD) format.
Media type: application/ld+json
JSON-based linked data serialization.
annotations:
media_type: "application/ld+json"
NTriplesFormat:
is_a: DataFormatType
class_uri: hc:NTriplesFormat
description: |
N-Triples format for RDF.
Media type: application/n-triples
Line-based RDF serialization.
annotations:
media_type: "application/n-triples"
# ===== Sensor/IoT Formats =====
SensorMlFormat:
is_a: DataFormatType
class_uri: hc:SensorMlFormat
description: |
Sensor Model Language (SensorML) format.
OGC standard for sensor metadata and processes.
annotations:
media_type: "application/xml"
standard: "OGC SensorML"
MqttPayloadFormat:
is_a: DataFormatType
class_uri: hc:MqttPayloadFormat
description: |
MQTT message payload format.
Used for IoT device communication.
Actual payload typically JSON or binary.
annotations:
protocol: "MQTT"
# ===== Heritage Metadata Formats =====
EadFormat:
is_a: DataFormatType
class_uri: hc:EadFormat
description: |
Encoded Archival Description (EAD) format.
Media type: application/xml
Standard for archival finding aids.
annotations:
media_type: "application/xml"
standard: "EAD3"
MarcXmlFormat:
is_a: DataFormatType
class_uri: hc:MarcXmlFormat
description: |
MARC 21 XML format.
Media type: application/marcxml+xml
Library bibliographic record format.
annotations:
media_type: "application/marcxml+xml"
standard: "MARC21"
MetsFormat:
is_a: DataFormatType
class_uri: hc:MetsFormat
description: |
Metadata Encoding and Transmission Standard (METS).
Media type: application/xml
Digital library object packaging.
annotations:
media_type: "application/xml"
standard: "METS"
LidoFormat:
is_a: DataFormatType
class_uri: hc:LidoFormat
description: |
Lightweight Information Describing Objects (LIDO).
Media type: application/xml
Museum object description harvesting.
annotations:
media_type: "application/xml"
standard: "LIDO"
DublinCoreFormat:
is_a: DataFormatType
class_uri: hc:DublinCoreFormat
description: |
Dublin Core metadata format (DC or qualified DC).
Media type: application/xml
General-purpose metadata standard.
annotations:
media_type: "application/xml"
standard: "Dublin Core"
# ===== Document Formats =====
PdfFormat:
is_a: DataFormatType
class_uri: hc:PdfFormat
description: |
Portable Document Format (PDF).
Media type: application/pdf
Document distribution and archival.
annotations:
media_type: "application/pdf"
HtmlFormat:
is_a: DataFormatType
class_uri: hc:HtmlFormat
description: |
HyperText Markup Language (HTML).
Media type: text/html
Web page content.
annotations:
media_type: "text/html"
PlainTextFormat:
is_a: DataFormatType
class_uri: hc:PlainTextFormat
description: |
Plain text format.
Media type: text/plain
Unformatted text content.
annotations:
media_type: "text/plain"
# ===== Binary/Media Formats =====
BinaryFormat:
is_a: DataFormatType
class_uri: hc:BinaryFormat
description: |
Generic binary data format.
Media type: application/octet-stream
Raw binary data streams.
annotations:
media_type: "application/octet-stream"

View file

@ -0,0 +1,117 @@
id: https://nde.nl/ontology/hc/class/DataSensitivityLevel
name: data_sensitivity_level_class
title: DataSensitivityLevel Class
description: >-
Data sensitivity classification level for records and information assets.
Used to categorize the confidentiality requirements and access restrictions
for administrative records, documents, and data systems.
Based on common information classification schemes including:
- ISO 27001 information security standards
- GDPR special category data requirements
- Dutch government classification (Rijksoverheid)
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dcterms: http://purl.org/dc/terms/
schema: http://schema.org/
imports:
- linkml:types
- ../slots/has_or_had_label
- ../slots/has_or_had_description
- ../slots/has_or_had_short_code
default_prefix: hc
classes:
DataSensitivityLevel:
class_uri: hc:DataSensitivityLevel
description: >-
Data sensitivity classification level.
**Standard Classification Levels**:
| Level | Short Code | Description | Access |
|-------|------------|-------------|--------|
| Public | PUBLIC | No restrictions on disclosure | Anyone |
| Internal | INTERNAL | For internal use only | Staff only |
| Confidential | CONFIDENTIAL | Need-to-know basis | Authorized staff |
| Strictly Confidential | STRICTLY_CONFIDENTIAL | Highly restricted | Named individuals |
| Personal Data | PERSONAL_DATA | Contains PII (GDPR Article 6) | Data subjects + authorized |
| Special Category | SPECIAL_CATEGORY | Sensitive personal data (GDPR Article 9) | Strictly controlled |
**GDPR Alignment**:
- PERSONAL_DATA: Covers GDPR Article 6 personal data
- SPECIAL_CATEGORY: Covers GDPR Article 9 special categories (health, religion,
ethnicity, political opinions, trade union membership, genetic/biometric data,
sexual orientation)
**Dublin Core**: Maps to dcterms:accessRights for access classification.
exact_mappings:
- dcterms:accessRights
close_mappings:
- schema:accessMode
slots:
- has_or_had_label
- has_or_had_short_code
- has_or_had_description
slot_usage:
has_or_had_label:
description: Human-readable name for the sensitivity level.
range: string
required: true
examples:
- value: "Public"
description: No access restrictions
- value: "Strictly Confidential"
description: Highest restriction level
has_or_had_short_code:
description: >-
Short code identifier for the sensitivity level.
Standard codes: PUBLIC, INTERNAL, CONFIDENTIAL, STRICTLY_CONFIDENTIAL,
PERSONAL_DATA, SPECIAL_CATEGORY
range: string
required: true
pattern: "^[A-Z][A-Z0-9_]*$"
examples:
- value: "PUBLIC"
description: No restrictions
- value: "CONFIDENTIAL"
description: Need-to-know basis
- value: "SPECIAL_CATEGORY"
description: GDPR Article 9 sensitive data
has_or_had_description:
description: Detailed description of what this sensitivity level means and when to apply it.
range: string
required: false
examples:
- value: "Contains employee health records - requires explicit consent and strict access controls"
description: SPECIAL_CATEGORY example
annotations:
specificity_score: 0.45
specificity_rationale: >-
Data sensitivity levels are moderately specific - used primarily in
records management and information governance contexts.
custodian_types: '["A", "O", "R"]'
custodian_types_rationale: >-
Most relevant for Archives (A), Official institutions (O), and
Research centers (R) that manage sensitive records.
examples:
- value:
has_or_had_label: "Confidential"
has_or_had_short_code: "CONFIDENTIAL"
has_or_had_description: "Need-to-know basis - restricted to authorized personnel"
description: Standard confidential classification
- value:
has_or_had_label: "Special Category Data"
has_or_had_short_code: "SPECIAL_CATEGORY"
has_or_had_description: "GDPR Article 9 sensitive personal data - health records, religious affiliation"
description: GDPR special category classification
- value:
has_or_had_label: "Personnel Data"
has_or_had_short_code: "PERSONAL_DATA"
has_or_had_description: "Contains employee personal information subject to GDPR"
description: Personal data classification for HR records

View file

@ -12,7 +12,7 @@ imports:
- ./TimeSpan
- ../slots/id
- ../slots/dissolution_date
- ../slots/data_license_policy
- ../slots/has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- ../slots/funding_source
- ../slots/description
- ../slots/has_or_had_url # was: website - migrated per Rule 53 (2025-01-15)
@ -46,38 +46,7 @@ imports:
- ./TemplateSpecificityType
- ./TemplateSpecificityTypes
- ../slots/data_license_policy
- ../slots/description
- ../slots/dissolution_date
- ../slots/external_identifier
# REMOVED: ../slots/founding_date - migrated to is_or_was_founded_through (Rule 53, 2026-01-22)
- ../slots/governance_authority
- ../slots/has_or_had_area_served
- ../slots/has_or_had_member_custodian
- ../slots/has_or_had_project
- ../slots/has_or_had_url
- ../slots/id
- ../slots/legal_jurisdiction
- ../slots/membership_criteria
- ../slots/organization_legal_form
- ../slots/organization_name
- ../slots/organization_type
- ../slots/service_offering
- ../slots/specificity_annotation
- ../slots/has_or_had_score # was: template_specificity - migrated per Rule 53 (2026-01-17)
- ../slots/data_license_policy
- ../slots/description
- ../slots/dissolution_date
- ../slots/external_identifier
# REMOVED: ../slots/founding_date - migrated to is_or_was_founded_through (Rule 53, 2026-01-22)
- ../slots/governance_authority
- ../slots/has_or_had_area_served
- ../slots/has_or_had_member_custodian
- ../slots/has_or_had_project
- ../slots/has_or_had_url
- ../slots/id
- ../slots/legal_jurisdiction
- ../slots/membership_criteria
# NOTE: Duplicate imports removed during data_license_policy migration (2026-01-22)
- ../slots/organization_legal_form
- ../slots/organization_name
- ../slots/organization_type
@ -131,7 +100,7 @@ classes:
\ from Mondriaan Fund\" (FundingOrganisation - via schema:funder)\n"
slots:
- has_or_had_area_served
- data_license_policy
- has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- description
- dissolution_date
- external_identifier

View file

@ -47,7 +47,7 @@ imports:
- ../slots/has_or_had_score # was: template_specificity - migrated per Rule 53 (2026-01-17)
- ../slots/has_or_had_budget # was: total_annual_budget - migrated per Rule 53 (2026-01-15)
- ./Budget # for has_or_had_budget range
- ../slots/data_license_policy
- ../slots/has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- ../slots/description
- ../slots/governance_authority
- ../slots/has_or_had_area_served
@ -357,7 +357,7 @@ classes:
examples:
- value: OCLC membership is open to libraries and cultural heritage organizations. Members pay annual fees based on
usage. Members receive governance rights and access to services.
data_license_policy:
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
recommended: true
exact_mappings:
- org:FormalOrganization
@ -396,7 +396,7 @@ classes:
rights (voting in Global Council), access to member pricing for services, and participation in cooperative programs.
governance_authority: Governed by Global Council of elected library representatives. Board of Trustees provides strategic
oversight. Regional councils for Americas, EMEA, and Asia Pacific. Annual Members Council meeting.
data_license_policy:
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
policy_name: OCLC Data Usage Policy
openness_stance: MIXED_POLICY
default_license: proprietary-worldcat
@ -459,7 +459,7 @@ classes:
- value: Wikimedia projects are governed by community consensus. The Wikimedia Foundation provides infrastructure
and legal support but does not control content. Movement governance through affiliates, chapters, and community-elected
bodies.
data_license_policy:
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
required: true
exact_mappings:
- schema:Organization
@ -504,7 +504,7 @@ classes:
governance_authority: Wikimedia projects are governed by community consensus through volunteer administrators, arbitration
committees, and policy pages. The Wikimedia Foundation Board of Trustees provides strategic oversight. Movement
governance through affiliates, chapters, and community-elected bodies (Movement Charter in development).
data_license_policy:
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
policy_name: Wikimedia Foundation Open Content Policy
openness_stance: STRONG_OPEN_ADVOCATE
default_license: cc0-1.0

View file

@ -70,8 +70,7 @@ imports:
- ../slots/has_or_had_access_condition
- ../slots/is_or_was_access_restricted
- ../slots/has_or_had_comprehensive_overview
- ../slots/card_description
- ../slots/card_description_en
# REMOVED 2026-01-22: card_description, card_description_en → has_or_had_description + Description (with language tag) per slot_fixes.yaml
- ../slots/card_image_url
- ../slots/card_title
- ../slots/card_title_en
@ -1027,8 +1026,8 @@ classes:
'
slots:
- card_description
- card_description_en
# MIGRATED 2026-01-22: card_description, card_description_en → has_or_had_description + Description (multivalued with language tag)
- has_or_had_description
- card_image_url
- card_title
- card_title_en
@ -1037,6 +1036,25 @@ classes:
- has_or_had_score # was: template_specificity - migrated per Rule 53 (2026-01-17)
- has_or_had_provenance_path # was: xpath - migrated per Rule 53 (2026-01-15)
slot_usage:
has_or_had_description:
range: Description
multivalued: true
inlined: true
description: |
Card description(s) with language tagging.
MIGRATED 2026-01-22: Replaces card_description and card_description_en.
Use description_type: "card" and language: "nl"/"en" to distinguish.
examples:
- value:
description_text: "Kaart beschrijving in het Nederlands"
description_type: card
language: nl
description: Dutch card description
- value:
description_text: "Card description in English"
description_type: card
language: en
description: English card description
card_title:
required: true
card_url:

View file

@ -19,7 +19,9 @@ imports:
- ../slots/defined_by_standard
- ../slots/is_or_was_allocated_by
- ../slots/identifier_format_used
- ../slots/canonical_value
# MIGRATED 2026-01-22: canonical_value → has_or_had_canonical_form + CanonicalForm per slot_fixes.yaml feedback
- ../slots/has_or_had_canonical_form
- ./CanonicalForm
- ../slots/has_or_had_secondary_label
- ../slots/has_allocation_date
- ../slots/specificity_annotation
@ -160,7 +162,7 @@ classes:
- defined_by_standard: Which Standard defines this identifier type (ISIL → ISO 15511)
- allocated_by: Which AllocationAgency assigned this specific identifier
- identifier_format_used: Which format variant is used in identifier_value
- canonical_value: Normalized form for deduplication and matching
- has_or_had_canonical_form: Normalized form (CanonicalForm) for deduplication and matching
- allocation_date: When the identifier was assigned
**Dual-Purpose Identifiers**:
@ -187,7 +189,8 @@ classes:
- is_or_was_allocated_by
- has_allocation_date
- has_or_had_secondary_label
- canonical_value
# MIGRATED 2026-01-22: canonical_value → has_or_had_canonical_form + CanonicalForm
- has_or_had_canonical_form
- defined_by_standard
- identifier_format_used
- identifies_custodian
@ -203,8 +206,19 @@ classes:
required: false
identifier_format_used:
required: false
canonical_value:
has_or_had_canonical_form:
range: CanonicalForm
required: false
inlined: true
description: >-
Canonical/normalized form for deduplication and matching.
MIGRATED 2026-01-22: Replaces canonical_value with structured CanonicalForm.
examples:
- value:
has_or_had_label:
has_or_had_text: "0000000121465765"
normalization_rule: "ISNI_REMOVE_SPACES"
description: ISNI canonical form
has_or_had_secondary_label:
description: |
For dual-purpose identifiers (ISNI, VIAF), links to the name authority

View file

@ -13,7 +13,10 @@ imports:
- ./ReconstructedEntity
- ../slots/connectivity_type
- ../slots/coverage_area
- ../slots/data_format
- ./OutputData
- ./DataFormat
- ../slots/has_or_had_output
# REMOVED 2026-01-22: data_format migrated to has_or_had_output + OutputData (Rule 53)
- ../slots/decommission_date
- ../slots/device_count
- ../slots/device_id
@ -100,7 +103,7 @@ classes:
- has_or_had_api_endpoint
- connectivity_type
- coverage_area
- data_format
- has_or_had_output # was: data_format - migrated per Rule 53 (2026-01-22)
- decommission_date
- device_count
- device_id
@ -225,11 +228,20 @@ classes:
examples:
- value: https://api.museum.nl/sensors/v1/
description: Sensor data API
data_format:
range: string
has_or_had_output: # was: data_format - migrated per Rule 53 (2026-01-22)
range: OutputData
inlined: true
description: |
Output data specification for this device.
MIGRATED from data_format per slot_fixes.yaml (Rule 53).
Uses OutputData class with DataFormat for format specification.
examples:
- value: JSON
description: JSON data format
- value:
has_or_had_format:
has_or_had_type: JsonFormat
has_or_had_media_type: "application/json"
has_or_had_description: "Sensor readings in JSON format"
description: JSON data format (was data_format)
has_or_had_frequency:
range: UpdateFrequency
inlined: true
@ -342,7 +354,11 @@ classes:
power_source: BATTERY
publishes_to: https://dashboard.rijksmuseum.nl/climate
api_endpoint: https://api.rijksmuseum.nl/climate/v1/
data_format: JSON
has_or_had_output: # was: data_format - migrated per Rule 53
has_or_had_format:
has_or_had_type: JsonFormat
has_or_had_media_type: "application/json"
has_or_had_description: "Climate sensor data"
has_or_had_frequency:
frequency_description: "Every 5 minutes"
has_or_had_quantity:

View file

@ -0,0 +1,80 @@
id: https://nde.nl/ontology/hc/class/MainPart
name: main_part_class
title: Main Part Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
dcterms: http://purl.org/dc/terms/
imports:
- linkml:types
- ../slots/has_or_had_quantity
- ./Quantity
default_prefix: hc
classes:
MainPart:
class_uri: schema:QuantitativeValue
description: >-
Represents a principal/primary portion of something with quantified value.
**PURPOSE**:
MainPart provides structured representation for primary allocations such as:
- Capital budget (principal budget for infrastructure/equipment)
- Primary funding amount
- Main portion of a larger whole
**ONTOLOGY ALIGNMENT**:
| Ontology | Mapping | Rationale |
|----------|---------|-----------|
| Schema.org | schema:QuantitativeValue | Quantified value |
**USE CASES**:
- Capital budget allocation in institutional budgets
- Primary collection value
- Main funding allocation
MIGRATED 2026-01-22: Created per slot_fixes.yaml revision for capital_budget.
Replaces simple decimal capital_budget with structured class.
exact_mappings:
- schema:QuantitativeValue
slots:
- has_or_had_quantity
slot_usage:
has_or_had_quantity:
range: Quantity
required: true
inlined: true
description: >-
The quantified value of this main part.
For capital budget: Quantity.quantity_value = amount, currency in metadata.
attributes:
part_type:
range: string
required: false
description: >-
Type of main part (e.g., "capital_budget", "primary_allocation", "main_funding").
currency_code:
range: string
required: false
description: >-
ISO 4217 currency code for financial values (e.g., "EUR", "USD", "GBP").
examples:
- value:
has_or_had_quantity:
quantity_value: 3000000.0
part_type: capital_budget
currency_code: EUR
description: Capital budget of 3 million EUR
- value:
has_or_had_quantity:
quantity_value: 500000.0
part_type: capital_budget
currency_code: USD
description: Capital budget of 500,000 USD
annotations:
specificity_score: 0.40
specificity_rationale: >-
Main parts are moderately specific, relevant for budget and allocation queries.

View file

@ -0,0 +1,124 @@
# OutputData - Class for device/service output specifications
#
# Created per slot_fixes.yaml migration for: data_format
# Creation date: 2026-01-22
# Rule compliance: 39 (RiC-O naming), 50 (ontology mapping), 53 (generic slot reuse)
id: https://nde.nl/ontology/hc/class/OutputData
name: output_data
title: Output Data
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
sosa: http://www.w3.org/ns/sosa/
dct: http://purl.org/dc/terms/
default_prefix: hc
imports:
- linkml:types
- ./DataFormat
- ../slots/has_or_had_format
- ../slots/has_or_had_description
- ../slots/has_or_had_identifier
classes:
OutputData:
class_uri: hc:OutputData
description: |
Specification of output produced by a device, service, or process.
**DEFINITION**:
OutputData captures the characteristics of data or signals emitted by
systems, including format, structure, destination, and metadata.
**USAGE**:
- IoT device data (sensor readings, beacon signals)
- API responses (JSON, XML, RDF)
- Export files (CSV, Excel, PDF)
- Streaming data (MQTT, WebSocket)
**ONTOLOGY ALIGNMENT**:
- **Primary** (`class_uri`): `hc:OutputData` - Heritage Custodian class
- **Close**: `sosa:Result` - SOSA observation result
- **Close**: `schema:DataDownload` - Schema.org data download
**Example**:
```yaml
has_or_had_output:
- has_or_had_format:
has_or_had_type: JsonFormat
has_or_had_media_type: "application/json"
has_or_had_description: "Climate sensor readings"
destination_url: "https://analytics.museum.nl/climate"
```
close_mappings:
- sosa:Result
- schema:DataDownload
slots:
- has_or_had_format
- has_or_had_description
- has_or_had_identifier
- destination_url
- schema_url
- is_streaming
slot_usage:
has_or_had_format:
range: DataFormat
inlined: true
description: |
The format specification for this output.
Uses DataFormat class to capture format type, media type, and schema.
examples:
- value:
has_or_had_type: JsonFormat
has_or_had_media_type: "application/json"
description: JSON output format
has_or_had_description:
range: string
description: Human-readable description of the output data.
examples:
- value: "Temperature and humidity readings from conservation sensors"
description: Sensor data description
destination_url:
range: uri
description: URL where output is sent or published.
examples:
- value: "https://analytics.museum.nl/data"
description: Analytics platform destination
schema_url:
range: uri
description: URL to schema definition for the output data structure.
examples:
- value: "https://api.museum.nl/schemas/climate-v1.json"
description: JSON Schema for climate data
is_streaming:
range: boolean
description: Whether this output is continuous/streaming vs batch/discrete.
examples:
- value: true
description: Real-time streaming data
- value: false
description: Batch data export
attributes:
destination_url:
range: uri
description: URL where output is sent or published.
schema_url:
range: uri
description: URL to schema definition for the output data.
is_streaming:
range: boolean
description: Whether this output is streaming vs batch.
annotations:
custodian_types: '["*"]'
custodian_types_rationale: "Output data specifications apply to all custodian types with digital systems."
specificity_score: 0.65
specificity_rationale: "Fairly specific to IoT and digital platform contexts."

View file

@ -225,27 +225,30 @@ classes:
Uses Capacity class with capacity_type and has_or_had_measurement_unit.
examples:
- value:
- capacity_value: 8000.0
capacity_type: SHELF_LENGTH
has_or_had_measurement_unit:
has_or_had_type: LINEAR_METER
has_or_had_symbol: "m"
- has_or_had_quantity:
has_or_had_numeric_value: 8000.0
has_or_had_unit:
has_or_had_type: LinearMeter
has_or_had_symbol: "m"
has_or_had_type: ShelfLength
has_or_had_description: Total linear meters of shelving
description: Was capacity_linear_meters
description: Was capacity_linear_meters (capacity_value → has_or_had_quantity)
- value:
- capacity_value: 2500.0
capacity_type: VOLUME
has_or_had_measurement_unit:
has_or_had_type: CUBIC_METER
has_or_had_symbol: "m³"
description: Was capacity_cubic_meters
- has_or_had_quantity:
has_or_had_numeric_value: 2500.0
has_or_had_unit:
has_or_had_type: CubicMeter
has_or_had_symbol: "m³"
has_or_had_type: Volume
description: Was capacity_cubic_meters (capacity_value → has_or_had_quantity)
- value:
- capacity_value: 50000
capacity_type: ITEM_COUNT
has_or_had_measurement_unit:
has_or_had_type: ITEM
has_or_had_symbol: "archive boxes"
description: Was capacity_item
- has_or_had_quantity:
has_or_had_numeric_value: 50000
has_or_had_unit:
has_or_had_type: Item
has_or_had_symbol: "archive boxes"
has_or_had_type: ItemCount
description: Was capacity_item (capacity_value → has_or_had_quantity)
- value:
- has_or_had_description: "Approximately 5,000 linear meters of shelving across 3 floors"
is_estimate: true
@ -376,11 +379,12 @@ classes:
label_text: Rijksmuseum Depot Amersfoort
language: nl
has_or_had_capacity: # was: capacity_linear_meters - migrated per Rule 53
- capacity_value: 8000.0
capacity_type: SHELF_LENGTH
has_or_had_measurement_unit:
has_or_had_type: LINEAR_METER
has_or_had_symbol: "m"
- has_or_had_quantity:
has_or_had_numeric_value: 8000.0
has_or_had_unit:
has_or_had_type: LinearMeter
has_or_had_symbol: "m"
has_or_had_type: ShelfLength
has_or_had_description: Total linear shelf capacity
current_utilization_percent: 78.5
standards_applied:

View file

@ -0,0 +1,107 @@
# Title class
# Created 2026-01-22 per slot_fixes.yaml revision for dataset_title (Rule 53)
#
# Generation date: 2026-01-22
# Rule compliance: 53 (slot_fixes.yaml), 39 (RiC-O naming)
id: https://nde.nl/ontology/hc/class/Title
name: title_class
title: Title Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dct: http://purl.org/dc/terms/
schema: http://schema.org/
default_prefix: hc
imports:
- linkml:types
- ../slots/has_or_had_language
classes:
Title:
class_uri: hc:Title
description: |
A structured title with optional language tag and variant types.
**DEFINITION**:
Title represents a named designation for a resource. Titles can:
- Have language tags for multilingual support
- Have different types (main, alternative, translated, abbreviated)
- Change over time (use has_or_had_title slot)
**USE CASES**:
1. **Dataset titles**: "Dutch Heritage Collections 2024"
2. **Document titles**: "Conservation Guidelines for Paper"
3. **Collection titles**: "Van Gogh Letters"
4. **Work titles**: "The Night Watch"
**TITLE TYPES**:
| Type | Description |
|------|-------------|
| main | Primary/official title |
| alternative | Other names, subtitles |
| translated | Title in another language |
| abbreviated | Short form, acronym |
**ONTOLOGY ALIGNMENT**:
- **Primary** (`class_uri`): `hc:Title` - Heritage Custodian class
- **Close**: `dct:title` property domain
Created as part of dataset_title migration per slot_fixes.yaml (Rule 53).
close_mappings:
- schema:name
slots:
- title_text
- title_type
- has_or_had_language
attributes:
title_text:
range: string
required: true
description: The actual title text.
title_type:
range: string
description: |
Type of title: main, alternative, translated, abbreviated.
slot_usage:
has_or_had_language:
description: Language of the title (ISO 639-1 code).
examples:
- value:
language_code: "nl"
description: Dutch language title
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Titles applicable to all heritage resources.
specificity_score: 0.35
specificity_rationale: Generic class for title representation.
comments:
- "Created 2026-01-22 per slot_fixes.yaml dataset_title migration"
- "Supports multilingual titles with language tags"
- "Used with has_or_had_title slot"
examples:
- value:
title_text: "Collectie Nederland"
title_type: "main"
has_or_had_language:
language_code: "nl"
description: "Dutch main title"
- value:
title_text: "Collection Netherlands"
title_type: "translated"
has_or_had_language:
language_code: "en"
description: "English translated title"

View file

@ -9,7 +9,7 @@ imports:
- ./Methodology
- ../slots/person_id
- ../slots/has_average_scene_duration_seconds
- ../slots/cut_count
# REMOVED 2026-01-22: cut_count migrated to has_or_had_quantity + Quantity (Rule 53)
- ../slots/has_or_had_detected_face
- ../slots/has_or_had_detected_landmark
- ../slots/has_or_had_detected_logo
@ -196,7 +196,7 @@ classes:
- schema:Clip
slots:
- has_average_scene_duration_seconds
- cut_count
- has_or_had_quantity # was: cut_count - migrated per Rule 53 (2026-01-22)
- detection_level
- dissolve_count
- fade_count
@ -253,13 +253,21 @@ classes:
examples:
- value: '[{has_or_had_label: "CUT"}, {has_or_had_label: "FADE_IN"}]'
description: Transition types found in video
cut_count:
range: integer
has_or_had_quantity: # was: cut_count - migrated per Rule 53 (2026-01-22)
range: Quantity
required: false
minimum_value: 0
inlined: true
description: |
Number of hard cuts (instantaneous transitions) as a Quantity.
MIGRATED from cut_count per slot_fixes.yaml (Rule 53).
Uses Quantity class with Unit type "Cut".
examples:
- value: 42
description: 42 cuts detected
- value:
has_or_had_numeric_value: 42
has_or_had_unit:
has_or_had_type: Cut
has_or_had_symbol: "cuts"
description: 42 cuts detected (was cut_count)
fade_count:
range: integer
required: false

View file

@ -8,7 +8,9 @@ imports:
- ../slots/language
- ../slots/has_aspect_ratio
# REMOVED 2026-01-15: ../slots/available_caption_languages - migrated to has_available_caption_language
- ../slots/caption_available
# MIGRATED 2026-01-22: caption_available → has_or_had_caption + Caption per slot_fixes.yaml feedback
- ../slots/has_or_had_caption
- ./Caption
# REMOVED 2026-01-18: ../slots/comment_author - migrated to has_or_had_author + Author (Rule 53)
- ../slots/has_or_had_author
- ./Author
@ -223,7 +225,8 @@ classes:
slots:
- has_aspect_ratio
- has_available_caption_language
- caption_available
# MIGRATED 2026-01-22: caption_available → has_or_had_caption + Caption per slot_fixes.yaml feedback
- has_or_had_caption
# REMOVED 2026-01-18: comment_count - migrated to has_or_had_quantity + Quantity (Rule 53)
# REMOVED 2026-01-22: comments_fetched - migrated to was_fetched_at + is_or_was_part_of_total + SourceCommentCount (Rule 53)
- was_fetched_at
@ -279,14 +282,32 @@ classes:
# examples:
# - value: 30.0
# description: 30 frames per second
caption_available:
range: boolean
# MIGRATED 2026-01-22: caption_available → has_or_had_caption + Caption per slot_fixes.yaml feedback
has_or_had_caption:
range: Caption
multivalued: true
inlined: true
required: false
description: |
Structured caption/subtitle information for this video.
MIGRATED from caption_available per slot_fixes.yaml (Rule 53, 2026-01-22).
Caption class provides language, format, and availability metadata.
examples:
- value: true
description: Video has captions available
- value: false
description: No captions available
- value:
is_available: true
language: en
caption_format: closed_caption
description: English closed captions available
- value:
is_available: true
language: nl
caption_format: VTT
caption_url: https://example.org/video/captions_nl.vtt
description: Dutch subtitles in VTT format
- value:
is_available: false
language: null
description: No captions available (migrated from caption_available false)
default_language:
range: string
required: false

View file

@ -25,7 +25,7 @@ imports:
- ../slots/has_or_had_portal_data_source
- ../slots/operated_by
- ../slots/has_or_had_exposed_collection
- ../slots/data_license_policy
- ../slots/has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- ../slots/serves_finding_aid
- ./ReconstructedEntity
- ../slots/has_or_had_data_service_endpoint
@ -143,7 +143,7 @@ classes:
# associated_encompassing_bodies REMOVED - use is_or_was_associated_with (Rule 53)
- is_or_was_associated_with
- created_by_project
- data_license_policy
- has_or_had_policy # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- has_or_had_data_service_endpoint
- has_or_had_exposed_collection
- geographic_scope
@ -348,13 +348,16 @@ classes:
multivalued: true
is_or_was_generated_by: # was: was_generated_by - migrated per Rule 53
range: ReconstructionActivity
data_license_policy:
range: DataLicensePolicy
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
range: DataLicensePolicy # Narrowed from Policy base class
description: |
Data licensing policy for this portal.
MIGRATED from data_license_policy per slot_fixes.yaml (Rule 53).
examples:
- value: https://nde.nl/ontology/hc/policy/europeana
description: Europeana's CC0 metadata policy
description: Europeana's CC0 metadata policy (was data_license_policy)
- value: https://nde.nl/ontology/hc/policy/archieven-nl
description: Archieven.nl data policy
description: Archieven.nl data policy (was data_license_policy)
created_by_project:
range: Project
examples:
@ -419,7 +422,7 @@ classes:
- 'Portals form aggregation chains: regional → national → European'
- Typically operated by EncompassingBody (Network, Consortium)
- Track lifecycle with portal_status and supersedes_or_superseded
- 'NEW: data_license_policy links to portal''s licensing stance (CC0, CC-BY, etc.)'
- 'has_or_had_policy (was data_license_policy) links to portal''s licensing stance (CC0, CC-BY, etc.)'
- 'NEW: created_by_project links to Project that built the portal'
- 'NEW: is_or_was_associated_with for organizational relationships beyond operator (migrated from associated_encompassing_bodies)'
- 'NEW: implements_digital_platform links to aggregated DigitalPlatform instances'
@ -505,7 +508,7 @@ classes:
participating_institutions: 4000
external_identifier:
- http://www.wikidata.org/entity/Q209441
data_license_policy:
has_or_had_policy: # was: data_license_policy - migrated per Rule 53 (2026-01-22)
- policy_id: https://nde.nl/ontology/hc/policy/europeana-data-exchange
policy_name: Europeana Data Exchange Agreement
data_licenses:

View file

@ -25,9 +25,15 @@ imports:
- ./TemplateSpecificityTypes
- ./MetadataStandard # For has_or_had_standard range
- ../slots/cessation_observed_in
- ../slots/dataset_description
- ../slots/dataset_identifier
- ../slots/dataset_title
# REMOVED 2026-01-22: ../slots/dataset_description - migrated to has_or_had_description + Description (Rule 53)
- ../slots/has_or_had_description
- ./Description
# REMOVED 2026-01-22: ../slots/dataset_identifier - migrated to has_or_had_identifier + Identifier (Rule 53)
- ../slots/has_or_had_identifier
- ./Identifier
# REMOVED 2026-01-22: ../slots/dataset_title - migrated to has_or_had_title + Title (Rule 53)
- ../slots/has_or_had_title
- ./Title
- ../slots/download_endpoint
- ../slots/has_availability_timespan
- ../slots/has_or_had_linked_data_endpoint
@ -1225,9 +1231,9 @@ classes:
class_uri: dcat:Dataset
slots:
- has_availability_timespan
- dataset_description
- dataset_identifier
- dataset_title
- has_or_had_description # was: dataset_description - migrated per Rule 53 (2026-01-22)
- has_or_had_identifier # was: dataset_identifier - migrated per Rule 53 (2026-01-22)
- has_or_had_title # was: dataset_title - migrated per Rule 53 (2026-01-22)
- download_endpoint
- linked_data_access
- is_or_was_published_by # was: published_by - migrated per Rule 53/56 (2026-01-17)

View file

@ -0,0 +1,36 @@
id: https://nde.nl/ontology/hc/slot/has_or_had_caption
name: has_or_had_caption_slot
title: Has or Had Caption Slot
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
dcterms: http://purl.org/dc/terms/
imports:
- linkml:types
default_range: string
slots:
has_or_had_caption:
slot_uri: schema:caption
description: >-
Links to a Caption providing accessibility text for media content.
**PURPOSE**:
- Accessibility compliance (WCAG)
- Video/audio content description
- Multilingual caption support
**ONTOLOGY ALIGNMENT**:
- slot_uri: schema:caption (primary)
- Supports Schema.org media accessibility patterns
MIGRATED 2026-01-22: Replaces caption_available slot per slot_fixes.yaml feedback.
range: Caption
inlined: true
multivalued: true
exact_mappings:
- schema:caption
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Captions are universal for media accessibility

View file

@ -0,0 +1,35 @@
id: https://nde.nl/ontology/hc/slot/has_or_had_main_part
name: has_or_had_main_part_slot
title: Has or Had Main Part Slot
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
dcterms: http://purl.org/dc/terms/
imports:
- linkml:types
default_range: string
slots:
has_or_had_main_part:
slot_uri: schema:hasPart
description: >-
Links to a MainPart representing the principal/primary portion of something.
**USE CASES**:
- Capital budget (primary budget allocation for infrastructure/equipment)
- Primary collection holdings
- Main organizational unit
**ONTOLOGY ALIGNMENT**:
- slot_uri: schema:hasPart (primary)
- Represents a significant/main portion of a larger whole
MIGRATED 2026-01-22: Created per slot_fixes.yaml revision for capital_budget.
range: MainPart
inlined: true
exact_mappings:
- schema:hasPart
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Main parts are universal across organizational contexts

View file

@ -0,0 +1,66 @@
# has_or_had_output - Output/emission slot for devices and services
#
# Created per slot_fixes.yaml migration for: data_format
# Creation date: 2026-01-22
# Rule compliance: 39 (RiC-O naming), 50 (ontology mapping), 53 (generic slot reuse)
id: https://nde.nl/ontology/hc/slot/has_or_had_output
name: has_or_had_output
title: Has or Had Output
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
schema: http://schema.org/
sosa: http://www.w3.org/ns/sosa/
default_prefix: hc
imports:
- linkml:types
slots:
has_or_had_output:
slot_uri: hc:hasOrHadOutput
description: |
Output produced by a device, service, or process.
**USAGE**:
Represents data, signals, or artifacts emitted by:
- IoT devices (sensor readings, beacon signals)
- APIs and services (data responses)
- Processing pipelines (transformed data)
- Software systems (reports, exports)
**ONTOLOGY ALIGNMENT**:
- **Primary** (`slot_uri`): `hc:hasOrHadOutput` - Heritage Custodian property
- **Close**: `sosa:hasResult` - SOSA observation result
- **Close**: `schema:produces` - Schema.org production relationship
**RANGE**: `OutputData` class
The OutputData class captures output specifications including format,
frequency, destination, and data characteristics.
range: OutputData
multivalued: true
inlined_as_list: true
close_mappings:
- sosa:hasResult
- schema:produces
examples:
- value:
has_or_had_format:
has_or_had_type: JsonFormat
has_or_had_description: "Climate sensor readings in JSON format"
description: IoT device output specification
- value:
has_or_had_format:
has_or_had_type: CsvFormat
destination_url: "https://analytics.museum.nl/data"
description: Data export output
annotations:
custodian_types: '["*"]'
custodian_types_rationale: "Output specifications applicable to all custodian types with digital systems."

View file

@ -0,0 +1,67 @@
# has_or_had_title slot
# Created 2026-01-22 per slot_fixes.yaml revision for dataset_title (Rule 53)
#
# Generation date: 2026-01-22
# Rule compliance: 53 (slot_fixes.yaml), 39 (RiC-O naming), 50 (ontology mapping)
id: https://nde.nl/ontology/hc/slot/has_or_had_title
name: has_or_had_title_slot
title: Has Or Had Title Slot
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dct: http://purl.org/dc/terms/
schema: http://schema.org/
default_prefix: hc
imports:
- linkml:types
slots:
has_or_had_title:
slot_uri: dct:title
description: |
The title or name of a resource.
**RiC-O Temporal Pattern**:
Uses `hasOrHad*` pattern to indicate titles can change over time.
Resources may have different titles at different points in their lifecycle.
**USE CASES**:
1. Dataset titles
2. Document titles
3. Collection titles
4. Work titles
**ONTOLOGY ALIGNMENT**:
- **Primary** (`slot_uri`): `dct:title` - Dublin Core title
- **Close**: `schema:name` - Schema.org name
- **Close**: `rdfs:label` - RDF Schema label
Created as part of dataset_title migration per slot_fixes.yaml (Rule 53).
range: Title
multivalued: false
inlined: true
exact_mappings:
- dct:title
close_mappings:
- schema:name
- rdfs:label
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Titles applicable to all resource types.
rico_pattern: hasOrHadTitle
migration_date: "2026-01-22"
replaces_slots: "dataset_title"
examples:
- value:
title_text: "Dutch Heritage Collections Dataset"
language: "en"
description: "Dataset title in English"

View file

@ -18,14 +18,10 @@
"begin_of_the_begin.yaml",
"begin_of_the_end.yaml",
"has_or_had_notation.yaml",
"canonical_value.yaml",
"capacity.yaml",
"has_or_had_canonical_form.yaml",
"capacity_type.yaml",
"capacity_value.yaml",
"capital_budget.yaml",
"caption_available.yaml",
"card_description.yaml",
"card_description_en.yaml",
"has_or_had_main_part.yaml",
"has_or_had_caption.yaml",
"card_image_url.yaml",
"card_title.yaml",
"card_title_en.yaml",
@ -69,7 +65,7 @@
"confidence_value.yaml",
"__ARCHIVED_20260122__conflict_status.yaml",
"__ARCHIVED_20260122__connection.yaml",
"connection_degree.yaml",
"__ARCHIVED_20260122__connection_degree.yaml",
"connection_heritage_relevant.yaml",
"connection_heritage_type.yaml",
"connection_id.yaml",
@ -178,16 +174,16 @@
"custodian_type_related.yaml",
"custody_history.yaml",
"custody_received_by.yaml",
"cut_count.yaml",
"data_format.yaml",
"__ARCHIVED_20260122__cut_count.yaml",
"__ARCHIVED_20260122__data_format.yaml",
"data_license_policy.yaml",
"data_repository.yaml",
"data_sensitivity.yaml",
"__ARCHIVED_20260123__data_sensitivity.yaml",
"data_source_whatsapp.yaml",
"data_tier.yaml",
"dataset_description.yaml",
"dataset_identifier.yaml",
"dataset_title.yaml",
"__ARCHIVED_20260122__dataset_description.yaml",
"__ARCHIVED_20260122__dataset_identifier.yaml",
"__ARCHIVED_20260122__dataset_title.yaml",
"date.yaml",
"date_created.yaml",
"date_identified.yaml",
@ -890,6 +886,7 @@
"has_or_had_thumbnail.yaml",
"has_or_had_time_interval.yaml",
"has_or_had_timestamp.yaml",
"has_or_had_title.yaml",
"has_or_had_token.yaml",
"has_or_had_tracked_in_cm.yaml",
"has_or_had_transmission_method.yaml",

View file

@ -7956,7 +7956,8 @@ fixes:
would enhance semantic clarity and allow for richer metadata about each canonical value.
This would align with best practices for data normalization.'
done: false
done: true
response: "Completed 2026-01-22 by claude-sonnet-4. Created has_or_had_canonical_form slot and CanonicalForm class. Migrated Identifier.yaml (CustodianIdentifier) to use new pattern. CanonicalForm has has_or_had_label → Label for normalized value, plus normalization_rule and source_format attributes. Archived canonical_value.yaml."
- original_slot_id: https://nde.nl/ontology/hc/slot/capacity
revision:
- label: has_or_had_capacity
@ -7991,7 +7992,8 @@ fixes:
and align with best practices for modeling dimensional data.
This would facilitate better integration with other dimension-related data.'
done: false
done: true
response: "Completed 2026-01-22 by claude-sonnet-4. ARCHIVED (unused): capacity slot not imported by any class file. Archived to archive/capacity_archived_20260122.yaml. No migration needed as slot was never used."
- original_slot_id: https://nde.nl/ontology/hc/slot/capacity_cubic_meters
revision:
- label: has_or_had_capacity
@ -8094,7 +8096,8 @@ fixes:
would enhance semantic clarity and allow for richer metadata about each budget amount.
This would align with best practices for financial data modeling.'
done: false
done: true
response: "Completed 2026-01-22 by claude-sonnet-4. Per revision: created has_or_had_main_part slot and MainPart class. Migrated Budget.yaml to use MainPart with Quantity for capital budget amount. MainPart.part_type='capital_budget' and currency_code attribute. Archived capital_budget.yaml."
- original_slot_id: https://nde.nl/ontology/hc/slot/caption_available
revision:
- label: has_or_had_caption
@ -8131,7 +8134,8 @@ fixes:
would enhance semantic clarity and allow for richer metadata about caption availability.
This would align with best practices for accessibility data modeling.'
done: false
done: true
response: "Completed 2026-01-22 by claude-sonnet-4. Created has_or_had_caption slot and Caption class. Migrated VideoPost.yaml to use structured Caption with is_available, language, caption_format, caption_url attributes. Archived caption_available.yaml."
- original_slot_id: https://nde.nl/ontology/hc/slot/card_description
revision:
- label: has_or_had_description
@ -8166,7 +8170,8 @@ fixes:
would enhance semantic clarity and allow for richer metadata about each description.
This would align with best practices for descriptive data modeling.'
done: false
done: true
response: "Completed 2026-01-22 by claude-sonnet-4. Migrated FindingAid.yaml Card class to use has_or_had_description + Description (multivalued with language tag). Description.description_type='card' and Description.language='nl' distinguishes from English. Archived card_description.yaml."
- original_slot_id: https://nde.nl/ontology/hc/slot/card_description_en
revision:
- label: has_or_had_description
@ -8209,7 +8214,8 @@ fixes:
would enhance semantic clarity and allow for richer metadata about each description.
This would align with best practices for multilingual data modeling.'
done: false
done: true
response: "Completed 2026-01-22 by claude-sonnet-4. Same migration as card_description - FindingAid.yaml Card class uses has_or_had_description + Description with language='en'. Archived card_description_en.yaml."
- original_slot_id: https://nde.nl/ontology/hc/slot/card_image_url
revision:
- label: has_or_had_image
@ -11332,6 +11338,28 @@ fixes:
type: slot
- label: CapacityTypes
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration #59: capacity_type** ✅ COMPLETE
**Pattern**: capacity_type → has_or_had_type + CapacityType/CapacityTypes hierarchy
**Files Created**:
- CapacityType.yaml: Abstract base class for capacity types
- CapacityTypes.yaml: 10 concrete subclasses (Volume, ShelfLength, FloorArea, etc.)
**Files Modified**:
- Capacity.yaml: Migrated capacity_type to has_or_had_type + CapacityType
- Updated imports
- Updated slots list
- Updated slot_usage with CapacityType range
- Updated description examples
- Updated class examples
**Archived**: modules/slots/archive/capacity_type_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/capacity_value
revision:
- label: has_or_had_quantity
@ -11342,6 +11370,24 @@ fixes:
type: slot
- label: Unit
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration #60: capacity_value** ✅ COMPLETE
**Pattern**: capacity_value → has_or_had_quantity + Quantity + has_or_had_unit + Unit
**Files Used** (pre-existing):
- has_or_had_quantity.yaml, Quantity.yaml
- has_or_had_unit.yaml, Unit.yaml
**Files Modified**:
- Capacity.yaml: Replaced capacity_value with has_or_had_quantity (required field)
- Storage.yaml: Updated examples to use has_or_had_quantity pattern
**Archived**: modules/slots/archive/capacity_value_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/cut_count
revision:
- label: has_or_had_quantity
@ -11353,6 +11399,25 @@ fixes:
- label: Unit
type: class
value: cut
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration #61: cut_count** ✅ COMPLETE
**Pattern**: cut_count → has_or_had_quantity + Quantity + has_or_had_unit + Unit (value: cut)
**Files Used** (pre-existing):
- has_or_had_quantity.yaml, Quantity.yaml
- has_or_had_unit.yaml, Unit.yaml
**Files Modified**:
- VideoAnnotationTypes.yaml: Replaced cut_count with has_or_had_quantity in VideoSceneAnnotation class
- Updated imports, slots list, and slot_usage section
- Unit type set to "Cut" per revision value specification
**Archived**: modules/slots/archive/cut_count_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/data_format
revision:
- label: has_or_had_output
@ -11363,12 +11428,52 @@ fixes:
type: slot
- label: DataFormat
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration #62: data_format** ✅ COMPLETE
**Pattern**: data_format → has_or_had_output + OutputData + has_or_had_format + DataFormat
**Files Created**:
- has_or_had_output.yaml: New slot for device/service outputs
- OutputData.yaml: Class for output specifications
- DataFormat.yaml: Class for format specs + DataFormatType base class
- DataFormatTypes.yaml: 19 concrete format subclasses (JSON, XML, CSV, RDF, MARC, etc.)
**Files Modified**:
- InternetOfThings.yaml: Replaced data_format with has_or_had_output + OutputData
- Updated imports, slots list, slot_usage, and examples
**Archived**: modules/slots/archive/data_format_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/data_license_policy
revision:
- label: has_or_had_policy
type: slot
- label: DataLicensePolicy
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration #63: data_license_policy** ✅ COMPLETE
**Pattern**: data_license_policy → has_or_had_policy + DataLicensePolicy
**Files Used** (pre-existing):
- has_or_had_policy.yaml (with range: Policy)
- DataLicensePolicy.yaml (subclass of Policy)
**Files Modified**:
- Custodian.yaml: Replaced data_license_policy with has_or_had_policy (range narrowed to DataLicensePolicy)
- WebPortal.yaml: Replaced data_license_policy with has_or_had_policy
- EncompassingBody.yaml: Replaced data_license_policy with has_or_had_policy (also cleaned duplicate imports)
- EncompassingBodyTypes.yaml: Updated slot_usage and examples
**Archived**: modules/slots/archive/data_license_policy_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/data_source
revision:
- label: has_or_had_repository
@ -11383,6 +11488,25 @@ fixes:
type: slot
- label: DataSensitivityLevel
type: Class
processed:
status: true
date: '2026-01-23'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: data_sensitivity** ✅ COMPLETE
**Pattern**: data_sensitivity → has_or_had_level + DataSensitivityLevel
**Files Created**:
- DataSensitivityLevel.yaml: Structured class for data sensitivity classification
with standard codes (PUBLIC, INTERNAL, CONFIDENTIAL, STRICTLY_CONFIDENTIAL,
PERSONAL_DATA, SPECIAL_CATEGORY)
**Files Modified**:
- CustodianAdministration.yaml: Replaced data_sensitivity import and slot with
has_or_had_level + DataSensitivityLevel, updated slot_usage and all examples
**Archived**: modules/slots/archive/data_sensitivity_archived_20260123.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/data_source_whatsapp
revision:
- label: has_or_had_source
@ -11401,18 +11525,61 @@ fixes:
type: slot
- label: Description
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: dataset_description** ✅ COMPLETE
**Pattern**: dataset_description → has_or_had_description + Description
**Files Modified**:
- WebPortalTypes.yaml: Updated imports and slots list
**Archived**: modules/slots/archive/dataset_description_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/dataset_identifier
revision:
- label: has_or_had_identifier
type: slot
- label: Identifier
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: dataset_identifier** ✅ COMPLETE
**Pattern**: dataset_identifier → has_or_had_identifier + Identifier
**Files Modified**:
- WebPortalTypes.yaml: Updated imports and slots list
**Archived**: modules/slots/archive/dataset_identifier_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/dataset_title
revision:
- label: has_or_had_title
type: slot
- label: Title
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: dataset_title** ✅ COMPLETE
**Pattern**: dataset_title → has_or_had_title + Title
**Files Created**:
- has_or_had_title.yaml: Generic title slot
- Title.yaml: Structured title class
**Files Modified**:
- WebPortalTypes.yaml: Updated imports and slots list
**Archived**: modules/slots/archive/dataset_title_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/date_value
revision:
- label: temporal_extent
@ -15227,4 +15394,349 @@ fixes:
type: slot
- label: URL
type: class
# https://nde.nl/ontology/hc/slot/has_auxiliary_place
- original_slot_id: https://nde.nl/ontology/hc/slot/has_auxiliary_place
revision:
- label: is_or_was_associated_with
type: slot
- label: Place
type: class
- orignal_slot_id: https://nde.nl/ontology/hc/slot/has_auxiliary_place_type
revision:
- label: has_or_had_type
type: slot
- label: PlaceType
type: class
- label: includes_or_included
type: slot
- label: PlaceTypes
type: class
- orignal_slot_id: https://nde.nl/ontology/hc/slot/has_auxiliary_platform
revision:
- label: is_or_was_associated_with
type: slot
- label: Platform
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_auxiliary_platform_type
revision:
- label: has_or_had_type
type: slot
- label: PlatformType
type: class
- label: includes_or_included
type: slot
- label: PlatformTypes
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_av_equipment
revision:
- label: has_or_had_equipment
type: slot
- label: AVEquipment
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_availability_timespan
revision:
- label: has_or_had_time_interval
type: slot
- label: TimeSpan
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_available_caption_language
revision:
- label: has_or_had_caption
type: slot
- label: Caption
type: class
- label: has_or_had_language
type: slot
- label: Language
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_average_entry_duration_seconds
revision:
- label: had_or_had_time_interval
type: slot
- label: TimeSpan
type: class
- label: has_or_had_mean
type: slot
- label: MeanValue
type: class
- label: has_or_had_unit
type: slot
- label: Unit
type: class
value: seconds
- original_slot_id: https://nde.nl/ontology/hc/slot/has_average_scene_duration_seconds
revision:
- label: has_or_had_dhad_or_had_time_intervaluration
type: slot
- label: TimeSpan
type: class
- label: has_or_had_mean
type: slot
- label: MeanValue
type: class
- label: has_or_had_unit
type: slot
- label: Unit
type: class
value: seconds
- original_slot_id: https://nde.nl/ontology/hc/slot/has_boundary
revision:
- label: has_or_had_boundary
type: slot
- label: Boundary
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_budget
revision:
- label: has_or_had_budget
type: slot
- label: Budget
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_climate_control
revision:
- label: provides_or_provided
type: slot
- label: ClimateControl
type: class
- orignal_slot_id: https://nde.nl/ontology/hc/slot/has_clipping
revision:
- label: contains_or_contained
type: slot
- label: Clipping
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has-computer-terminals
revision:
- label: has_or_had_equipment
type: slot
- label: ComputerTerminal
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_deacidification_facility
revision:
- label: provides_or_provided
type: slot
- label: DeacidificationFacility
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_derived_observation
revision:
- label: refers_or_referred_to
type: slot
- label: Entity
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_feature_type
revision:
- label: has_or_had_type
type: slot
- label: FeatureType
type: class
- label: includes_or_included
type: slot
- label: FeatureTypes
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_fellows_program
revision:
- label: has_or_had_program
type: slot
- label: FellowsProgram
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_forklift_access
revision:
- label: provides_or_provided
type: slot
- label: ForkliftAccess
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_fume_hood
revision:
- label: provides_or_provided
type: slot
- label: FumeHood
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_geospatial_location
revision:
- label: has_or_had_location
type: slot
- label: GeospatialLocation
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_hands_on_facility
revision:
- label: provides_or_provided
type: slot
- label: HandsOnFacility
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_imaging_equipment
revision:
- label: has_or_had_equipment
type: slot
- label: ImagingEquipment
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_link
revision:
- label: has_or_had_url
type: slot
- label: URL
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_loading_dock
revision:
- label: provides_or_provided
type: slot
- label: LoadingDock
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_local_collection
revision:
- label: has_or_had_collection
type: slot
- label: LocalCollection
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has-lockers
revision:
- label: provides_or_provided
type: slot
- label: Locker
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_michelin_star
revision:
- label: has_or_had_rating
type: slot
- label: MichelinStarRating
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has-microfilm-readers
revision:
- label: has_or_had_equipment
type: slot
- label: MicrofilmReader
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_narrower_instance
revision:
- label: has_or_had_hyponym
type: slot
- label: Hyponym
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_observation
revision:
- label: refers_or_referred_to
type: slot
- label: Entity
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_operational_archive
revision:
- label: has_or_had_archive
type: slot
- label: OperationalArchive
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_operational_unit
revision:
- label: has_or_had_section
type: slot
- label: OperationalUnit
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_abbreviation
revision:
- label: has_or_had_label
type: slot
- label: Label
type: class
- label: has_or_had_type
type: slot
- label: LabelType
type: class
- label: includes_or_included
type: slot
- label: LabelTypes
type: class
note: AbbreviationLabel class is defined in the LinkML file
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_about_text
revision:
- label: has_or_had_description
type: slot
- label: Description
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_academic_affiliation
revision:
- label: is_or_was_affiliated_with
type: slot
- label: AcademicInstitution
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_academic_program
revision:
- label: has_or_had_program
type: slot
- label: AcademicProgram
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_condition
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_control
revision:
- label: has_or_had_policy
type: slot
- label: AccessControl
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_description
revision:
- label: has_or_had_description
type: slot
- label: Description
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_frequency
revision:
- label: offers_or_offered
type: slot
- label: Access
type: class
- label: has_or_had_frequency
type: slot
- label: Frequency
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_level
revision:
- label: has_or_had_level
type: slot
- label: AccessLevel
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_management
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_policy
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_policy_reference
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_restriction
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_right
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_trigger_event
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- label: allows_or_allowed
type: slot
- label: Access
type: class
- label: poses_or_posed_condition
type: slot
- label: Condition
type: class
#https://nde.nl/ontology/hc/slot/has_or_had_access_trigger_event

View file

@ -236,6 +236,8 @@ const createProfileFromSearchResult = (result: PersonSearchResult): ProfileDetai
interface ReviewStats {
total_profiles: number;
profiles_with_candidates: number;
matched_profiles?: number; // Profiles with at least one confirmed match
pending_profiles?: number; // Profiles still needing review
wcms_only_count: number; // WCMS profiles without LinkedIn candidates
total_wcms_in_index: number; // Total in WCMS email index
total_candidates: number;
@ -1039,7 +1041,7 @@ export default function EntityReviewPage() {
{/* Compact Stats Dashboard */}
{stats && (
<div className="stats-dashboard compact">
<Tooltip content={language === 'nl' ? 'Toon alle profielen' : 'Show all profiles'} position="bottom">
<Tooltip content={language === 'nl' ? 'WCMS profielen met LinkedIn kandidaten' : 'WCMS profiles with LinkedIn candidates'} position="bottom">
<div
className={`stat-card clickable ${statsFilter === 'all' ? 'active' : ''}`}
onClick={() => { setStatsFilter('all'); setPage(1); }}
@ -1048,41 +1050,26 @@ export default function EntityReviewPage() {
<span className="stat-label">Profielen</span>
</div>
</Tooltip>
<Tooltip content={language === 'nl' ? 'Totaal aantal kandidaat-matches' : 'Total candidate matches'} position="bottom">
<div className="stat-card">
<span className="stat-value">{stats.total_candidates.toLocaleString()}</span>
<span className="stat-label">Kandidaten</span>
</div>
</Tooltip>
<Tooltip content={language === 'nl' ? 'Toon alleen beoordeelde profielen' : 'Show reviewed profiles only'} position="bottom">
<div
className={`stat-card success clickable ${statsFilter === 'reviewed' ? 'active' : ''}`}
onClick={() => { setStatsFilter('reviewed'); setPage(1); }}
>
<span className="stat-value">{stats.reviewed_candidates.toLocaleString()}</span>
<span className="stat-label">Beoordeeld</span>
</div>
</Tooltip>
<Tooltip content={language === 'nl' ? 'Toon profielen met bevestigde matches' : 'Show profiles with confirmed matches'} position="bottom">
<Tooltip content={language === 'nl' ? 'Profielen met bevestigde match (klaar!)' : 'Profiles with confirmed match (done!)'} position="bottom">
<div
className={`stat-card match clickable ${statsFilter === 'matched' ? 'active' : ''}`}
onClick={() => { setStatsFilter('matched'); setPage(1); }}
>
<CheckCircle size={14} className="stat-icon" />
<span className="stat-value">{stats.decisions.match.toLocaleString()}</span>
<span className="stat-value">{(stats.matched_profiles || stats.decisions.match).toLocaleString()}</span>
<span className="stat-label">{language === 'nl' ? 'Gematcht' : 'Matched'}</span>
</div>
</Tooltip>
<Tooltip content={language === 'nl' ? 'Toon alleen profielen met openstaande reviews' : 'Show profiles with pending reviews'} position="bottom">
<Tooltip content={language === 'nl' ? 'Profielen nog te reviewen (geen match gevonden)' : 'Profiles still to review (no match found yet)'} position="bottom">
<div
className={`stat-card warning clickable ${statsFilter === 'pending' ? 'active' : ''}`}
onClick={() => { setStatsFilter('pending'); setPage(1); }}
>
<span className="stat-value">{stats.pending_candidates.toLocaleString()}</span>
<span className="stat-value">{(stats.pending_profiles || stats.pending_candidates).toLocaleString()}</span>
<span className="stat-label">In afwachting</span>
</div>
</Tooltip>
<Tooltip content={language === 'nl' ? 'WCMS profielen zonder LinkedIn kandidaten - klaar voor zoeken' : 'WCMS profiles without LinkedIn candidates - ready for search'} position="bottom">
<Tooltip content={language === 'nl' ? 'WCMS profielen zonder LinkedIn kandidaten - zoek handmatig' : 'WCMS profiles without LinkedIn candidates - search manually'} position="bottom">
<div
className={`stat-card info clickable ${statsFilter === 'wcms_only' ? 'active' : ''}`}
onClick={() => { setStatsFilter('wcms_only'); setWcmsOnlyPage(1); }}
@ -1100,12 +1087,14 @@ export default function EntityReviewPage() {
</div>
</Tooltip>
)}
<div className="stat-card progress">
<span className="stat-value">{stats.review_progress_percent}%</span>
<div className="progress-bar">
<div className="progress-fill" style={{ width: `${stats.review_progress_percent}%` }} />
<Tooltip content={language === 'nl' ? `Voortgang: ${stats.matched_profiles || stats.decisions.match} van ${stats.profiles_with_candidates} profielen gematcht` : `Progress: ${stats.matched_profiles || stats.decisions.match} of ${stats.profiles_with_candidates} profiles matched`} position="bottom">
<div className="stat-card progress">
<span className="stat-value">{stats.review_progress_percent}%</span>
<div className="progress-bar">
<div className="progress-fill" style={{ width: `${stats.review_progress_percent}%` }} />
</div>
</div>
</div>
</Tooltip>
</div>
)}

View file

@ -1,12 +1,12 @@
{
"generated": "2026-01-22T21:35:10.346Z",
"generated": "2026-01-23T10:04:15.652Z",
"schemaRoot": "/schemas/20251121/linkml",
"totalFiles": 3037,
"totalFiles": 3036,
"categoryCounts": {
"main": 4,
"class": 970,
"class": 980,
"enum": 155,
"slot": 1904,
"slot": 1893,
"module": 4
},
"categories": [
@ -565,6 +565,11 @@
"path": "modules/classes/CallForApplication.yaml",
"category": "class"
},
{
"name": "CanonicalForm",
"path": "modules/classes/CanonicalForm.yaml",
"category": "class"
},
{
"name": "CantonalArchive",
"path": "modules/classes/CantonalArchive.yaml",
@ -585,6 +590,21 @@
"path": "modules/classes/Capacity.yaml",
"category": "class"
},
{
"name": "CapacityType",
"path": "modules/classes/CapacityType.yaml",
"category": "class"
},
{
"name": "CapacityTypes",
"path": "modules/classes/CapacityTypes.yaml",
"category": "class"
},
{
"name": "Caption",
"path": "modules/classes/Caption.yaml",
"category": "class"
},
{
"name": "CareerEntry",
"path": "modules/classes/CareerEntry.yaml",
@ -1260,11 +1280,26 @@
"path": "modules/classes/DarkArchiveRecordSetTypes.yaml",
"category": "class"
},
{
"name": "DataFormat",
"path": "modules/classes/DataFormat.yaml",
"category": "class"
},
{
"name": "DataFormatTypes",
"path": "modules/classes/DataFormatTypes.yaml",
"category": "class"
},
{
"name": "DataLicensePolicy",
"path": "modules/classes/DataLicensePolicy.yaml",
"category": "class"
},
{
"name": "DataSensitivityLevel",
"path": "modules/classes/DataSensitivityLevel.yaml",
"category": "class"
},
{
"name": "DataServiceEndpoint",
"path": "modules/classes/DataServiceEndpoint.yaml",
@ -2390,6 +2425,11 @@
"path": "modules/classes/MailingListArchiveRecordSetTypes.yaml",
"category": "class"
},
{
"name": "MainPart",
"path": "modules/classes/MainPart.yaml",
"category": "class"
},
{
"name": "MappingType",
"path": "modules/classes/MappingType.yaml",
@ -2880,6 +2920,11 @@
"path": "modules/classes/OutdoorSite.yaml",
"category": "class"
},
{
"name": "OutputData",
"path": "modules/classes/OutputData.yaml",
"category": "class"
},
{
"name": "Overview",
"path": "modules/classes/Overview.yaml",
@ -4210,6 +4255,11 @@
"path": "modules/classes/Timestamp.yaml",
"category": "class"
},
{
"name": "Title",
"path": "modules/classes/Title.yaml",
"category": "class"
},
{
"name": "TitleType",
"path": "modules/classes/TitleType.yaml",
@ -5737,46 +5787,6 @@
"path": "modules/slots/begin_of_the_end.yaml",
"category": "slot"
},
{
"name": "canonical_value",
"path": "modules/slots/canonical_value.yaml",
"category": "slot"
},
{
"name": "capacity",
"path": "modules/slots/capacity.yaml",
"category": "slot"
},
{
"name": "capacity_type",
"path": "modules/slots/capacity_type.yaml",
"category": "slot"
},
{
"name": "capacity_value",
"path": "modules/slots/capacity_value.yaml",
"category": "slot"
},
{
"name": "capital_budget",
"path": "modules/slots/capital_budget.yaml",
"category": "slot"
},
{
"name": "caption_available",
"path": "modules/slots/caption_available.yaml",
"category": "slot"
},
{
"name": "card_description",
"path": "modules/slots/card_description.yaml",
"category": "slot"
},
{
"name": "card_description_en",
"path": "modules/slots/card_description_en.yaml",
"category": "slot"
},
{
"name": "card_image_url",
"path": "modules/slots/card_image_url.yaml",
@ -6497,31 +6507,11 @@
"path": "modules/slots/custody_received_by.yaml",
"category": "slot"
},
{
"name": "cut_count",
"path": "modules/slots/cut_count.yaml",
"category": "slot"
},
{
"name": "data_format",
"path": "modules/slots/data_format.yaml",
"category": "slot"
},
{
"name": "data_license_policy",
"path": "modules/slots/data_license_policy.yaml",
"category": "slot"
},
{
"name": "data_repository",
"path": "modules/slots/data_repository.yaml",
"category": "slot"
},
{
"name": "data_sensitivity",
"path": "modules/slots/data_sensitivity.yaml",
"category": "slot"
},
{
"name": "data_source_whatsapp",
"path": "modules/slots/data_source_whatsapp.yaml",
@ -6532,21 +6522,6 @@
"path": "modules/slots/data_tier.yaml",
"category": "slot"
},
{
"name": "dataset_description",
"path": "modules/slots/dataset_description.yaml",
"category": "slot"
},
{
"name": "dataset_identifier",
"path": "modules/slots/dataset_identifier.yaml",
"category": "slot"
},
{
"name": "dataset_title",
"path": "modules/slots/dataset_title.yaml",
"category": "slot"
},
{
"name": "date",
"path": "modules/slots/date.yaml",
@ -9067,6 +9042,11 @@
"path": "modules/slots/has_or_had_capacity.yaml",
"category": "slot"
},
{
"name": "has_or_had_caption",
"path": "modules/slots/has_or_had_caption.yaml",
"category": "slot"
},
{
"name": "has_or_had_category",
"path": "modules/slots/has_or_had_category.yaml",
@ -9492,6 +9472,11 @@
"path": "modules/slots/has_or_had_location.yaml",
"category": "slot"
},
{
"name": "has_or_had_main_part",
"path": "modules/slots/has_or_had_main_part.yaml",
"category": "slot"
},
{
"name": "has_or_had_managed_by_cm",
"path": "modules/slots/has_or_had_managed_by_cm.yaml",
@ -9622,6 +9607,11 @@
"path": "modules/slots/has_or_had_organizer.yaml",
"category": "slot"
},
{
"name": "has_or_had_output",
"path": "modules/slots/has_or_had_output.yaml",
"category": "slot"
},
{
"name": "has_or_had_owner",
"path": "modules/slots/has_or_had_owner.yaml",
@ -10077,6 +10067,11 @@
"path": "modules/slots/has_or_had_timestamp.yaml",
"category": "slot"
},
{
"name": "has_or_had_title",
"path": "modules/slots/has_or_had_title.yaml",
"category": "slot"
},
{
"name": "has_or_had_token",
"path": "modules/slots/has_or_had_token.yaml",

View file

@ -20,7 +20,8 @@ imports:
- ../slots/has_or_had_business_criticality # was: business_criticality - migrated per Rule 53/56/57 (2026-01-17)
- ./BusinessCriticality
- ../slots/creating_function
- ../slots/data_sensitivity
- ../slots/has_or_had_level # was: data_sensitivity - migrated per Rule 53/56/57 (2026-01-23)
- ./DataSensitivityLevel
- ../slots/estimated_volume
- ../slots/expected_transfer_date
- ../slots/gdpr_relevant
@ -116,7 +117,7 @@ classes:
- has_or_had_status
- has_or_had_business_criticality # was: business_criticality - migrated per Rule 53/56/57 (2026-01-17)
- creating_function
- data_sensitivity
- has_or_had_level # was: data_sensitivity - migrated per Rule 53/56/57 (2026-01-23)
- estimated_volume
- expected_transfer_date
- gdpr_relevant
@ -211,11 +212,19 @@ classes:
examples:
- value: '2027-01-01'
description: Oldest records eligible for transfer in 2027
data_sensitivity:
range: string
has_or_had_level: # was: data_sensitivity - migrated per Rule 53/56/57 (2026-01-23)
range: DataSensitivityLevel
inlined: true
required: false
description: >-
Data sensitivity classification level.
Standard codes: PUBLIC, INTERNAL, CONFIDENTIAL, STRICTLY_CONFIDENTIAL,
PERSONAL_DATA, SPECIAL_CATEGORY
examples:
- value: CONFIDENTIAL - Personnel data
- value:
has_or_had_label: Confidential
has_or_had_short_code: CONFIDENTIAL
has_or_had_description: Personnel data - need-to-know basis
description: HR files classification
gdpr_relevant:
range: boolean
@ -314,7 +323,10 @@ classes:
retention_schedule: Museum Retention Schedule 2020, cat. 1.1
retention_period_years: 10
expected_transfer_date: '2028-01-01'
data_sensitivity: CONFIDENTIAL
has_or_had_level: # was: data_sensitivity
has_or_had_label: Confidential
has_or_had_short_code: CONFIDENTIAL
has_or_had_description: Confidential correspondence - need-to-know basis
gdpr_relevant: true
has_or_had_business_criticality: # was: business_criticality - migrated to BusinessCriticality class
has_or_had_label: HIGH
@ -344,7 +356,10 @@ classes:
primary_system: https://nde.nl/ontology/hc/platform/rm-workday
retention_schedule: Museum Retention Schedule 2020, cat. 3.2
retention_period_years: 20
data_sensitivity: SPECIAL_CATEGORY - Personnel data
has_or_had_level: # was: data_sensitivity
has_or_had_label: Special Category Data
has_or_had_short_code: SPECIAL_CATEGORY
has_or_had_description: Personnel data - GDPR Article 9 sensitive personal data
gdpr_relevant: true
has_or_had_business_criticality: # was: business_criticality - migrated to BusinessCriticality class
has_or_had_label: CRITICAL
@ -376,7 +391,10 @@ classes:
- https://nde.nl/ontology/hc/platform/rm-adlib
retention_schedule: Permanent - linked to collection objects
retention_period_years: null
data_sensitivity: INTERNAL
has_or_had_level: # was: data_sensitivity
has_or_had_label: Internal
has_or_had_short_code: INTERNAL
has_or_had_description: For internal staff use only
gdpr_relevant: false
has_or_had_business_criticality: # was: business_criticality - migrated to BusinessCriticality class
has_or_had_label: HIGH

View file

@ -0,0 +1,117 @@
id: https://nde.nl/ontology/hc/class/DataSensitivityLevel
name: data_sensitivity_level_class
title: DataSensitivityLevel Class
description: >-
Data sensitivity classification level for records and information assets.
Used to categorize the confidentiality requirements and access restrictions
for administrative records, documents, and data systems.
Based on common information classification schemes including:
- ISO 27001 information security standards
- GDPR special category data requirements
- Dutch government classification (Rijksoverheid)
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dcterms: http://purl.org/dc/terms/
schema: http://schema.org/
imports:
- linkml:types
- ../slots/has_or_had_label
- ../slots/has_or_had_description
- ../slots/has_or_had_short_code
default_prefix: hc
classes:
DataSensitivityLevel:
class_uri: hc:DataSensitivityLevel
description: >-
Data sensitivity classification level.
**Standard Classification Levels**:
| Level | Short Code | Description | Access |
|-------|------------|-------------|--------|
| Public | PUBLIC | No restrictions on disclosure | Anyone |
| Internal | INTERNAL | For internal use only | Staff only |
| Confidential | CONFIDENTIAL | Need-to-know basis | Authorized staff |
| Strictly Confidential | STRICTLY_CONFIDENTIAL | Highly restricted | Named individuals |
| Personal Data | PERSONAL_DATA | Contains PII (GDPR Article 6) | Data subjects + authorized |
| Special Category | SPECIAL_CATEGORY | Sensitive personal data (GDPR Article 9) | Strictly controlled |
**GDPR Alignment**:
- PERSONAL_DATA: Covers GDPR Article 6 personal data
- SPECIAL_CATEGORY: Covers GDPR Article 9 special categories (health, religion,
ethnicity, political opinions, trade union membership, genetic/biometric data,
sexual orientation)
**Dublin Core**: Maps to dcterms:accessRights for access classification.
exact_mappings:
- dcterms:accessRights
close_mappings:
- schema:accessMode
slots:
- has_or_had_label
- has_or_had_short_code
- has_or_had_description
slot_usage:
has_or_had_label:
description: Human-readable name for the sensitivity level.
range: string
required: true
examples:
- value: "Public"
description: No access restrictions
- value: "Strictly Confidential"
description: Highest restriction level
has_or_had_short_code:
description: >-
Short code identifier for the sensitivity level.
Standard codes: PUBLIC, INTERNAL, CONFIDENTIAL, STRICTLY_CONFIDENTIAL,
PERSONAL_DATA, SPECIAL_CATEGORY
range: string
required: true
pattern: "^[A-Z][A-Z0-9_]*$"
examples:
- value: "PUBLIC"
description: No restrictions
- value: "CONFIDENTIAL"
description: Need-to-know basis
- value: "SPECIAL_CATEGORY"
description: GDPR Article 9 sensitive data
has_or_had_description:
description: Detailed description of what this sensitivity level means and when to apply it.
range: string
required: false
examples:
- value: "Contains employee health records - requires explicit consent and strict access controls"
description: SPECIAL_CATEGORY example
annotations:
specificity_score: 0.45
specificity_rationale: >-
Data sensitivity levels are moderately specific - used primarily in
records management and information governance contexts.
custodian_types: '["A", "O", "R"]'
custodian_types_rationale: >-
Most relevant for Archives (A), Official institutions (O), and
Research centers (R) that manage sensitive records.
examples:
- value:
has_or_had_label: "Confidential"
has_or_had_short_code: "CONFIDENTIAL"
has_or_had_description: "Need-to-know basis - restricted to authorized personnel"
description: Standard confidential classification
- value:
has_or_had_label: "Special Category Data"
has_or_had_short_code: "SPECIAL_CATEGORY"
has_or_had_description: "GDPR Article 9 sensitive personal data - health records, religious affiliation"
description: GDPR special category classification
- value:
has_or_had_label: "Personnel Data"
has_or_had_short_code: "PERSONAL_DATA"
has_or_had_description: "Contains employee personal information subject to GDPR"
description: Personal data classification for HR records

View file

@ -0,0 +1,107 @@
# Title class
# Created 2026-01-22 per slot_fixes.yaml revision for dataset_title (Rule 53)
#
# Generation date: 2026-01-22
# Rule compliance: 53 (slot_fixes.yaml), 39 (RiC-O naming)
id: https://nde.nl/ontology/hc/class/Title
name: title_class
title: Title Class
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dct: http://purl.org/dc/terms/
schema: http://schema.org/
default_prefix: hc
imports:
- linkml:types
- ../slots/has_or_had_language
classes:
Title:
class_uri: hc:Title
description: |
A structured title with optional language tag and variant types.
**DEFINITION**:
Title represents a named designation for a resource. Titles can:
- Have language tags for multilingual support
- Have different types (main, alternative, translated, abbreviated)
- Change over time (use has_or_had_title slot)
**USE CASES**:
1. **Dataset titles**: "Dutch Heritage Collections 2024"
2. **Document titles**: "Conservation Guidelines for Paper"
3. **Collection titles**: "Van Gogh Letters"
4. **Work titles**: "The Night Watch"
**TITLE TYPES**:
| Type | Description |
|------|-------------|
| main | Primary/official title |
| alternative | Other names, subtitles |
| translated | Title in another language |
| abbreviated | Short form, acronym |
**ONTOLOGY ALIGNMENT**:
- **Primary** (`class_uri`): `hc:Title` - Heritage Custodian class
- **Close**: `dct:title` property domain
Created as part of dataset_title migration per slot_fixes.yaml (Rule 53).
close_mappings:
- schema:name
slots:
- title_text
- title_type
- has_or_had_language
attributes:
title_text:
range: string
required: true
description: The actual title text.
title_type:
range: string
description: |
Type of title: main, alternative, translated, abbreviated.
slot_usage:
has_or_had_language:
description: Language of the title (ISO 639-1 code).
examples:
- value:
language_code: "nl"
description: Dutch language title
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Titles applicable to all heritage resources.
specificity_score: 0.35
specificity_rationale: Generic class for title representation.
comments:
- "Created 2026-01-22 per slot_fixes.yaml dataset_title migration"
- "Supports multilingual titles with language tags"
- "Used with has_or_had_title slot"
examples:
- value:
title_text: "Collectie Nederland"
title_type: "main"
has_or_had_language:
language_code: "nl"
description: "Dutch main title"
- value:
title_text: "Collection Netherlands"
title_type: "translated"
has_or_had_language:
language_code: "en"
description: "English translated title"

View file

@ -25,9 +25,15 @@ imports:
- ./TemplateSpecificityTypes
- ./MetadataStandard # For has_or_had_standard range
- ../slots/cessation_observed_in
- ../slots/dataset_description
- ../slots/dataset_identifier
- ../slots/dataset_title
# REMOVED 2026-01-22: ../slots/dataset_description - migrated to has_or_had_description + Description (Rule 53)
- ../slots/has_or_had_description
- ./Description
# REMOVED 2026-01-22: ../slots/dataset_identifier - migrated to has_or_had_identifier + Identifier (Rule 53)
- ../slots/has_or_had_identifier
- ./Identifier
# REMOVED 2026-01-22: ../slots/dataset_title - migrated to has_or_had_title + Title (Rule 53)
- ../slots/has_or_had_title
- ./Title
- ../slots/download_endpoint
- ../slots/has_availability_timespan
- ../slots/has_or_had_linked_data_endpoint
@ -1225,9 +1231,9 @@ classes:
class_uri: dcat:Dataset
slots:
- has_availability_timespan
- dataset_description
- dataset_identifier
- dataset_title
- has_or_had_description # was: dataset_description - migrated per Rule 53 (2026-01-22)
- has_or_had_identifier # was: dataset_identifier - migrated per Rule 53 (2026-01-22)
- has_or_had_title # was: dataset_title - migrated per Rule 53 (2026-01-22)
- download_endpoint
- linked_data_access
- is_or_was_published_by # was: published_by - migrated per Rule 53/56 (2026-01-17)

View file

@ -0,0 +1,67 @@
# has_or_had_title slot
# Created 2026-01-22 per slot_fixes.yaml revision for dataset_title (Rule 53)
#
# Generation date: 2026-01-22
# Rule compliance: 53 (slot_fixes.yaml), 39 (RiC-O naming), 50 (ontology mapping)
id: https://nde.nl/ontology/hc/slot/has_or_had_title
name: has_or_had_title_slot
title: Has Or Had Title Slot
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dct: http://purl.org/dc/terms/
schema: http://schema.org/
default_prefix: hc
imports:
- linkml:types
slots:
has_or_had_title:
slot_uri: dct:title
description: |
The title or name of a resource.
**RiC-O Temporal Pattern**:
Uses `hasOrHad*` pattern to indicate titles can change over time.
Resources may have different titles at different points in their lifecycle.
**USE CASES**:
1. Dataset titles
2. Document titles
3. Collection titles
4. Work titles
**ONTOLOGY ALIGNMENT**:
- **Primary** (`slot_uri`): `dct:title` - Dublin Core title
- **Close**: `schema:name` - Schema.org name
- **Close**: `rdfs:label` - RDF Schema label
Created as part of dataset_title migration per slot_fixes.yaml (Rule 53).
range: Title
multivalued: false
inlined: true
exact_mappings:
- dct:title
close_mappings:
- schema:name
- rdfs:label
annotations:
custodian_types: '["*"]'
custodian_types_rationale: Titles applicable to all resource types.
rico_pattern: hasOrHadTitle
migration_date: "2026-01-22"
replaces_slots: "dataset_title"
examples:
- value:
title_text: "Dutch Heritage Collections Dataset"
language: "en"
description: "Dataset title in English"

View file

@ -178,12 +178,12 @@
"__ARCHIVED_20260122__data_format.yaml",
"data_license_policy.yaml",
"data_repository.yaml",
"data_sensitivity.yaml",
"__ARCHIVED_20260123__data_sensitivity.yaml",
"data_source_whatsapp.yaml",
"data_tier.yaml",
"dataset_description.yaml",
"dataset_identifier.yaml",
"dataset_title.yaml",
"__ARCHIVED_20260122__dataset_description.yaml",
"__ARCHIVED_20260122__dataset_identifier.yaml",
"__ARCHIVED_20260122__dataset_title.yaml",
"date.yaml",
"date_created.yaml",
"date_identified.yaml",
@ -886,6 +886,7 @@
"has_or_had_thumbnail.yaml",
"has_or_had_time_interval.yaml",
"has_or_had_timestamp.yaml",
"has_or_had_title.yaml",
"has_or_had_token.yaml",
"has_or_had_tracked_in_cm.yaml",
"has_or_had_transmission_method.yaml",

View file

@ -11488,6 +11488,25 @@ fixes:
type: slot
- label: DataSensitivityLevel
type: Class
processed:
status: true
date: '2026-01-23'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: data_sensitivity** ✅ COMPLETE
**Pattern**: data_sensitivity → has_or_had_level + DataSensitivityLevel
**Files Created**:
- DataSensitivityLevel.yaml: Structured class for data sensitivity classification
with standard codes (PUBLIC, INTERNAL, CONFIDENTIAL, STRICTLY_CONFIDENTIAL,
PERSONAL_DATA, SPECIAL_CATEGORY)
**Files Modified**:
- CustodianAdministration.yaml: Replaced data_sensitivity import and slot with
has_or_had_level + DataSensitivityLevel, updated slot_usage and all examples
**Archived**: modules/slots/archive/data_sensitivity_archived_20260123.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/data_source_whatsapp
revision:
- label: has_or_had_source
@ -11506,18 +11525,61 @@ fixes:
type: slot
- label: Description
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: dataset_description** ✅ COMPLETE
**Pattern**: dataset_description → has_or_had_description + Description
**Files Modified**:
- WebPortalTypes.yaml: Updated imports and slots list
**Archived**: modules/slots/archive/dataset_description_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/dataset_identifier
revision:
- label: has_or_had_identifier
type: slot
- label: Identifier
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: dataset_identifier** ✅ COMPLETE
**Pattern**: dataset_identifier → has_or_had_identifier + Identifier
**Files Modified**:
- WebPortalTypes.yaml: Updated imports and slots list
**Archived**: modules/slots/archive/dataset_identifier_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/dataset_title
revision:
- label: has_or_had_title
type: slot
- label: Title
type: class
processed:
status: true
date: '2026-01-22'
agent: claude-claude-sonnet-4-20250514
notes: |
**Migration: dataset_title** ✅ COMPLETE
**Pattern**: dataset_title → has_or_had_title + Title
**Files Created**:
- has_or_had_title.yaml: Generic title slot
- Title.yaml: Structured title class
**Files Modified**:
- WebPortalTypes.yaml: Updated imports and slots list
**Archived**: modules/slots/archive/dataset_title_archived_20260122.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/date_value
revision:
- label: temporal_extent
@ -15428,4 +15490,253 @@ fixes:
type: slot
- label: Budget
type: class
# https://nde.nl/ontology/hc/slot/has_climate_control
- original_slot_id: https://nde.nl/ontology/hc/slot/has_climate_control
revision:
- label: provides_or_provided
type: slot
- label: ClimateControl
type: class
- orignal_slot_id: https://nde.nl/ontology/hc/slot/has_clipping
revision:
- label: contains_or_contained
type: slot
- label: Clipping
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has-computer-terminals
revision:
- label: has_or_had_equipment
type: slot
- label: ComputerTerminal
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_deacidification_facility
revision:
- label: provides_or_provided
type: slot
- label: DeacidificationFacility
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_derived_observation
revision:
- label: refers_or_referred_to
type: slot
- label: Entity
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_feature_type
revision:
- label: has_or_had_type
type: slot
- label: FeatureType
type: class
- label: includes_or_included
type: slot
- label: FeatureTypes
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_fellows_program
revision:
- label: has_or_had_program
type: slot
- label: FellowsProgram
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_forklift_access
revision:
- label: provides_or_provided
type: slot
- label: ForkliftAccess
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_fume_hood
revision:
- label: provides_or_provided
type: slot
- label: FumeHood
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_geospatial_location
revision:
- label: has_or_had_location
type: slot
- label: GeospatialLocation
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_hands_on_facility
revision:
- label: provides_or_provided
type: slot
- label: HandsOnFacility
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_imaging_equipment
revision:
- label: has_or_had_equipment
type: slot
- label: ImagingEquipment
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_link
revision:
- label: has_or_had_url
type: slot
- label: URL
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_loading_dock
revision:
- label: provides_or_provided
type: slot
- label: LoadingDock
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_local_collection
revision:
- label: has_or_had_collection
type: slot
- label: LocalCollection
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has-lockers
revision:
- label: provides_or_provided
type: slot
- label: Locker
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_michelin_star
revision:
- label: has_or_had_rating
type: slot
- label: MichelinStarRating
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has-microfilm-readers
revision:
- label: has_or_had_equipment
type: slot
- label: MicrofilmReader
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_narrower_instance
revision:
- label: has_or_had_hyponym
type: slot
- label: Hyponym
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_observation
revision:
- label: refers_or_referred_to
type: slot
- label: Entity
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_operational_archive
revision:
- label: has_or_had_archive
type: slot
- label: OperationalArchive
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_operational_unit
revision:
- label: has_or_had_section
type: slot
- label: OperationalUnit
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_abbreviation
revision:
- label: has_or_had_label
type: slot
- label: Label
type: class
- label: has_or_had_type
type: slot
- label: LabelType
type: class
- label: includes_or_included
type: slot
- label: LabelTypes
type: class
note: AbbreviationLabel class is defined in the LinkML file
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_about_text
revision:
- label: has_or_had_description
type: slot
- label: Description
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_academic_affiliation
revision:
- label: is_or_was_affiliated_with
type: slot
- label: AcademicInstitution
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_academic_program
revision:
- label: has_or_had_program
type: slot
- label: AcademicProgram
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_condition
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_control
revision:
- label: has_or_had_policy
type: slot
- label: AccessControl
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_description
revision:
- label: has_or_had_description
type: slot
- label: Description
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_frequency
revision:
- label: offers_or_offered
type: slot
- label: Access
type: class
- label: has_or_had_frequency
type: slot
- label: Frequency
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_level
revision:
- label: has_or_had_level
type: slot
- label: AccessLevel
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_management
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_policy
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_policy_reference
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_restriction
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_right
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- original_slot_id: https://nde.nl/ontology/hc/slot/has_or_had_access_trigger_event
revision:
- label: has_or_had_policy
type: slot
- label: AccessPolicy
type: class
- label: allows_or_allowed
type: slot
- label: Access
type: class
- label: poses_or_posed_condition
type: slot
- label: Condition
type: class
#https://nde.nl/ontology/hc/slot/has_or_had_access_trigger_event

View file

@ -1198,6 +1198,37 @@ def find_entity_file(linkedin_slug: str) -> Optional[Path]:
return None
def find_ppid_file_by_linkedin_slug(linkedin_slug: str) -> Optional[Path]:
"""
Find a PPID file in data/person/ that corresponds to a LinkedIn slug.
PPID files may contain the linkedin_slug in their metadata.
This searches for files that match the name pattern from the slug.
"""
if not linkedin_slug or not PERSON_DATA_DIR.exists():
return None
# Normalize slug for matching
norm_slug = linkedin_slug.replace('%', '').replace('', '').replace('', '')
# Convert slug to uppercase name pattern (e.g., "jan-de-vries" -> "JAN-DE-VRIES")
name_pattern = norm_slug.upper()
# Look for PPID files containing this name pattern
# PPID format: ID_XX-XX-XXX_XXXX_XX-XX-XXX_XXXX_NAME-TOKENS.json
for f in PERSON_DATA_DIR.glob(f'ID_*_{name_pattern}*.json'):
try:
with open(f, 'r') as file:
data = json.load(file)
# Verify it's the right person by checking linkedin_slug
if data.get('linkedin_slug') == linkedin_slug or data.get('linkedin_slug') == norm_slug:
return f
except (json.JSONDecodeError, IOError):
continue
return None
async def update_entity_with_wcms_identifiers(
linkedin_slug: str,
wcms_ppid: str,
@ -1209,6 +1240,10 @@ async def update_entity_with_wcms_identifiers(
"""
Update or create an entity file with WCMS identifiers when a match is confirmed.
IMPORTANT: Updates BOTH:
1. PPID file in data/person/ (authoritative source)
2. Entity file in data/custodian/person/entity/ (backward compatibility)
If entity file exists: Updates it with wcms_identifiers.
If entity file doesn't exist: Fetches LinkedIn profile via Exa and creates entity file.
@ -1217,6 +1252,7 @@ async def update_entity_with_wcms_identifiers(
Returns a status message string or None if nothing was done.
"""
now = datetime.now(timezone.utc)
results = []
# Get WCMS identifiers
wcms_ids = get_wcms_identifiers(wcms_ppid, wcms_email)
@ -1224,7 +1260,79 @@ async def update_entity_with_wcms_identifiers(
print(f"Warning: Could not load WCMS identifiers for {wcms_ppid}")
return "WCMS identifiers not found"
# Check if entity file already exists
# ========================================================================
# STEP 1: Update PPID file in data/person/ (authoritative source)
# ========================================================================
ppid_file = find_ppid_file_by_linkedin_slug(linkedin_slug)
if ppid_file:
try:
with open(ppid_file, 'r') as f:
ppid_data = json.load(f)
# Add or update WCMS identifiers
ppid_data['wcms_identifiers'] = wcms_ids
# Add WCMS activity data if available
wcms_email_index = load_wcms_email_index()
if wcms_email and wcms_email.lower() in wcms_email_index:
wcms_user_data = wcms_email_index[wcms_email.lower()]
ppid_data['wcms_activity'] = {
'status': wcms_user_data.get('status'),
'roles': wcms_user_data.get('roles', []),
'registered_since': wcms_user_data.get('registered_since'),
'last_access': wcms_user_data.get('last_access'),
}
# Update heritage relevance to mark as confirmed
if 'heritage_relevance' not in ppid_data:
ppid_data['heritage_relevance'] = {}
ppid_data['heritage_relevance']['is_heritage_relevant'] = True
ppid_data['heritage_relevance']['rationale'] = 'Confirmed match via entity resolution review'
# Add web claim for the match confirmation
if 'web_claims' not in ppid_data:
ppid_data['web_claims'] = []
ppid_data['web_claims'].append({
'claim_type': 'entity_resolution_match',
'claim_value': wcms_ppid,
'source_url': 'entity_resolution_review',
'retrieved_on': now.isoformat(),
'statement_created_at': now.isoformat(),
'source_archived_at': now.isoformat(),
'retrieval_agent': 'entity_review_api'
})
# Sync source_urls (non-LinkedIn evidence URLs) to web_claims
if source_urls:
for src in source_urls:
url = src.get('url', '')
if url:
ppid_data['web_claims'].append({
'claim_type': 'source_url',
'claim_value': url,
'source_url': url,
'retrieved_on': src.get('added_at', now.isoformat()),
'statement_created_at': now.isoformat(),
'source_archived_at': src.get('added_at', now.isoformat()),
'retrieval_agent': 'entity_review_api',
'notes': src.get('comment', '')
})
# Write back
with open(ppid_file, 'w', encoding='utf-8') as f:
json.dump(ppid_data, f, indent=2, ensure_ascii=False)
results.append(f"PPID file updated: {ppid_file.name}")
print(f"Updated PPID file: {ppid_file}")
except Exception as e:
print(f"Error updating PPID file: {e}")
results.append(f"Error updating PPID file: {e}")
else:
print(f"No PPID file found for linkedin_slug: {linkedin_slug}")
# ========================================================================
# STEP 2: Update entity file in data/custodian/person/entity/ (backward compat)
# ========================================================================
existing_file = find_entity_file(linkedin_slug)
if existing_file:
@ -1275,10 +1383,10 @@ async def update_entity_with_wcms_identifiers(
with open(existing_file, 'w', encoding='utf-8') as f:
json.dump(entity_data, f, indent=2, ensure_ascii=False)
return f"Entity file updated: {existing_file.name}"
results.append(f"Entity file updated: {existing_file.name}")
except Exception as e:
print(f"Error updating entity file: {e}")
return f"Error updating entity file: {e}"
results.append(f"Error updating entity file: {e}")
else:
# Create new entity file - fetch profile first
@ -1376,10 +1484,13 @@ async def update_entity_with_wcms_identifiers(
status += " with Exa profile data"
else:
status += " (profile fetch unavailable)"
return f"{status}: {filename}"
results.append(f"{status}: {filename}")
except Exception as e:
print(f"Error creating entity file: {e}")
return f"Error creating entity file: {e}"
results.append(f"Error creating entity file: {e}")
# Return combined results
return "; ".join(results) if results else "No files updated"
@router.post("/decision", response_model=ReviewResponse)
@ -1521,6 +1632,10 @@ async def get_review_stats():
"""
Get overall review statistics.
Uses pre-aggregated candidates data.
KEY LOGIC: When a WCMS profile has a confirmed MATCH, all remaining candidates
for that profile are considered "resolved" and NOT counted as pending.
This ensures matched profiles don't inflate the pending count.
"""
# Load candidates from cached file
load_candidates()
@ -1529,9 +1644,11 @@ async def get_review_stats():
return {
"total_profiles": 0,
"profiles_with_candidates": 0,
"matched_profiles": 0,
"total_candidates": 0,
"reviewed_candidates": 0,
"pending_candidates": 0,
"pending_profiles": 0,
"review_progress_percent": 0,
"decisions": {"match": 0, "not_match": 0, "uncertain": 0},
"likely_wrong_person": 0,
@ -1544,36 +1661,65 @@ async def get_review_stats():
likely_wrong_person = 0
decisions = {"match": 0, "not_match": 0, "uncertain": 0}
# Track profiles with at least one match (these are "done")
matched_profiles = set()
# Track pending candidates only from profiles that DON'T have a match
truly_pending_candidates = 0
pending_profiles = 0
for wcms_ppid, wcms_data in _candidates_by_wcms.items():
candidates = wcms_data.get('candidates', [])
total_candidates += len(candidates)
# First pass: check if this profile has ANY match decision
profile_has_match = False
profile_pending_count = 0
for c in candidates:
if c.get('reviewed'):
reviewed_candidates += 1
decision = c.get('review_decision')
if decision in decisions:
decisions[decision] += 1
if decision == 'match':
profile_has_match = True
else:
profile_pending_count += 1
if c.get('is_likely_wrong_person'):
likely_wrong_person += 1
# Get WCMS-only profiles count
# If profile has a match, it's resolved - don't count remaining as pending
if profile_has_match:
matched_profiles.add(wcms_ppid)
elif profile_pending_count > 0:
# Only count as pending if profile has NO match yet
truly_pending_candidates += profile_pending_count
pending_profiles += 1
# Get WCMS-only profiles count (excluding profiles that have been matched)
wcms_only_profiles = load_wcms_only_profiles()
# Filter out any that might have been matched via manual candidate addition
wcms_only_count = len(wcms_only_profiles)
# Total WCMS in email index
wcms_email_index = load_wcms_email_index()
total_wcms_in_index = len(wcms_email_index)
# Calculate progress: matched profiles / total profiles with candidates
profiles_with_candidates = len(_candidates_by_wcms)
match_progress_percent = round(len(matched_profiles) / profiles_with_candidates * 100, 1) if profiles_with_candidates > 0 else 0
return {
"total_profiles": metadata.get('wcms_profiles_processed', 0),
"profiles_with_candidates": len(_candidates_by_wcms),
"profiles_with_candidates": profiles_with_candidates,
"matched_profiles": len(matched_profiles), # Profiles with at least one confirmed match
"pending_profiles": pending_profiles, # Profiles still needing review
"wcms_only_count": wcms_only_count, # WCMS profiles without LinkedIn candidates
"total_wcms_in_index": total_wcms_in_index, # Total in WCMS email index
"total_candidates": total_candidates,
"reviewed_candidates": reviewed_candidates,
"pending_candidates": total_candidates - reviewed_candidates,
"review_progress_percent": round(reviewed_candidates / total_candidates * 100, 1) if total_candidates > 0 else 0,
"pending_candidates": truly_pending_candidates, # Only from profiles WITHOUT a match
"review_progress_percent": match_progress_percent, # Based on matched profiles
"decisions": decisions,
"likely_wrong_person": likely_wrong_person,
"confidence_scoring_version": metadata.get('confidence_scoring_version', '1.0'),