diff --git a/src/oold/validation/meta/1.0.0-rc.3/oold-meta-schema-base.json b/src/oold/validation/meta/1.0.0-rc.3/oold-meta-schema-base.json new file mode 100644 index 0000000..7ce7cf6 --- /dev/null +++ b/src/oold/validation/meta/1.0.0-rc.3/oold-meta-schema-base.json @@ -0,0 +1,248 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://oo-ld.org/latest/meta/oold-meta-schema-base.json", + "$dynamicAnchor": "meta", + "title": "OO-LD dialect meta-schema (body)", + "$comment": "The dialect body: the standard 2020-12 vocabularies plus the x-oold-* keyword syntax. It carries $dynamicAnchor: \"meta\", so nested subschemas (properties, $defs, x-oold-range, ...) recurse into THIS resource and are validated without the document-level obligations. oold-meta-schema.json wraps it and adds those root-only requirements; see that file.", + "allOf": [ + { + "$ref": "https://json-schema.org/draft/2020-12/schema" + }, + { + "$ref": "https://oo-ld.org/latest/meta/oold-ui-meta-schema.json#keywords" + } + ], + "properties": { + "@context": { + "description": "JSON-LD context for instances of this schema. The schema is consumed as a remote JSON-LD context; this entry is ignored by JSON-Schema validators. Only the outer shape is checked here - a context definition is a map, an IRI reference to a remote context, an array combining either, or null (JSON-LD 1.1, Context Definitions). Whether the term definitions inside are well-formed is decided by a JSON-LD processor, not by JSON Schema.", + "anyOf": [ + { + "type": "object" + }, + { + "type": "string", + "format": "iri-reference" + }, + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string", + "format": "iri-reference" + }, + { + "type": "null" + } + ] + } + }, + { + "type": "null" + } + ] + }, + "x-oold-context": { + "description": "Extended term mappings (synonyms): an object keyed by term (a property, class, or value term), each holding a dict keyed by synonym IRI whose value is a JSON-LD term-definition fragment plus an optional strippable x-oold-sssom block. OO-LD tooling reads only two x-oold-sssom slots - predicate_id (a SKOS mapping predicate) and mapping_set_id (for profile-based selection); all other slots ride along and round-trip to SSSOM. Supports override under composition (most-derived-wins; null removes) and namespace/mapping-set selection. Promoted into @context by OO-LD-aware tooling; see the 'Term mappings and synonyms' section.", + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": [ + "object", + "null" + ], + "description": "A JSON-LD term-definition fragment (@id, @type, @container, ...), promotable verbatim into @context, plus an optional x-oold-sssom block. null removes an inherited mapping under composition.", + "properties": { + "x-oold-sssom": { + "type": "object", + "description": "SSSOM mapping metadata (https://w3id.org/sssom/). OO-LD interprets predicate_id and mapping_set_id; all other SSSOM slots are preserved verbatim and round-trip to a SSSOM mapping set.", + "properties": { + "predicate_id": { + "description": "SKOS mapping predicate from the term's primary IRI (subject) to this synonym IRI (object); default skos:exactMatch when absent. Compared by expansion to an absolute IRI. Only exactMatch entries are co-emitted by default.", + "type": "string", + "default": "skos:exactMatch", + "examples": [ + "skos:exactMatch", + "skos:closeMatch", + "skos:broadMatch", + "skos:narrowMatch", + "skos:relatedMatch" + ] + }, + "mapping_set_id": { + "description": "The SSSOM mapping set(s) this entry belongs to, for profile-based selection. SSSOM defines mapping_set_id at set level; OO-LD records it inline per entry and an entry MAY belong to several sets.", + "oneOf": [ + { + "type": "string", + "format": "iri-reference" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "iri-reference" + } + } + ] + } + } + } + } + } + }, + "examples": [ + { + "name": { + "skos:prefLabel": { + "x-oold-sssom": { + "predicate_id": "skos:exactMatch", + "confidence": 0.95 + } + } + } + } + ] + }, + "x-oold-sssom": { + "description": "Schema-level ontology correspondences: an SSSOM mapping set whose subject is this schema, keyed by the object IRI of a resolvable resource, each value carrying SSSOM slots (predicate_id default skos:exactMatch, mapping_set_id, ...). The schema-level counterpart of the per-term x-oold-sssom used inside x-oold-context; it describes the schema itself, not its instances. See the 'Ontology correspondence' section.", + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "predicate_id": { + "type": "string", + "default": "skos:exactMatch", + "examples": [ + "skos:exactMatch", + "skos:closeMatch" + ] + }, + "mapping_set_id": { + "oneOf": [ + { + "type": "string", + "format": "iri-reference" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "iri-reference" + } + } + ] + } + } + }, + "examples": [ + { + "https://schema.org/Person": { + "predicate_id": "skos:exactMatch" + } + } + ] + }, + "x-oold-uuid": { + "description": "Stable UUID identifying this schema across versions and locations.", + "type": "string", + "format": "uuid" + }, + "x-oold-version": { + "description": "Semantic version of this schema.", + "type": "string" + }, + "x-oold-prior-version": { + "description": "Identifier or version of the immediately preceding schema version.", + "type": "string" + }, + "x-oold-backward-compatible-with": { + "description": "URI of a prior schema version this schema is backward-compatible with.", + "type": "string", + "format": "uri-reference" + }, + "x-oold-incompatible-with": { + "description": "URI of a prior schema version this schema is NOT compatible with.", + "type": "string", + "format": "uri-reference" + }, + "x-oold-instance-rdf-type": { + "description": "The rdf:type(s) carried by instances of this schema, as a list of IRIs (e.g. [\"schema:Person\"]). OO-LD tooling materializes these as @type when exporting an instance to JSON-LD / RDF.", + "type": "array", + "items": { + "type": "string" + } + }, + "x-oold-ref": { + "description": "Reference to another OO-LD schema. Use x-oold-ref (not the standard $ref) for references that appear inside OO-LD custom keywords such as x-oold-range: there a plain $ref would be eagerly - and, for cyclic schema graphs, dangerously - dereferenced by generic JSON-Schema bundlers (the behaviour is undefined per Core section 9.4.2). Keep using the standard $ref for ordinary schema composition (allOf, properties, $defs), which bundlers are expected to resolve. x-oold-ref is resolved only by OO-LD-aware tools, lazily and with cycle handling.", + "type": "string", + "format": "uri-reference" + }, + "x-oold-range": { + "description": "Type constraint on the target of an IRI-valued property: an IRI string, an array of IRIs, or an OO-LD subschema (using x-oold-ref for references). See the 'Range of properties' section.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "object", + "$comment": "OO-LD subschema form; references inside it use x-oold-ref. The reverse-property keywords (x-oold-reverse-*) are intentionally not validated within a range subschema for now." + } + ] + }, + "x-oold-multilang-title": { + "description": "Language map of translated `title` values keyed by BCP-47 language code.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "x-oold-multilang-description": { + "description": "Language map of translated `description` values keyed by BCP-47 language code.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "x-oold-reverse-properties": { + "description": "Properties stored on the related object but editable from this side, mapped via JSON-LD @reverse.", + "type": "object" + }, + "x-oold-reverse-required": { + "description": "Names of reverse properties that are required.", + "type": "array", + "items": { + "type": "string" + } + }, + "x-enum-varnames": { + "description": "Identifier-safe code names aligned positionally with `enum`, for code generation. For `enum: [\"m\", \"s\"]` the value `[\"metre\", \"second\"]` names each option (so a generator can emit `Unit.metre` instead of `Unit.m`). An established vendor extension (OpenAPI Generator; NSwag uses the camelCase `x-enumNames`). Kept as-is; distinct from the human labels in `x-oold-ui-enum-titles`.", + "type": "array", + "items": { "type": "string" }, + "examples": [["metre", "second"]] + }, + "x-enum-descriptions": { + "description": "Per-value descriptions aligned positionally with `enum`, the established companion of `x-enum-varnames`. For `enum: [\"m\", \"s\"]`: `[\"SI base unit of length\", \"SI base unit of time\"]`.", + "type": "array", + "items": { "type": "string" }, + "examples": [["SI base unit of length", "SI base unit of time"]] + }, + "x-oold-reverse-default-properties": { + "description": "Deprecated. Names of reverse properties shown by default in generated user interfaces. Like the object-level defaultProperties array this is extend-only under composition; prefer a per-reverse-property x-oold-ui-default-property boolean, which is overridable.", + "deprecated": true, + "type": "array", + "items": { + "type": "string" + } + } + } +} diff --git a/src/oold/validation/meta/1.0.0-rc.3/oold-meta-schema.json b/src/oold/validation/meta/1.0.0-rc.3/oold-meta-schema.json new file mode 100644 index 0000000..0776608 --- /dev/null +++ b/src/oold/validation/meta/1.0.0-rc.3/oold-meta-schema.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://oo-ld.org/latest/meta/oold-meta-schema.json", + "title": "OO-LD dialect meta-schema", + "$comment": "The $id uses the versioned hosting at oo-ld.org/ (the source keeps the /latest/ placeholder; each released copy is stamped per release). The OO-LD vocabulary is declared optional (false) so that generic JSON-Schema 2020-12 validators still process OO-LD schemas. Two-tier structure: this resource is what a schema's $schema points at, so it carries the DOCUMENT-level obligations (required: $id). The dialect body lives in oold-meta-schema-base.json, which holds $dynamicAnchor: \"meta\"; nested subschemas recurse into the base via the standard $dynamicRef and are therefore NOT required to carry $id - a fragment inside properties or $defs legitimately has none. The UI keyword definitions are included via the oold-ui-meta-schema #keywords anchor so a schema carrying x-oold-ui-* annotations validates in one pass. The @context below is the OO-LD meta-level prefix set against which x-oold-context / x-oold-sssom CURIEs (synonym keys, predicate_id, mapping_set_id) are expanded by OO-LD processors; it is not an instance context.", + "@context": { + "skos": "http://www.w3.org/2004/02/skos/core#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "owl": "http://www.w3.org/2002/07/owl#", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "sssom": "https://w3id.org/sssom/" + }, + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/core": true, + "https://json-schema.org/draft/2020-12/vocab/applicator": true, + "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, + "https://json-schema.org/draft/2020-12/vocab/validation": true, + "https://json-schema.org/draft/2020-12/vocab/meta-data": true, + "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, + "https://json-schema.org/draft/2020-12/vocab/content": true, + "https://oo-ld.org/latest/vocab/oold": false + }, + "$ref": "https://oo-ld.org/latest/meta/oold-meta-schema-base.json", + "required": [ + "$id" + ] +} diff --git a/src/oold/validation/meta/1.0.0-rc.3/oold-pattern-lint.schema.json b/src/oold/validation/meta/1.0.0-rc.3/oold-pattern-lint.schema.json new file mode 100644 index 0000000..2291694 --- /dev/null +++ b/src/oold/validation/meta/1.0.0-rc.3/oold-pattern-lint.schema.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://oo-ld.org/latest/meta/oold-pattern-lint.schema.json", + "title": "OO-LD round-trip pattern lint", + "description": "SHOULD-level constraints on a schema's @context that keep instances round-trip-safe, checkable by JSON Schema alone. This is distinct from oold-meta-schema.json, which asserts MUST-level well-formedness. It currently enforces that no term coerces a literal to a datatype JSON-LD produces by default from a native JSON value (xsd:string, xsd:boolean, xsd:integer, xsd:double): xsd:string is RDF's default datatype and is elided from plain literals, and the round-trip contract reconstructs boolean/integer/double literals as native JSON values (fromRDF with native types), so in both cases the value carries no @type and a term declaring one is never selected when the value is compacted back from RDF - the property returns under its full IRI and the round-trip is lossy (see the specification, Property value forms). JSON-LD derives the correct RDF datatype from the native JSON type, so these coercions are also redundant. Datatypes JSON-LD does not produce by default (xsd:date, xsd:dateTime, xsd:float, ... - the value carried as a JSON string) keep their @type through the round-trip and coerce fine. CURIEs are matched in their conventional xsd: form and as the full XSD IRI; a term that coerces through a non-standard prefix mapping is beyond what a single JSON Schema can resolve and is left to tooling.", + "type": "object", + "properties": { + "@context": { "$ref": "#/$defs/context" } + }, + "$defs": { + "context": { + "oneOf": [ + { "type": "null" }, + { "type": "string" }, + { "type": "array", "items": { "$ref": "#/$defs/context" } }, + { "$ref": "#/$defs/contextObject" } + ] + }, + "contextObject": { + "type": "object", + "patternProperties": { + "^@": true, + "^[^@]": { "$ref": "#/$defs/termValue" } + }, + "additionalProperties": { "$ref": "#/$defs/termValue" } + }, + "termValue": { + "oneOf": [ + { "type": "null" }, + { "type": "string" }, + { "$ref": "#/$defs/termDefinition" } + ] + }, + "termDefinition": { + "type": "object", + "properties": { + "@type": { "$ref": "#/$defs/notNativeJsonDatatype" }, + "@context": { "$ref": "#/$defs/context" } + } + }, + "notNativeJsonDatatype": { + "not": { + "enum": [ + "xsd:string", "http://www.w3.org/2001/XMLSchema#string", + "xsd:boolean", "http://www.w3.org/2001/XMLSchema#boolean", + "xsd:integer", "http://www.w3.org/2001/XMLSchema#integer", + "xsd:double", "http://www.w3.org/2001/XMLSchema#double" + ] + } + } + } +} diff --git a/src/oold/validation/meta/1.0.0-rc.3/oold-rules.json b/src/oold/validation/meta/1.0.0-rc.3/oold-rules.json new file mode 100644 index 0000000..21993eb --- /dev/null +++ b/src/oold/validation/meta/1.0.0-rc.3/oold-rules.json @@ -0,0 +1,1116 @@ +{ + "$schema": "https://oo-ld.org/latest/meta/oold-rules.schema.json", + "$comment": "Catalog of the normative statements in the OO-LD specification, generated from the :rule[...] markers in spec/sections/*.md by scripts/extract_rules.py. Do not edit by hand. Ids are immutable and never reused; see meta/RULES.md.", + "spec_version": "1.0.0-rc.3", + "areas": { + "CNF": "Serialization and conformance", + "SCH": "Schema well-formedness and the meta-schema", + "CMP": "Composition, merge and override", + "INS": "Instances: $schema, identity, semantic type, value forms", + "RT": "Projection to RDF and round-trip safety", + "VER": "Identification and versioning", + "EXT": "Standard extensions (JSON-LD and JSON Schema)" + }, + "applies_to": { + "document": "Checkable by validating a schema or instance document", + "implementation": "Constrains an OO-LD implementation; needs a library conformance suite", + "advisory": "Guidance; nothing verifies it automatically" + }, + "rules": [ + { + "id": "OOLD-CMP-1257", + "area": "CMP", + "level": "MUST", + "applies_to": "document", + "section": "closing-composed-objects", + "summary": "A composed object is closed with unevaluatedProperties, not additionalProperties.", + "text": "A schema that closes a composed object MUST do so with `unevaluatedProperties: false` (JSONSCHEMA §11.3), which is evaluated after the `allOf` branches and therefore accounts for their properties, rather than with `additionalProperties: false`, which does not see them and so rejects instances the composition permits.", + "text_sha256": "7e3a4ba0adb7bb93289004c49bf1f53410d852293e4be4089eb7d3618c7d5087", + "context": "Because `allOf` composition is conjunctive, `additionalProperties: false` on one subschema rejects the members that the other composed subschemas contribute, so it cannot close a composed object. A schema that closes a composed object MUST do so with `unevaluatedProperties: false` (JSONSCHEMA §11.3), which is evaluated after the `allOf` branches and therefore accounts for their properties, rather than with `additionalProperties: false`, which does not see them and so rejects instances the composition permits. Note that [](#schema-instances) requires such a schema to still permit the instance-level `$schema` and `@context` members.", + "machine_checkable": true, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "06-composition.md:86" + }, + { + "id": "OOLD-CMP-1d7e", + "area": "CMP", + "level": "MUST NOT", + "applies_to": "document", + "section": "merging-remote-contexts", + "summary": "Reflected oneOf/anyOf branch contexts must not map the same keyword to different IRIs at the root.", + "text": "The remote contexts of `oneOf` / `anyOf` branches MAY also be reflected into the `@context`, but they MUST NOT conflict at the root - they MUST NOT map the same keyword to different IRIs there.", + "text_sha256": "2bb32571967d138ce1b962cd0951dbf255af2de7c7bf2a2dbfd42718017dc18e", + "context": "`oneOf` / `anyOf`. The remote contexts of `oneOf` / `anyOf` branches MAY also be reflected into the `@context`, but they MUST NOT conflict at the root - they MUST NOT map the same keyword to different IRIs there. A JSON-LD processor merges all listed contexts (most-recently-wins) and has no notion of which branch a given instance matched, so a root-level conflict would be decided by context order rather than by the branch the data conforms to.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:49" + }, + { + "id": "OOLD-CMP-5266", + "area": "CMP", + "level": "SHOULD", + "applies_to": "document", + "section": "composition", + "summary": "An embedded object property should be reflected as that property's scoped JSON-LD context.", + "text": "An embedded object reached under an object-valued property - one whose value is an object, directly (`type: object`) or as the `items` of an array (`type: array`), whether inlined or brought in by `$ref` - SHOULD be reflected as that property's scoped JSON-LD context, so its terms resolve only under that property and cannot conflict with a same-named term elsewhere.", + "text_sha256": "62cca7366f12688f2708768b351e60662cb4704c3039f2c7f9243446ec9d21a6", + "context": "It MUST NOT be required to further process an OO-LD schema document in order to interpret it as a JSON-LD context. This implies that all occurrences of `$ref` in the schema are reflected in the JSON-LD context. An embedded object reached under an object-valued property - one whose value is an object, directly (`type: object`) or as the `items` of an array (`type: array`), whether inlined or brought in by `$ref` - SHOULD be reflected as that property's scoped JSON-LD context, so its terms resolve only under that property and cannot conflict with a same-named term elsewhere. That scoped context MAY reference the embedded schema remotely (by URL) or carry its terms inline. Where the embed graph is cyclic - a value type whose scoped context transitively references itself through remote schema files - JSON-LD processors cannot resolve the recursive remote contexts (see [](#round-trip)); breaking the cycle requires migrating the remote reference to a local (inline) context - inlining the term definitions so there is no remote hop to recurse - which MAY be flattened onto the root context as a shared vocabulary. Moving the remote reference to the root does not break the cycle; only replacing it with local definitions does. A `$ref` at the root level of the OO-LD schema is listed at the root of the JSON-LD context. (A scalar reference - a property whose value is an IRI string, not an embedded object - carries its target type in [`x-oold-range`](#range-of-properties), not a `$ref`, and so contributes no scoped context.) In case of multiple `$ref` within `allOf` the corresponding remote contexts are merged into an array-valued `@context` (see [](#merging-remote-contexts)). For `oneOf` / `anyOf` this requires care to avoid conflicts. At any time the importing OO-LD schema MAY define its own or override the imported JSON-LD context.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:5" + }, + { + "id": "OOLD-CMP-53bf", + "area": "CMP", + "level": "SHOULD", + "applies_to": "document", + "section": "merging-remote-contexts", + "summary": "A schema's JSON Schema and JSON-LD base URIs should be aligned so a relative reference resolves the same under both.", + "text": "Relative references resolve against the schema's `$id` (the JSON Schema base URI) and, on the JSON-LD side, against `@base` / the retrieval URL; these base URIs SHOULD be aligned so a relative reference resolves to the same absolute URL under both.", + "text_sha256": "47730120a068a22fa8d75d91b9797166ad500f332b8b84e06f82476d15296511", + "context": "Independent references and base URIs. A JSON Schema `$ref` and a JSON-LD `@context` entry are independent references: they MAY point to the same document (the typical OO-LD case, where one document is both a schema and a context) or to different documents - for example a plain JSON Schema referenced via `$ref` together with a separate remote `@context` that supplies the semantics. Relative references resolve against the schema's `$id` (the JSON Schema base URI) and, on the JSON-LD side, against `@base` / the retrieval URL; these base URIs SHOULD be aligned so a relative reference resolves to the same absolute URL under both. `$id` MUST NOT contain a non-empty fragment (JSONSCHEMA §8.2.1).", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:74" + }, + { + "id": "OOLD-CMP-6d7b", + "area": "CMP", + "level": "MUST", + "applies_to": "document", + "section": "merging-remote-contexts", + "summary": "Branch-specific mappings for the same keyword must be scoped rather than placed at the root.", + "text": "Where branches genuinely need different mappings for the same keyword, those mappings MUST be scoped with JSON-LD scoped contexts so each applies only where its branch applies, rather than placed at the root, since colliding root mappings are resolved by context order instead of by the branch the data conforms to: Type-scoped contexts when the branches are distinguished by `@type`. The", + "text_sha256": "20a163b888e4fc79898974b0e846bb25df1e73dec7bb5fd434a19934bef7e47a", + "context": "Where branches genuinely need different mappings for the same keyword, those mappings MUST be scoped with JSON-LD scoped contexts so each applies only where its branch applies, rather than placed at the root, since colliding root mappings are resolved by context order instead of by the branch the data conforms to:\n- Type-scoped contexts when the branches are distinguished by `@type`. The", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:51" + }, + { + "id": "OOLD-CMP-a05a", + "area": "CMP", + "level": "MUST", + "applies_to": "document", + "section": "merging-remote-contexts", + "summary": "A scoped context that must apply only to the immediate node sets @propagate false; contexts in one array share it.", + "text": "Where a referenced context should apply only to the immediate node, the schema MUST set `\"@propagate\": false` on that scoped context.", + "text_sha256": "c9059a4861176c0efa21e2f497d557b096d3105ca0cf872497191c5ed80cc7e8", + "context": "Propagation (`@propagate`). A `$ref` inside a `type: object` property is reflected as a property-scoped context, which by default propagates into the whole subtree rooted at that property (\"By default ... contexts propagate across node objects, other than for type-scoped contexts, which default to false\"). Where a referenced context should apply only to the immediate node, the schema MUST set `\"@propagate\": false` on that scoped context.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:70" + }, + { + "id": "OOLD-CMP-b926", + "area": "CMP", + "level": "MUST NOT", + "applies_to": "document", + "section": "composition", + "summary": "A schema must be usable as a JSON-LD context with no further processing, so every $ref is reflected in the @context.", + "text": "It MUST NOT be required to further process an OO-LD schema document in order to interpret it as a JSON-LD context.", + "text_sha256": "fb9e604440b34e28343756729d47c1cf923d35a93bc11354181e4cd87b069a4c", + "context": "It MUST NOT be required to further process an OO-LD schema document in order to interpret it as a JSON-LD context. This implies that all occurrences of `$ref` in the schema are reflected in the JSON-LD context. An embedded object reached under an object-valued property - one whose value is an object, directly (`type: object`) or as the `items` of an array (`type: array`), whether inlined or brought in by `$ref` - SHOULD be reflected as that property's scoped JSON-LD context, so its terms resolve only under that property and cannot conflict with a same-named term elsewhere. That scoped context MAY reference the embedded schema remotely (by URL) or carry its terms inline. Where the embed graph is cyclic - a value type whose scoped context transitively references itself through remote schema files - JSON-LD processors cannot resolve the recursive remote contexts (see [](#round-trip)); breaking the cycle requires migrating the remote reference to a local (inline) context - inlining the term definitions so there is no remote hop to recurse - which MAY be flattened onto the root context as a shared vocabulary. Moving the remote reference to the root does not break the cycle; only replacing it with local definitions does. A `$ref` at the root level of the OO-LD schema is listed at the root of the JSON-LD context. (A scalar reference - a property whose value is an IRI string, not an embedded object - carries its target type in [`x-oold-range`](#range-of-properties), not a `$ref`, and so contributes no scoped context.) In case of multiple `$ref` within `allOf` the corresponding remote contexts are merged into an array-valued `@context` (see [](#merging-remote-contexts)). For `oneOf` / `anyOf` this requires care to avoid conflicts. At any time the importing OO-LD schema MAY define its own or override the imported JSON-LD context.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:5" + }, + { + "id": "OOLD-CMP-dd2b", + "area": "CMP", + "level": "MUST NOT", + "applies_to": "document", + "section": "merging-remote-contexts", + "summary": "A schema $id must not contain a non-empty fragment.", + "text": "`$id` MUST NOT contain a non-empty fragment (JSONSCHEMA §8.2.1).", + "text_sha256": "bc845f8e67383d4802f512fbf76d46caa3873cae4b10e370cca35952b5d62c0f", + "context": "Independent references and base URIs. A JSON Schema `$ref` and a JSON-LD `@context` entry are independent references: they MAY point to the same document (the typical OO-LD case, where one document is both a schema and a context) or to different documents - for example a plain JSON Schema referenced via `$ref` together with a separate remote `@context` that supplies the semantics. Relative references resolve against the schema's `$id` (the JSON Schema base URI) and, on the JSON-LD side, against `@base` / the retrieval URL; these base URIs SHOULD be aligned so a relative reference resolves to the same absolute URL under both. `$id` MUST NOT contain a non-empty fragment (JSONSCHEMA §8.2.1).", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:74" + }, + { + "id": "OOLD-CMP-e4a3", + "area": "CMP", + "level": "MUST", + "applies_to": "document", + "section": "merging-remote-contexts", + "summary": "A schema with multiple $refs must list their remote contexts as an array, in allOf order.", + "text": "By the reflection rule above, the schema's own `@context` MUST list those remote contexts as an array, in the same order as the `allOf` members, so the schema stays usable as a context without further processing.", + "text_sha256": "7c113ef3179658fded82c089504e6f781d0c22a75a46be372fec0cf83b1748f7", + "context": "Multiple `$ref` (e.g. in `allOf`) each correspond to a remote context. By the reflection rule above, the schema's own `@context` MUST list those remote contexts as an array, in the same order as the `allOf` members, so the schema stays usable as a context without further processing. A JSON-LD processor then resolves that array in order, later entries overriding earlier ones - duplicate context terms are overridden using a most-recently-defined-wins mechanism (JSONLD11-API, Context Processing Algorithm). The schema MAY append its own context object as the last array entry to override an inherited term. The single-context `@import` keyword is an alternative only when exactly one remote context is wrapped and locally modified (it cannot contain a nested `@import`), so the array form is used for the multi-`$ref` case.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:47" + }, + { + "id": "OOLD-CMP-f3c7", + "area": "CMP", + "level": "MUST NOT", + "applies_to": "document", + "section": "merge-and-override-model", + "summary": "Composition is narrow-only: a derived schema may restrict a constraint but must not relax it.", + "text": "For assertion-bearing keywords the resolved view additionally honors narrow-only composition: a derived schema MAY restrict a constraint but MUST NOT relax it, matching how code generators let a subclass tighten - never loosen - a superclass property's validation.", + "text_sha256": "6e73492f741ebab68002a6728d628b42613c8f4d7adccee5e7ff92bdc61e0b84", + "context": "When such a merge is required, OO-LD resolves the `allOf` chain by applying JSON Merge Patch (RFC7396) semantics: keyed by object member, most-recently-defined (most-derived) wins, and a `null` value removes a key. For the `@context` this coincides with JSON-LD's own override rule. For assertion-bearing keywords the resolved view additionally honors narrow-only composition: a derived schema MAY restrict a constraint but MUST NOT relax it, matching how code generators let a subclass tighten - never loosen - a superclass property's validation.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "06-composition.md:80" + }, + { + "id": "OOLD-CNF-1120", + "area": "CNF", + "level": "MUST", + "applies_to": "document", + "section": "notation", + "summary": "A conforming schema or instance must be interchangeable as JSON, canonicalized per RFC 8785.", + "text": "JSON (RFC8259) is the canonical serialization: a conforming OO-LD schema or instance MUST be interchangeable as JSON, and the canonical form used for identity and integrity (for example content-hashing a versioned schema) is its JSON Canonicalization Scheme (RFC8785) serialization.", + "text_sha256": "a9cdf1bd1358785e00667c7d0ce7baf6dea8e8c1ad3736385ee92243ed38a2e6", + "context": "The normative data model of OO-LD is the JSON data model shared by JSONSCHEMA and JSON-LD11. JSON (RFC8259) is the canonical serialization: a conforming OO-LD schema or instance MUST be interchangeable as JSON, and the canonical form used for identity and integrity (for example content-hashing a versioned schema) is its JSON Canonicalization Scheme (RFC8785) serialization.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "03-conformance.md:9" + }, + { + "id": "OOLD-CNF-22d3", + "area": "CNF", + "level": "MUST NOT", + "applies_to": "document", + "section": "notation", + "summary": "A YAML serialization outside the JSON-compatible subset is not a conforming OO-LD serialization.", + "text": "A YAML document outside this subset, including one relying on the features YAML-LD admits only in its Extended profile, MUST NOT be treated as a conforming OO-LD serialization.", + "text_sha256": "b4e844d40d00838c2dbbc8d722aa9f35f85211917d61d5b453ea1ecafbf5a2a0", + "context": "A document MAY additionally be authored or served as YAML, provided it stays within the JSON-compatible subset of [YAML 1.2](https://yaml.org/spec/1.2.2/): no tags, anchors, aliases, or merge keys; a single document; and no implicit typing beyond what JSON expresses. Within this subset - which coincides with the Basic profile of [YAML-LD](https://github.com/w3c/yaml-ld) - a YAML document maps one-to-one onto the JSON data model and converts to the canonical JSON without loss. A YAML document outside this subset, including one relying on the features YAML-LD admits only in its Extended profile, MUST NOT be treated as a conforming OO-LD serialization.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "03-conformance.md:11" + }, + { + "id": "OOLD-CNF-d71d", + "area": "CNF", + "level": "MUST", + "applies_to": "document", + "section": "notation", + "summary": "Where a YAML form and its canonical JSON disagree, the JSON form is authoritative.", + "text": "Where the two forms disagree, the JSON form MUST be treated as authoritative.", + "text_sha256": "bbaaecdeec3c9419d4056db8917d92c8b14f3bd0af5c6d9c765c55814f3976b9", + "context": "Authors using YAML should be aware that YAML comments and implicit type coercions (for example the strings `NO` or `1.10` read as a boolean or a truncated number by some parsers) do not survive conversion to the canonical JSON. Where the two forms disagree, the JSON form MUST be treated as authoritative. Examples in this specification are shown as JSON, with an equivalent YAML rendering available under \"View as YAML\".", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "03-conformance.md:13" + }, + { + "id": "OOLD-EXT-1dc8", + "area": "EXT", + "level": "MUST NOT", + "applies_to": "document", + "section": "synonyms", + "summary": "A predicate_id must not be a bare local name.", + "text": "A bare local name (`exactMatch`) MUST NOT be used as a `predicate_id`.", + "text_sha256": "8874d4e1da929ee9f25b4925a9820211469c1bc397b80760fdf25be82cf1d49b", + "context": "`predicate_id` is a [SKOS](https://www.w3.org/TR/skos-reference/) mapping predicate - `skos:exactMatch` (the default when the slot is absent), `skos:closeMatch`, `skos:broadMatch`, `skos:narrowMatch` or `skos:relatedMatch` - relating the term's primary IRI (subject) to the synonym IRI (object); it decides which entries denote equivalence. It MUST be written as a full IRI or a CURIE and compared by expansion to an absolute IRI, the same rule the synonym keys follow, so `skos:exactMatch` and `http://www.w3.org/2004/02/skos/core#exactMatch` are one predicate. `x-oold-context` is a schema-level keyword consumed by OO-LD processors (it is promoted into a clean `@context` before any generic JSON-LD processor runs), so its CURIEs - the synonym keys and the `predicate_id` / `mapping_set_id` values alike - are expanded not against the instance `@context` but against a fixed well-known prefix set the meta-schema defines (`skos`, `rdfs`, `owl`, `xsd`, `sssom`), reached through the schema's `$schema`. The contract therefore holds without the author redeclaring those prefixes in the data context. A bare local name (`exactMatch`) MUST NOT be used as a `predicate_id`.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:58" + }, + { + "id": "OOLD-EXT-1e3c", + "area": "EXT", + "level": "MUST", + "applies_to": "document", + "section": "widget-hints", + "summary": "A widget hint that is not a registered format goes in x-oold-ui-widget, leaving format for validation.", + "text": "A value that is not a registered format (`table`, `tabs`, `grid`, `autocomplete`, `textarea`, `checkbox`, `markdown`, `color`, ...) is widget-only and MUST be carried in `x-oold-ui-widget` rather than `format`, which stays a validation assertion: a validator that checks declared formats would otherwise reject every value of the property.", + "text_sha256": "a10af104ed72237be86bd01f683041cf51fae97707f843e0906d22c53016011a", + "context": "`format` carries the widget hint when its value is a registered JSON Schema 2020-12 format (`date`, `date-time`, `time`, `duration`, `email`, `uri`, `iri`, `uuid`, ...); a validator may check it and a form generator picks the matching input. A value that is not a registered format (`table`, `tabs`, `grid`, `autocomplete`, `textarea`, `checkbox`, `markdown`, `color`, ...) is widget-only and MUST be carried in `x-oold-ui-widget` rather than `format`, which stays a validation assertion: a validator that checks declared formats would otherwise reject every value of the property.", + "machine_checkable": true, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "09-extensions.md:423" + }, + { + "id": "OOLD-EXT-1f92", + "area": "EXT", + "level": "RECOMMENDED", + "applies_to": "document", + "section": "range-reference-form", + "summary": "iri-reference is the recommended default format for an IRI-valued property.", + "text": "By RFC3987 this accepts absolute IRIs, compact IRIs (`ex:alice`, `schema:Person`) and context-relative references alike - the forms OO-LD instances routinely use - so it is the RECOMMENDED default.", + "text_sha256": "5d4c4a4f84533b109985d2562ad3459f3c9ce3dcd42d66aebeca8ca6c182e815", + "context": "- Any IRI reference - `\"format\": \"iri-reference\"`. By RFC3987 this accepts absolute IRIs, compact IRIs (`ex:alice`, `schema:Person`) and context-relative references alike - the forms OO-LD instances routinely use - so it is the RECOMMENDED default. It also accepts a bare term such as `alice`, expanded against the context's `@base` / `@vocab`.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:343" + }, + { + "id": "OOLD-EXT-2542", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "value-term-aliases", + "summary": "Value terms should not collide with JSON-LD keyword aliases or other context terms.", + "text": "The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (`id`, `type`) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name.", + "text_sha256": "e004b9449c9c6f9b84588bb7bf7660d81665e99f0a1040320bce572ae2f7fb45", + "context": "Because `@vocab` expands an unmatched string against the vocabulary - concatenating it onto the default vocabulary base when one is set (minting a new IRI), or leaving it a relative IRI when none is - a typo silently becomes a stray IRI rather than an error. A property coerced `\"@type\": \"@vocab\"` therefore SHOULD constrain its values with an `enum` of the value terms (optionally named with `x-enum-varnames`) or with `x-oold-range`, so only intended individuals are accepted. The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (`id`, `type`) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name. Confining the value terms to the property's own scoped `@context` keeps them out of that shared namespace, since they then resolve only for that property's values; naming them with opaque identifiers such as UUIDs avoids the clash where readability is not required.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:352" + }, + { + "id": "OOLD-EXT-2b61", + "area": "EXT", + "level": "MUST", + "applies_to": "document", + "section": "range-reference-form", + "summary": "A compact-IRI prefix used by a property must be defined in the @context.", + "text": "Compact form specifically - a `\"pattern\"` such as `\"^[A-Za-z_][\\\\w.-]:(?!//)\\\\S$\"`, which accepts `ex:alice` and `schema:Person` while rejecting `http://…`; the prefix MUST be defined in the `@context`.", + "text_sha256": "9ed092ee23b716d012311740effff835e67e883d41215e2fd27f66107a383708", + "context": "- Stricter, ASCII only - `\"format\": \"uri\"` or `\"uri-reference\"`, where values are known not to use internationalized (non-ASCII) IRIs.\n- Compact form specifically - a `\"pattern\"` such as `\"^[A-Za-z_][\\\\w.-]:(?!//)\\\\S$\"`, which accepts `ex:alice` and `schema:Person` while rejecting `http://…`; the prefix MUST be defined in the `@context`.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:346" + }, + { + "id": "OOLD-EXT-391e", + "area": "EXT", + "level": "MUST", + "applies_to": "implementation", + "section": "range-of-properties", + "summary": "A loader that dereferences a target validates it against the declared range and does not assume the target conforms.", + "text": "A loader that dereferences a target MUST validate it against that range before treating it as a member, and MUST NOT assume the target conforms, since the target is a separate document that may change independently of the reference.", + "text_sha256": "b0caa6b770adbdec9bcdb37cfb4d365c87eed6817f55c8f40574ec0d6587077d", + "context": "An `x-oold-range` value is a reference: the property holds the target's IRI, and an OO-LD-aware loader MAY dereference that IRI to obtain the target document itself, so a large or shared object can live in a separate document and be pulled in on demand (data bundling). A published reference SHOULD point at a target that validates against the property's declared range. A loader that dereferences a target MUST validate it against that range before treating it as a member, and MUST NOT assume the target conforms, since the target is a separate document that may change independently of the reference. This holds whether the reference is written as a bare IRI string or as a `{ \"@id\": … }` object; generic tooling leaves it unresolved, exactly as it leaves `x-oold-ref` (see [](#why-x-oold-ref)).", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:337" + }, + { + "id": "OOLD-EXT-3fe9", + "area": "EXT", + "level": "MUST", + "applies_to": "document", + "section": "range-of-properties", + "summary": "References inside x-oold-range must use x-oold-ref, never $ref.", + "text": "References to other schemas inside `x-oold-range` MUST use `x-oold-ref`, never `$ref` (see below).", + "text_sha256": "6626132bb2c6a394d430fb9e4db9a559c26b71914acdc07ed8fb3a4b06c88d75", + "context": "3. An OO-LD subschema, the most expressive form. Unions (`anyOf` / `oneOf`), intersections (`allOf`) and inline constraints can be combined to describe an anonymous subclass. References to other schemas inside `x-oold-range` MUST use `x-oold-ref`, never `$ref` (see below). The single-IRI form (1) is a shorthand for `{ \"allOf\": [ { \"x-oold-ref\": \"Organization.schema.json\" } ] }`:", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:315" + }, + { + "id": "OOLD-EXT-436a", + "area": "EXT", + "level": "SHOULD", + "applies_to": "implementation", + "section": "semantic-delivery", + "summary": "For OpenAPI 3.0, deliver the context and type per class as vendor extensions.", + "text": "For OpenAPI 3.0, which rejects unprefixed keywords in a Schema Object (and typically bundles several classes with no document root to host one `@context`), the context and type SHOULD be delivered per class as `x-jsonld-context` and `x-jsonld-type` following [REST API Linked Data Keywords](https://datatracker.ietf.org/doc/html/draft-polli-restapi-ld-keywords-08): `@context` maps to `x-jsonld-context` and `x-oold-instance-rdf-type` to `x-jsonld-type`.", + "text_sha256": "90622f946111378db3b4fed08c6981f87e452e982f9f208a562ada1ade8122da", + "context": "- For OpenAPI 3.0, which rejects unprefixed keywords in a Schema Object (and typically bundles several classes with no document root to host one `@context`), the context and type SHOULD be delivered per class as `x-jsonld-context` and `x-jsonld-type` following [REST API Linked Data Keywords](https://datatracker.ietf.org/doc/html/draft-polli-restapi-ld-keywords-08): `@context` maps to `x-jsonld-context` and `x-oold-instance-rdf-type` to `x-jsonld-type`. That draft requires references inside these keywords not to be dereferenced automatically, consistent with the `x-oold-ref` rule (see [](#why-x-oold-ref)). The mapping is reversible, so such an export can be read back into an OO-LD schema.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:446" + }, + { + "id": "OOLD-EXT-4966", + "area": "EXT", + "level": "MUST", + "applies_to": "implementation", + "section": "synonyms", + "summary": "Promotion selects one synonym per term for the target profile, writes it as the term definition and drops the x-oold-sssom blocks.", + "text": "To promote `x-oold-context` into a real `@context`, a preprocessor MUST select one synonym per term for a target profile, write `{ \"@id\": , ...fragment without x-oold-sssom }` as that term's definition, and drop the `x-oold-sssom` blocks, so standard JSON-LD tools then run on a clean context.", + "text_sha256": "fbd527aa776fd794bb6d90aa255b8c2752e6164878e9aa1d9d957bece9ae658a", + "context": "Selection. To promote `x-oold-context` into a real `@context`, a preprocessor MUST select one synonym per term for a target profile, write `{ \"@id\": , ...fragment without x-oold-sssom }` as that term's definition, and drop the `x-oold-sssom` blocks, so standard JSON-LD tools then run on a clean context. A profile is expressed either as an ordered list of IRI namespaces (ontology-family priority - `schema:` before `bfo:` before `emmo:`) or as one or more `mapping_set_id`s (a set may span namespaces, e.g. a PMDco profile of `pmd:` plus reused `obo:` terms). A term with no synonym matching the target keeps its default `@context` IRI. Selection MUST NOT use a synonym from outside the target profile; where the profile is an ordered list, the highest-priority match wins and a lower-priority entry is selected only where no higher one matches.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:62" + }, + { + "id": "OOLD-EXT-5184", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "jsonschema-extensions", + "summary": "A schema should declare the OO-LD dialect meta-schema as its $schema.", + "text": "An OO-LD schema SHOULD declare the OO-LD dialect meta-schema (which extends 2020-12) as its `$schema`, e.g. `\"$schema\": \"https://oo-ld.org/latest/meta/oold-meta-schema.json\"` - pinning a specific version (e.g. `.../0.4.0/meta/oold-meta-schema.json`) for reproducibility.", + "text_sha256": "128c5740185a075885f4ff1aeddf90f73f951ed978e47ef6e8f1187d1e9b5753", + "context": "OO-LD targets JSONSCHEMA (2020-12) as its normative dialect. An OO-LD schema SHOULD declare the OO-LD dialect meta-schema (which extends 2020-12) as its `$schema`, e.g. `\"$schema\": \"https://oo-ld.org/latest/meta/oold-meta-schema.json\"` - pinning a specific version (e.g. `.../0.4.0/meta/oold-meta-schema.json`) for reproducibility. Declaring the plain 2020-12 meta-schema (`https://json-schema.org/draft/2020-12/schema`) remains valid for tools that only understand standard JSON Schema.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:185" + }, + { + "id": "OOLD-EXT-557e", + "area": "EXT", + "level": "MUST", + "applies_to": "implementation", + "section": "synonyms", + "summary": "A predicate_id is written as a full IRI or CURIE and compared by expansion to an absolute IRI.", + "text": "It MUST be written as a full IRI or a CURIE and compared by expansion to an absolute IRI, the same rule the synonym keys follow, so `skos:exactMatch` and `http://www.w3.org/2004/02/skos/core#exactMatch` are one predicate.", + "text_sha256": "47866999c5fcf3c61427192149b560a2002a174311a64b04a2be36f2e3383916", + "context": "`predicate_id` is a [SKOS](https://www.w3.org/TR/skos-reference/) mapping predicate - `skos:exactMatch` (the default when the slot is absent), `skos:closeMatch`, `skos:broadMatch`, `skos:narrowMatch` or `skos:relatedMatch` - relating the term's primary IRI (subject) to the synonym IRI (object); it decides which entries denote equivalence. It MUST be written as a full IRI or a CURIE and compared by expansion to an absolute IRI, the same rule the synonym keys follow, so `skos:exactMatch` and `http://www.w3.org/2004/02/skos/core#exactMatch` are one predicate. `x-oold-context` is a schema-level keyword consumed by OO-LD processors (it is promoted into a clean `@context` before any generic JSON-LD processor runs), so its CURIEs - the synonym keys and the `predicate_id` / `mapping_set_id` values alike - are expanded not against the instance `@context` but against a fixed well-known prefix set the meta-schema defines (`skos`, `rdfs`, `owl`, `xsd`, `sssom`), reached through the schema's `$schema`. The contract therefore holds without the author redeclaring those prefixes in the data context. A bare local name (`exactMatch`) MUST NOT be used as a `predicate_id`.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:58" + }, + { + "id": "OOLD-EXT-6007", + "area": "EXT", + "level": "SHOULD", + "applies_to": "implementation", + "section": "why-x-oold-ref", + "summary": "An OO-LD-aware tool resolves x-oold-ref lazily and handles a cyclic reference graph by terminating rather than recursing indefinitely.", + "text": "An OO-LD-aware tool SHOULD resolve `x-oold-ref` lazily, and MUST handle a cyclic reference graph - terminating and returning the references it has already resolved, rather than recursing indefinitely - since the graph it opts into may be unbounded or self-referential.", + "text_sha256": "933cab8c00e5318aab051baa733bee926e95deec92971645c6281457c0bdbe1f", + "context": "`x-oold-ref` avoids this. Generic tools only follow the standard `$ref` keyword, so they leave `x-oold-ref` untouched. An OO-LD-aware tool SHOULD resolve `x-oold-ref` lazily, and MUST handle a cyclic reference graph - terminating and returning the references it has already resolved, rather than recursing indefinitely - since the graph it opts into may be unbounded or self-referential. The standard `$ref` continues to be used for ordinary schema composition (`allOf`, `properties`, `$defs`), which bundlers are expected to resolve. Because the only difference is the keyword name, the mapping is reversible: an OO-LD-aware tool can mechanically replace `x-oold-ref` with `$ref` to obtain a plain, fully-resolvable JSON Schema - the explicit opt-in to resolving the (possibly cyclic) graph.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:358" + }, + { + "id": "OOLD-EXT-61aa", + "area": "EXT", + "level": "SHOULD", + "applies_to": "implementation", + "section": "semantic-delivery", + "summary": "A consumer accepting arbitrary JSON Schema keywords should receive the native form unchanged.", + "text": "A consumer that accepts arbitrary JSON Schema keywords SHOULD receive the native form unchanged.", + "text_sha256": "aa1601aa9ebbaf66046ee3c18acd7690ee8da151843196a42f3d4c1958ed42cd", + "context": "- A consumer that accepts arbitrary JSON Schema keywords SHOULD receive the native form unchanged. This covers plain JSON Schema 2020-12 validators, OpenAPI 3.1, and - because they place no restriction on `@context` - Model Context Protocol tool schemas (`inputSchema` / `outputSchema`) as well as LLM tool-use and structured-output APIs, which carry the context through and can use it as grounding.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:445" + }, + { + "id": "OOLD-EXT-6312", + "area": "EXT", + "level": "MUST NOT", + "applies_to": "document", + "section": "localizing-instance-values", + "summary": "The multilang keywords must not be used to localize an instance value; the standard JSON-LD mechanism is used instead.", + "text": "To localize a value of an instance - a translatable string in the data that should round-trip to language-tagged RDF literals - the keywords above MUST NOT be used; the standard JSON-LD mechanism MUST be used instead.", + "text_sha256": "24f4abaced11e4203298124cfbc2642efc2b6b0fc4c9a3369e0ff4c8d16ce1b8", + "context": "To localize a value of an instance - a translatable string in the data that should round-trip to language-tagged RDF literals - the keywords above MUST NOT be used; the standard JSON-LD mechanism MUST be used instead. There are two equivalent JSON-LD-native ways to carry such a value, both producing the same language-tagged literals.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:227" + }, + { + "id": "OOLD-EXT-6ea3", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "range-reference-form", + "summary": "An IRI-valued property should constrain its lexical form with an IRI/URI-family format.", + "text": "Its lexical form SHOULD be constrained with an IRI/URI-family `format` so that malformed values are rejected; the choices, from most to least permissive:", + "text_sha256": "a1fd73169ee2f84b0a897e74e5495e9019dd4a8ac1c763a108fc8cb02a0afe9e", + "context": "The value of an IRI-valued property is a JSON string. Its role as a reference comes from the `@context` (`\"@type\": \"@id\"`) and its class from `x-oold-range`. Its lexical form SHOULD be constrained with an IRI/URI-family `format` so that malformed values are rejected; the choices, from most to least permissive:\n- Any IRI reference - `\"format\": \"iri-reference\"`. By RFC3987 this accepts absolute IRIs, compact IRIs (`ex:alice`, `schema:Person`) and context-relative references alike - the forms OO-LD instances routinely use - so it is the RECOMMENDED default. It also accepts a bare term such as `alice`, expanded against the context's `@base` / `@vocab`.\n- Absolute IRIs only - `\"format\": \"iri\"`. A compact IRI is itself a valid absolute IRI (scheme `ex`, path `alice`), so `iri` accepts `ex:alice`; choose it to additionally forbid relative references.\n- Stricter, ASCII only - `\"format\": \"uri\"` or `\"uri-reference\"`, where values are known not to use internationalized (non-ASCII) IRIs.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:341" + }, + { + "id": "OOLD-EXT-7256", + "area": "EXT", + "level": "SHOULD NOT", + "applies_to": "implementation", + "section": "synonyms", + "summary": "Entries that are not exactMatch should not be co-emitted unless a consumer explicitly requests it.", + "text": "By default a converter co-emits only `skos:exactMatch` entries; entries whose `predicate_id` is `skos:closeMatch`/`broadMatch`/`narrowMatch`/`relatedMatch` SHOULD NOT be co-emitted unless a consumer explicitly requests it, since such a triple asserts a broader, narrower or merely related relation, not that the value holds under the synonym property, so the requester takes responsibility for that reading.", + "text_sha256": "1d8752aa41f9ee074a8b56e0e957c837218642db3fe32699d62cd0e5a669456b", + "context": "Co-emission. Selection yields one IRI per term; for interoperability a converter MAY additionally co-emit the instance value under other synonyms' IRIs. This is a pragmatic interoperability aid, not a logical entailment: `skos:exactMatch` records that two terms are interchangeable across a wide range of applications, but it is not `owl:equivalentProperty` / `owl:equivalentClass` and licenses no reasoner inference - which is exactly why the mapping predicates are SKOS (reasoner-safe) rather than OWL. By default a converter co-emits only `skos:exactMatch` entries; entries whose `predicate_id` is `skos:closeMatch`/`broadMatch`/`narrowMatch`/`relatedMatch` SHOULD NOT be co-emitted unless a consumer explicitly requests it, since such a triple asserts a broader, narrower or merely related relation, not that the value holds under the synonym property, so the requester takes responsibility for that reading.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:64" + }, + { + "id": "OOLD-EXT-7c5d", + "area": "EXT", + "level": "MUST", + "applies_to": "implementation", + "section": "synonyms", + "summary": "A conforming mapping processor reads exactly the synonym IRI, the term-definition fragment, predicate_id and mapping_set_id from an entry.", + "text": "A conforming OO-LD mapping processor MUST read exactly four things from each entry: the synonym IRI (the key), the promotable term-definition fragment, and two `x-oold-sssom` slots - `predicate_id` and `mapping_set_id`.", + "text_sha256": "c427f66d6c7aff32fe62825b744d49ce754281ed070248a0d31324295985cf1e", + "context": "Processing contract. A conforming OO-LD mapping processor MUST read exactly four things from each entry: the synonym IRI (the key), the promotable term-definition fragment, and two `x-oold-sssom` slots - `predicate_id` and `mapping_set_id`. Conformance MUST NOT depend on anything else an entry carries (the rest of `x-oold-sssom`, any further fragment keys); a processor MAY interpret such keys as its own extension, and MUST carry them through unchanged where it rewrites an entry rather than promoting it - promotion deliberately drops the `x-oold-sssom` blocks, as Selection describes below. Those two slots, over the SKOS predicate vocabulary, are the whole stable contract an implementation depends on.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:56" + }, + { + "id": "OOLD-EXT-8f62", + "area": "EXT", + "level": "MUST NOT", + "applies_to": "implementation", + "section": "synonyms", + "summary": "Selection must not use a synonym outside the target profile; within an ordered profile the highest-priority match wins.", + "text": "Selection MUST NOT use a synonym from outside the target profile; where the profile is an ordered list, the highest-priority match wins and a lower-priority entry is selected only where no higher one matches.", + "text_sha256": "6c1a14a9767b73741bc1b264af5d472191cb51e19cf4c4daa824ba35c814efc3", + "context": "Selection. To promote `x-oold-context` into a real `@context`, a preprocessor MUST select one synonym per term for a target profile, write `{ \"@id\": , ...fragment without x-oold-sssom }` as that term's definition, and drop the `x-oold-sssom` blocks, so standard JSON-LD tools then run on a clean context. A profile is expressed either as an ordered list of IRI namespaces (ontology-family priority - `schema:` before `bfo:` before `emmo:`) or as one or more `mapping_set_id`s (a set may span namespaces, e.g. a PMDco profile of `pmd:` plus reused `obo:` terms). A term with no synonym matching the target keeps its default `@context` IRI. Selection MUST NOT use a synonym from outside the target profile; where the profile is an ordered list, the highest-priority match wins and a lower-priority entry is selected only where no higher one matches.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:62" + }, + { + "id": "OOLD-EXT-adcc", + "area": "EXT", + "level": "MUST NOT", + "applies_to": "implementation", + "section": "synonyms", + "summary": "Conformance must not depend on anything an entry carries beyond the four contract members.", + "text": "Conformance MUST NOT depend on anything else an entry carries (the rest of `x-oold-sssom`, any further fragment keys); a processor MAY interpret such keys as its own extension, and MUST carry them through unchanged where it rewrites an entry rather than promoting it - promotion deliberately drops the `x-oold-sssom` blocks, as Selection describes below.", + "text_sha256": "8396100be9d471ae2bf7a2767ad2b384b737e72888ccc960b9dcaf00616f13ac", + "context": "Processing contract. A conforming OO-LD mapping processor MUST read exactly four things from each entry: the synonym IRI (the key), the promotable term-definition fragment, and two `x-oold-sssom` slots - `predicate_id` and `mapping_set_id`. Conformance MUST NOT depend on anything else an entry carries (the rest of `x-oold-sssom`, any further fragment keys); a processor MAY interpret such keys as its own extension, and MUST carry them through unchanged where it rewrites an entry rather than promoting it - promotion deliberately drops the `x-oold-sssom` blocks, as Selection describes below. Those two slots, over the SKOS predicate vocabulary, are the whole stable contract an implementation depends on.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:56" + }, + { + "id": "OOLD-EXT-af50", + "area": "EXT", + "level": "REQUIRED", + "applies_to": "document", + "section": "jsonschema-extensions", + "summary": "JSON Schema 2020-12 is required as the dialect, because composition places $ref alongside sibling keywords.", + "text": "2020-12 is REQUIRED, not merely preferred: OO-LD's composition places `$ref` alongside sibling keywords (e.g. a property carrying `type`, `x-oold-range` and `@context`, or `allOf: [{$ref: ...}]` next to `properties`).", + "text_sha256": "72547da1a2d09844c2095de159112d47feea6881c50f48ad7d968f755330748b", + "context": "2020-12 is REQUIRED, not merely preferred: OO-LD's composition places `$ref` alongside sibling keywords (e.g. a property carrying `type`, `x-oold-range` and `@context`, or `allOf: [{$ref: ...}]` next to `properties`). Keywords adjacent to `$ref` are only evaluated from JSON Schema 2019-09 onward; in Draft 4 and Draft 7 they are ignored (JSONSCHEMA §8.2.3.1). Keywords such as `const` (used throughout this document) are likewise only available from draft-06 onward. Migration from the earlier Draft-4-style notation: rename `definitions` to `$defs`, `id` to `$id`, and use the numeric form of `exclusiveMinimum`/`exclusiveMaximum` instead of the boolean form.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:187" + }, + { + "id": "OOLD-EXT-b23b", + "area": "EXT", + "level": "SHOULD", + "applies_to": "implementation", + "section": "enum-names", + "summary": "A form generator labels an option with x-oold-ui-enum-titles where the schema gives it, and may show x-enum-descriptions as further explanation.", + "text": "a form generator SHOULD label each option with [`x-oold-ui-enum-titles`](#ui-generation) where the schema gives it, and MAY additionally present `x-enum-descriptions` as further explanation - help text or a tooltip beside the option - rather than as the label itself.", + "text_sha256": "3e4db6d0120646f017b231c986401334c428bf6180dd10a230da209ecbd7f943", + "context": "Three keywords serve two generators. Code generation uses `x-enum-varnames` for the member name and `x-enum-descriptions` for that member's doc comment. Form generation uses a keyword of its own for the option label, [`x-oold-ui-enum-titles`](#ui-generation): a form generator SHOULD label each option with [`x-oold-ui-enum-titles`](#ui-generation) where the schema gives it, and MAY additionally present `x-enum-descriptions` as further explanation - help text or a tooltip beside the option - rather than as the label itself.", + "machine_checkable": false, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "09-extensions.md:204" + }, + { + "id": "OOLD-EXT-b249", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "enum-names", + "summary": "An enum whose values are not all valid identifiers should declare x-enum-varnames.", + "text": "Where any `enum` value is not a valid identifier in the target language, the schema SHOULD declare `x-enum-varnames`, because each generator otherwise applies its own mangling: the member name becomes toolchain-dependent, and two values differing only in characters the mangling strips can collapse onto a single member.", + "text_sha256": "48a867bb4a45f9c94cb0aa8a8cda5406c8d95c801abb2011eebfc22ababb73ad", + "context": "Where any `enum` value is not a valid identifier in the target language, the schema SHOULD declare `x-enum-varnames`, because each generator otherwise applies its own mangling: the member name becomes toolchain-dependent, and two values differing only in characters the mangling strips can collapse onto a single member. Where every value is already a valid identifier the keyword MAY be omitted, since a generator derives the same names from the values.", + "machine_checkable": true, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "09-extensions.md:200" + }, + { + "id": "OOLD-EXT-dd76", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "localizing-schema-annotations", + "summary": "A schema using multilingual annotations should still provide a default title and description.", + "text": "A schema SHOULD still provide a default `title` / `description`; a consumer that has no entry for the requested language falls back to that default.", + "text_sha256": "bbbf0172cbf0c77fbe39625c8df206a570aa41f405c9e9a213152154d1e4486d", + "context": "The JSON Schema annotation keywords `title` and `description` carry a single, default human-readable string used by tooling (for example for UI generation). To provide localized variants, OO-LD adds the keywords `x-oold-multilang-title` and `x-oold-multilang-description`. Their value MUST be an object whose keys are [BCP 47](https://www.rfc-editor.org/info/bcp47) language tags (e.g. `en`, `de`, `en-GB`) and whose values are the translated strings. A schema SHOULD still provide a default `title` / `description`; a consumer that has no entry for the requested language falls back to that default. These keywords localize the schema's own labels and are not interpreted as JSON-LD.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:212" + }, + { + "id": "OOLD-EXT-ddda", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "processing-mode", + "summary": "A generated context should declare @version 1.1 as a JSON number.", + "text": "Generated OO-LD contexts SHOULD therefore declare `\"@version\": 1.1` (the JSON number `1.1`, not the string `\"1.1\"`).", + "text_sha256": "d4435d679d95a50a4cb65f720ee08a3c8637db3652d2b8310d1d08cac0de0946", + "context": "Generated OO-LD contexts SHOULD therefore declare `\"@version\": 1.1` (the JSON number `1.1`, not the string `\"1.1\"`). Modern processors default to the 1.1 processing mode, so this is a guard rather than a strict requirement: it prevents a JSON-LD 1.0 processor from silently mis-processing a 1.1 document (JSON-LD11 §4.1.1). Because the first encountered `@version` entry determines the processing mode, it is sufficient to declare `\"@version\": 1.1` once in the base context of a composition (for example a root `Thing` schema).", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:13" + }, + { + "id": "OOLD-EXT-ece0", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "range-of-properties", + "summary": "A published reference should point at a target that validates against the property's declared range.", + "text": "A published reference SHOULD point at a target that validates against the property's declared range.", + "text_sha256": "261731e44c8056793242380d5f01d4bade80a43f9db81cbc6c04296d2eeeffd7", + "context": "An `x-oold-range` value is a reference: the property holds the target's IRI, and an OO-LD-aware loader MAY dereference that IRI to obtain the target document itself, so a large or shared object can live in a separate document and be pulled in on demand (data bundling). A published reference SHOULD point at a target that validates against the property's declared range. A loader that dereferences a target MUST validate it against that range before treating it as a member, and MUST NOT assume the target conforms, since the target is a separate document that may change independently of the reference. This holds whether the reference is written as a bare IRI string or as a `{ \"@id\": … }` object; generic tooling leaves it unresolved, exactly as it leaves `x-oold-ref` (see [](#why-x-oold-ref)).", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:337" + }, + { + "id": "OOLD-EXT-ef09", + "area": "EXT", + "level": "MUST", + "applies_to": "document", + "section": "localizing-schema-annotations", + "summary": "x-oold-multilang-title/description must map BCP 47 language tags to translated strings.", + "text": "Their value MUST be an object whose keys are [BCP 47](https://www.rfc-editor.org/info/bcp47) language tags (e.g. `en`, `de`, `en-GB`) and whose values are the translated strings.", + "text_sha256": "f283baf414a7d41c21181aab27a32af73c618fa651fb20cb8d9ad80392063cf6", + "context": "The JSON Schema annotation keywords `title` and `description` carry a single, default human-readable string used by tooling (for example for UI generation). To provide localized variants, OO-LD adds the keywords `x-oold-multilang-title` and `x-oold-multilang-description`. Their value MUST be an object whose keys are [BCP 47](https://www.rfc-editor.org/info/bcp47) language tags (e.g. `en`, `de`, `en-GB`) and whose values are the translated strings. A schema SHOULD still provide a default `title` / `description`; a consumer that has no entry for the requested language falls back to that default. These keywords localize the schema's own labels and are not interpreted as JSON-LD.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:212" + }, + { + "id": "OOLD-EXT-fdd8", + "area": "EXT", + "level": "SHOULD", + "applies_to": "document", + "section": "value-term-aliases", + "summary": "A property coerced @type @vocab should constrain its values with an enum or x-oold-range.", + "text": "A property coerced `\"@type\": \"@vocab\"` therefore SHOULD constrain its values with an `enum` of the value terms (optionally named with `x-enum-varnames`) or with `x-oold-range`, so only intended individuals are accepted.", + "text_sha256": "c4bcd0af638b79ed0dc4ec4e25a597d38f2b3a957fab6ec77075e728b5887712", + "context": "Because `@vocab` expands an unmatched string against the vocabulary - concatenating it onto the default vocabulary base when one is set (minting a new IRI), or leaving it a relative IRI when none is - a typo silently becomes a stray IRI rather than an error. A property coerced `\"@type\": \"@vocab\"` therefore SHOULD constrain its values with an `enum` of the value terms (optionally named with `x-enum-varnames`) or with `x-oold-range`, so only intended individuals are accepted. The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (`id`, `type`) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name. Confining the value terms to the property's own scoped `@context` keeps them out of that shared namespace, since they then resolve only for that property's values; naming them with opaque identifiers such as UUIDs avoids the clash where readability is not required.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "09-extensions.md:352" + }, + { + "id": "OOLD-INS-1d33", + "area": "INS", + "level": "MUST", + "applies_to": "implementation", + "section": "identity", + "summary": "An exported identifiable entity must carry an IRI.", + "text": "An implementation MAY use a non-IRI identifier internally, but when it exports an identifiable entity (to JSON-LD / RDF) it MUST assign an `@id` (or the aliased `id`).", + "text_sha256": "0ca31c621870dd1904ce0662b98d9c3633da1d2fa2eb149d4d7c592407a26ba3", + "context": "An implementation MAY use a non-IRI identifier internally, but when it exports an identifiable entity (to JSON-LD / RDF) it MUST assign an `@id` (or the aliased `id`). The `@id` SHOULD be resolvable, and it is RECOMMENDED to mint it from an autogenerated UUID - mirroring the schema's `x-oold-uuid` - e.g. `https://example.org/a1b2c3d4-1234-...`.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:62" + }, + { + "id": "OOLD-INS-1df7", + "area": "INS", + "level": "MUST NOT", + "applies_to": "document", + "section": "value-forms", + "summary": "Under the value-form pattern a reference is written as an object and its term must not carry @type.", + "text": "References are written as objects, and the term MUST NOT carry `@type`.", + "text_sha256": "7ed52efe5f63156ec8bd6abec09bae6117bf64fead052cf226687b15def1f02c", + "context": "1. Value-form - a single plain term (no `@type: \"@id\"`); the value shape alone disambiguates: a bare scalar is a literal, `{ \"id\": ... }` is a reference, a typed object is embedded. References are written as objects, and the term MUST NOT carry `@type`.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:138" + }, + { + "id": "OOLD-INS-27aa", + "area": "INS", + "level": "SHOULD NOT", + "applies_to": "implementation", + "section": "referencing-schema", + "summary": "A consumer should not blindly trust the schema an instance declares for itself.", + "text": "JSON Schema deliberately does not standardize `$schema` on instances, partly over a self-validation concern: a consumer SHOULD NOT blindly trust the schema an instance declares for itself (a crafted instance could point at a permissive schema) and remains responsible for validating against a schema it trusts.", + "text_sha256": "5fe40a0c4116c197a46477bc16e26da36e667f9c1f2cdccc812a20078affaf30", + "context": "`@context` already provides a JSON-LD-native link to the schema (resolution case 2 above), so `$schema` is kept primarily for compatibility with the widespread editor and CI convention, not as a second authoritative mechanism. JSON Schema deliberately does not standardize `$schema` on instances, partly over a self-validation concern: a consumer SHOULD NOT blindly trust the schema an instance declares for itself (a crafted instance could point at a permissive schema) and remains responsible for validating against a schema it trusts.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:39" + }, + { + "id": "OOLD-INS-2b3f", + "area": "INS", + "level": "SHOULD", + "applies_to": "document", + "section": "identity", + "summary": "Schemas should expose @id through an aliased id property.", + "text": "To keep instance keys variable-name-friendly, schemas SHOULD expose `@id` through an aliased `id` property (as with `type` -> `@type`):", + "text_sha256": "4f852db64a6532e49924b789cb0fdc636d349b6990b28a6b417d10ed49e564e0", + "context": "To keep instance keys variable-name-friendly, schemas SHOULD expose `@id` through an aliased `id` property (as with `type` -> `@type`):", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:45" + }, + { + "id": "OOLD-INS-2e5d", + "area": "INS", + "level": "MUST NOT", + "applies_to": "document", + "section": "value-forms", + "summary": "A property whose range includes free text must not use @type @id.", + "text": "A property whose range is references only therefore uses `@type: \"@id\"` and MAY be written as a bare IRI string; a property whose range includes free text MUST NOT use `@type: \"@id\"`.", + "text_sha256": "a25ac65edb99dd6ad5c5c7eb84e9c8c31eae9bc323fe5f241c7d8b0dfefa8948", + "context": "A single `@context` term cannot interpret a bare string as both a literal and an IRI: `@type: \"@id\"` coerces every string value to an IRI (so free text becomes an - often invalid, then dropped - IRI), while a plain term keeps every string a literal. A property whose range is references only therefore uses `@type: \"@id\"` and MAY be written as a bare IRI string; a property whose range includes free text MUST NOT use `@type: \"@id\"`.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:134" + }, + { + "id": "OOLD-INS-4b5c", + "area": "INS", + "level": "MUST", + "applies_to": "document", + "section": "semantic-type", + "summary": "An inline type must be consistent with the schema's x-oold-instance-rdf-type.", + "text": "If an inline `type` is present it MUST be consistent with the schema's `x-oold-instance-rdf-type`.", + "text_sha256": "e299166560553f9f4cc299e1da6315d09fbd878673eecdf78fce526bf6ae2f1b", + "context": "If an inline `type` is present it MUST be consistent with the schema's `x-oold-instance-rdf-type`. Note that `@type` alone lets a consumer locate the schema (case 3 above) only when one of the type IRIs resolves to an OO-LD schema.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:107" + }, + { + "id": "OOLD-INS-559f", + "area": "INS", + "level": "MUST", + "applies_to": "document", + "section": "semantic-type", + "summary": "The nearest x-oold-instance-rdf-type declaration in an allOf chain replaces a base class's value rather than appending to it.", + "text": "The nearest declaration in the `allOf` chain is authoritative and MUST replace a base class's value rather than append to it.", + "text_sha256": "39b70037901e41876545b50e5cca0c1f9d2d1bab77069b3edfe024538891aed3", + "context": "Under composition, `x-oold-instance-rdf-type` follows the same most-derived-wins rule as the rest of the schema (see [](#composition)). The nearest declaration in the `allOf` chain is authoritative and MUST replace a base class's value rather than append to it. Superclass types are recoverable by ontology inference (`rdfs:subClassOf`) and so need not be materialized; a schema that wants a supertype carried in the data lists it explicitly (e.g. `[\"schema:Researcher\", \"schema:Person\"]`).", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:109" + }, + { + "id": "OOLD-INS-75c6", + "area": "INS", + "level": "MUST", + "applies_to": "implementation", + "section": "semantic-type", + "summary": "Tooling exporting an instance must materialize the schema-declared rdf:type(s) as @type.", + "text": "Therefore, when OO-LD tooling exports an instance (to JSON-LD / RDF), it MUST materialize the declared `rdf:type`(s) as an `@type` on the instance, so that the type reaches RDF without access to the schema or to a type registry.", + "text_sha256": "3363473f627d54f6a732c599af8d3692ac0ba421a6b2770dff6347173934402c", + "context": "These types live in the schema, not in the instance data, so a JSON-LD-only processor - which sees only the instance and its `@context` - cannot derive them. Therefore, when OO-LD tooling exports an instance (to JSON-LD / RDF), it MUST materialize the declared `rdf:type`(s) as an `@type` on the instance, so that the type reaches RDF without access to the schema or to a type registry.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:78" + }, + { + "id": "OOLD-INS-9416", + "area": "INS", + "level": "SHOULD", + "applies_to": "document", + "section": "schema-instances", + "summary": "Instances should reference a versioned schema URL.", + "text": "Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.", + "text_sha256": "e9929e4d9ba01bc251bf092b05c886ff703d9432859d20c4c7db8dcdc6e8244d", + "context": "The two SHOULD point at the same schema URL, so that the context an instance is read with and the schema it is validated against are the same document. Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:17" + }, + { + "id": "OOLD-INS-ba9e", + "area": "INS", + "level": "MUST", + "applies_to": "document", + "section": "referencing-schema", + "summary": "A schema closing its objects must still permit the $schema and @context members.", + "text": "Because an instance carries `$schema` and `@context` as ordinary members, an OO-LD schema that closes its objects with `additionalProperties: false` or `unevaluatedProperties: false` MUST permit these two members, or conforming instances would fail validation.", + "text_sha256": "abd2bf2e989b2e2aea4cd7af0f6f7a3d69f802e6722467da727bd915940f1b68", + "context": "Because an instance carries `$schema` and `@context` as ordinary members, an OO-LD schema that closes its objects with `additionalProperties: false` or `unevaluatedProperties: false` MUST permit these two members, or conforming instances would fail validation.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:37" + }, + { + "id": "OOLD-INS-cb1a", + "area": "INS", + "level": "SHOULD", + "applies_to": "document", + "section": "schema-instances", + "summary": "An instance's @context and $schema should point at the same schema URL.", + "text": "The two SHOULD point at the same schema URL, so that the context an instance is read with and the schema it is validated against are the same document.", + "text_sha256": "523bf44316cca4e0b580834e1c588fb24e88d3720b86285bcea4ce7b4beb3990", + "context": "The two SHOULD point at the same schema URL, so that the context an instance is read with and the schema it is validated against are the same document. Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:17" + }, + { + "id": "OOLD-INS-cd80", + "area": "INS", + "level": "SHOULD", + "applies_to": "document", + "section": "identity", + "summary": "An instance @id should be resolvable, and is recommended to be minted from an autogenerated UUID.", + "text": "The `@id` SHOULD be resolvable, and it is RECOMMENDED to mint it from an autogenerated UUID - mirroring the schema's `x-oold-uuid` - e.g. `https://example.org/a1b2c3d4-1234-...`.", + "text_sha256": "c6075abdc17f9bb557fca8e7cc0d67b4ebc4af17797cb1ce28c4b6f8035cc89f", + "context": "An implementation MAY use a non-IRI identifier internally, but when it exports an identifiable entity (to JSON-LD / RDF) it MUST assign an `@id` (or the aliased `id`). The `@id` SHOULD be resolvable, and it is RECOMMENDED to mint it from an autogenerated UUID - mirroring the schema's `x-oold-uuid` - e.g. `https://example.org/a1b2c3d4-1234-...`.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:62" + }, + { + "id": "OOLD-INS-da1a", + "area": "INS", + "level": "SHOULD", + "applies_to": "advisory", + "section": "value-forms", + "summary": "A model ecosystem should adopt one of the two ambiguous-range patterns consistently.", + "text": "For a property whose range mixes free text with references and/or embedded objects (for example `Text | PostalAddress | Place`), two patterns keep the instance round-trippable (see [](#round-trip)); a model ecosystem SHOULD adopt one of them consistently:", + "text_sha256": "fd5834cb52f2ba7a41d5919db177c636bb08de85e3d8484c246a8c70e88fe921", + "context": "For a property whose range mixes free text with references and/or embedded objects (for example `Text | PostalAddress | Place`), two patterns keep the instance round-trippable (see [](#round-trip)); a model ecosystem SHOULD adopt one of them consistently:\n1. Value-form - a single plain term (no `@type: \"@id\"`); the value shape alone disambiguates: a bare scalar is a literal, `{ \"id\": ... }` is a reference, a typed object is embedded. References are written as objects, and the term MUST NOT carry `@type`.\n2. Separate keys - a canonical term `p` with `@type: \"@id\"` (a bare IRI string reference, plus embedded objects via a scoped `@context`) and a companion `p_text` that is a plain term for the literal.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:136" + }, + { + "id": "OOLD-INS-f010", + "area": "INS", + "level": "MUST NOT", + "applies_to": "implementation", + "section": "referencing-schema", + "summary": "A consuming side must not be assumed to hold an rdf:type-to-schema registry; exports are self-sufficient.", + "text": "An implementation MAY additionally maintain a registry mapping `rdf:type` IRIs to OO-LD schemas to resolve case 3, but such a registry MUST NOT be assumed to exist on the consuming side - so exports must be self-sufficient (see below).", + "text_sha256": "1f3874f3ae2f46ff72ae03f0f5b715296e7b637357bb3d8ac6eec656688fc17b", + "context": "An implementation MAY additionally maintain a registry mapping `rdf:type` IRIs to OO-LD schemas to resolve case 3, but such a registry MUST NOT be assumed to exist on the consuming side - so exports must be self-sufficient (see below).", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:35" + }, + { + "id": "OOLD-RT-08f2", + "area": "RT", + "level": "MUST", + "applies_to": "document", + "section": "round-trip", + "summary": "A strictly array-typed property must declare @container @set or @list.", + "text": "Because the reconstruction MUST re-validate, a property that is strictly an array (JSON Schema `type: \"array\"`) MUST declare `@container: \"@set\"` (or `\"@list\"`): without it a single-element array returns as a scalar and violates the `array` type.", + "text_sha256": "cccd90d1135476689792616dac8db9b85956567b4d689637621b77cdbec356f5", + "context": "- Multi-valued properties are set-valued in RDF: order is not preserved, duplicates are removed, and a single value compacts to a scalar. Because the reconstruction MUST re-validate, a property that is strictly an array (JSON Schema `type: \"array\"`) MUST declare `@container: \"@set\"` (or `\"@list\"`): without it a single-element array returns as a scalar and violates the `array` type. A property that also permits a scalar (an `anyOf`/`oneOf` of a literal and an array) MAY declare it for a stable array shape, but need not - the scalar form still validates, and a single value and a one-element array are JSON-LD-equivalent. Round-trip equality is set equality. A property SHOULD NOT declare `@list` unless the order of its values is significant, since ordering costs merge and query ergonomics.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:180" + }, + { + "id": "OOLD-RT-2028", + "area": "RT", + "level": "SHOULD NOT", + "applies_to": "document", + "section": "round-trip", + "summary": "A property should not declare @list unless the order of its values is significant.", + "text": "A property SHOULD NOT declare `@list` unless the order of its values is significant, since ordering costs merge and query ergonomics.", + "text_sha256": "a3db6b5a849249ccab57c724863d0b6460bc36cff7876ceb00a8c44b23ff746c", + "context": "- Multi-valued properties are set-valued in RDF: order is not preserved, duplicates are removed, and a single value compacts to a scalar. Because the reconstruction MUST re-validate, a property that is strictly an array (JSON Schema `type: \"array\"`) MUST declare `@container: \"@set\"` (or `\"@list\"`): without it a single-element array returns as a scalar and violates the `array` type. A property that also permits a scalar (an `anyOf`/`oneOf` of a literal and an array) MAY declare it for a stable array shape, but need not - the scalar form still validates, and a single value and a one-element array are JSON-LD-equivalent. Round-trip equality is set equality. A property SHOULD NOT declare `@list` unless the order of its values is significant, since ordering costs merge and query ergonomics.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:180" + }, + { + "id": "OOLD-RT-a12c", + "area": "RT", + "level": "MUST", + "applies_to": "document", + "section": "round-trip", + "summary": "An embedded object must carry an explicit type where the scoped context is type-scoped or the reconstruction frame matches on @type.", + "text": "The embedded object MUST carry an explicit `type` where the property's scoped `@context` is type-scoped - keyed by the value's `@type` to distinguish several embedded types (or to stamp the node's `rdf:type`) - or where the frame used to reconstruct it matches on `@type`, as a frame derived from the schema's class type does (see [](#framing)).", + "text_sha256": "064ffda87f246a6a69473c3f5fb31e58fcb9dc5c57f1f2d3583df3c402395f48", + "context": "- Embedded objects are flattened in RDF, and compaction does not re-nest a flat graph, so reconstructing the tree requires [Framing](#framing) - the frame can be as small as `{ \"\": {} }`. The embedded object MUST carry an explicit `type` where the property's scoped `@context` is type-scoped - keyed by the value's `@type` to distinguish several embedded types (or to stamp the node's `rdf:type`) - or where the frame used to reconstruct it matches on `@type`, as a frame derived from the schema's class type does (see [](#framing)). A flat scoped context reconstructed through a property-matching frame needs none. Where required, tooling materializes the type on export (see [](#semantic-type)).", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:179" + }, + { + "id": "OOLD-RT-ad63", + "area": "RT", + "level": "SHOULD NOT", + "applies_to": "document", + "section": "value-forms", + "summary": "A numeric property should not be coerced to a narrower datatype unless the exact RDF datatype matters.", + "text": "A numeric property SHOULD NOT be coerced to a narrower datatype, and its values SHOULD be left as native JSON numbers, unless the exact RDF datatype matters.", + "text_sha256": "0d9c417a64efe4f181ead588ab43f10d045c69269e15bac78256775442cbf94d", + "context": "Datatypes JSON-LD does not produce by default are the ones to declare with `@type`: the date/time family (`xsd:date`, `xsd:dateTime`, `xsd:time`, `xsd:duration`), `xsd:anyURI`, and every numeric refinement outside the two native ones (`xsd:float`, `xsd:decimal`, `xsd:long`, `xsd:int`, `xsd:unsignedByte`, ...). These stay explicit on the literal through the round-trip and compact back onto the term, but JSON has no native syntax for them, so their value is carried as a JSON string. The consequence is worth stating plainly: a JSON-native number can only ever be `xsd:integer` or `xsd:double`; any narrower or more specific numeric datatype is reached by writing the value as a string under an `@type` coercion (a bare JSON number under, say, `@type: \"xsd:float\"` keeps the term but comes back as its canonical string form). A numeric property SHOULD NOT be coerced to a narrower datatype, and its values SHOULD be left as native JSON numbers, unless the exact RDF datatype matters.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:166" + }, + { + "id": "OOLD-RT-d376", + "area": "RT", + "level": "SHOULD", + "applies_to": "document", + "section": "round-trip", + "summary": "The embed graph formed by scoped @contexts should be acyclic.", + "text": "These scoped contexts form an embed graph between schemas, and that graph SHOULD be acyclic: model a property whose value is an independent entity, or whose type would close an embed cycle (a type embedding itself, or two types embedding each other), as a reference - `@type: \"@id\"` plus `x-oold-range`, with no scoped `@context` - rather than an embed.", + "text_sha256": "c8d004af368510bff41449b8c6432b829dcf78f4966aff541cbe7c508a60ed52", + "context": "An embedded object is mapped by a scoped `@context` on its property (referencing the embedded type's own context). These scoped contexts form an embed graph between schemas, and that graph SHOULD be acyclic: model a property whose value is an independent entity, or whose type would close an embed cycle (a type embedding itself, or two types embedding each other), as a reference - `@type: \"@id\"` plus `x-oold-range`, with no scoped `@context` - rather than an embed. This is the linked-data analog of using a pointer instead of inlining a recursive data structure. A self-reference through the top-level `@context` (a property that nests the same type but carries no scoped context, so the global context maps the nested keys - e.g. a `Process` with sub-`Process`es) is not part of this graph and round-trips normally, bounded by the instance's actual depth.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:187" + }, + { + "id": "OOLD-RT-d9bd", + "area": "RT", + "level": "MUST NOT", + "applies_to": "document", + "section": "value-forms", + "summary": "A term must not coerce a literal to a datatype JSON-LD produces by default from a native JSON value (xsd:string, xsd:boolean, xsd:integer, xsd:double).", + "text": "A term MUST NOT declare `@type` with a datatype that JSON-LD produces by default from a native JSON value: `xsd:string` (from a string), `xsd:boolean` (from a boolean), `xsd:integer` (from an integer number), and `xsd:double` (from a fractional number).", + "text_sha256": "b32b762e810a70e38f25329563c43687ce6402c92f464eb8764ccaceb9376c54", + "context": "A term MUST NOT declare `@type` with a datatype that JSON-LD produces by default from a native JSON value: `xsd:string` (from a string), `xsd:boolean` (from a boolean), `xsd:integer` (from an integer number), and `xsd:double` (from a fractional number). These are exactly the datatypes reconstruction converts back to native JSON values without an `@type` (JSONLD11-API, RDF to Object Conversion; see [](#round-trip)): the value arrives from RDF with no datatype, and a term is never selected against a conflicting or absent type mapping (JSONLD11-API, Term Selection), so the value reappears under the full predicate IRI instead. Coercing to one of these is redundant and lossy - a native JSON number already round-trips as `xsd:integer` or `xsd:double` with no coercion at all, and a boolean/string likewise. This is inherent to the compaction algorithm, not a tooling limitation; such terms are left plain (no `@type`), and the projection to RDF still yields the correct datatype from the native JSON type (JSONLD11-API, Data Round Tripping). The behaviour assumes reconstruction with native types (`useNativeTypes`), the mainstream default: a processor that instead keeps every literal as a typed value object would select the coerced term, but then plain native numbers and booleans no longer return as native JSON either (they come back as `{ \"@value\": ..., \"@type\": ... }` objects), which defeats the structural model - so native-type reconstruction is assumed throughout.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "07-schema-instances.md:164" + }, + { + "id": "OOLD-SCH-21d7", + "area": "SCH", + "level": "SHOULD", + "applies_to": "document", + "section": "basic-concepts", + "summary": "A schema should offer at least one complete mapping, so its instances can round-trip through RDF without loss.", + "text": "A schema SHOULD offer at least one complete mapping - a [target profile](#synonyms) under which every declared property carries a term - because a property with no term produces no triple, so an instance can only round-trip through RDF without loss under a mapping that covers all of them.", + "text_sha256": "62ae3aa3447402336c6dfd9ae5a221e58a3727b9752de1054d9632b6b31a40f0", + "context": "Leaving a term unmapped is a deferral, not a destination. A schema SHOULD offer at least one complete mapping - a [target profile](#synonyms) under which every declared property carries a term - because a property with no term produces no triple, so an instance can only round-trip through RDF without loss under a mapping that covers all of them. A schema MAY carry further, deliberately partial profiles alongside it.", + "machine_checkable": true, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "05-basic-concepts.md:18" + }, + { + "id": "OOLD-SCH-2d05", + "area": "SCH", + "level": "MUST NOT", + "applies_to": "implementation", + "section": "basic-concepts", + "summary": "An unmapped term is not a conformance failure, though a tool may report it under an opt-in strict mode.", + "text": "An implementation MUST NOT treat an unmapped term as a conformance failure, though it MAY report one as guidance, or reject it under a strict mode the user opts into.", + "text_sha256": "717066e5d688bbd40921250987404f4e899fe73139282fd7d323cc527256d91c", + "context": "A term of an OO-LD schema MAY be left unmapped. An unmapped term is structurally valid and simply produces no triples under JSON-LD expansion, which is what lets semantics be added incrementally, one term at a time, rather than committed to up front. Where every term is intended to reach RDF, a schema MAY declare `@vocab` in its `@context`, mapping each otherwise-unmapped term into a default namespace, or carry the mapping in [`x-oold-context`](#synonyms), whose entries are promoted into the `@context` before a JSON-LD processor runs. An implementation MUST NOT treat an unmapped term as a conformance failure, though it MAY report one as guidance, or reject it under a strict mode the user opts into.", + "machine_checkable": false, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "05-basic-concepts.md:16" + }, + { + "id": "OOLD-SCH-a9ee", + "area": "SCH", + "level": "MUST NOT", + "applies_to": "implementation", + "section": "basic-concepts", + "summary": "An OO-LD schema document must not be interpreted as a JSON-LD document.", + "text": "OO-LD schema documents MUST NOT be interpreted as JSON-LD documents, because that would apply the schema's own `@context` to the schema itself and produce incorrect triples.", + "text_sha256": "635a77aac991bbe8295616c5465c2963e0d6a51618ed49c2d835d448dc53bfca", + "context": "- An OO-LD schema is consumed as a JSON-LD remote context (referenced by its URL from an instance's `@context`), never as a JSON-LD document. OO-LD schema documents MUST NOT be interpreted as JSON-LD documents, because that would apply the schema's own `@context` to the schema itself and produce incorrect triples.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "05-basic-concepts.md:11" + }, + { + "id": "OOLD-VER-2e63", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "identification", + "summary": "A schema should be resolvable via its $id.", + "text": "The schema SHOULD be resolvable via this URI.", + "text_sha256": "fd7f4ef994bb7fea2782f7c30ee8f8c2a3f9b8161c61ced1f2f038a64f106c2c", + "context": "OO-LD schemas MUST have a `$id` (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema. The value of `$id` MAY be an absolute URI (details below). The schema SHOULD be resolvable via this URI. The schema SHOULD have an annotation `x-oold-uuid` with a UUID value.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:5" + }, + { + "id": "OOLD-VER-3662", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "versioning", + "summary": "A schema version should be stated with x-oold-version.", + "text": "The schema version SHOULD be indicated by `x-oold-version`; a prior version MAY be indicated with `x-oold-prior-version`:", + "text_sha256": "7d62b2cbfa7d78f02f91d1e08fa0ac97e07385088b1b5da426e9f46dea77961a", + "context": "The schema version SHOULD be indicated by `x-oold-version`; a prior version MAY be indicated with `x-oold-prior-version`:", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:53" + }, + { + "id": "OOLD-VER-3b96", + "area": "VER", + "level": "MUST", + "applies_to": "document", + "section": "identification", + "summary": "A schema must have a $id serving as its global unique identifier.", + "text": "OO-LD schemas MUST have a `$id` (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema.", + "text_sha256": "0489dab8d39ad1fbe8057598def7a10fa00816ece4c6482b9e0de23145c82a3b", + "context": "OO-LD schemas MUST have a `$id` (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema. The value of `$id` MAY be an absolute URI (details below). The schema SHOULD be resolvable via this URI. The schema SHOULD have an annotation `x-oold-uuid` with a UUID value.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:5" + }, + { + "id": "OOLD-VER-4261", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "versioning", + "summary": "Under schema-package versioning, the package version should be prepended before the schema id.", + "text": "For schema-package versioning (recommended), the version of the package SHOULD be prepended before the schema's ID, e.g. `https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json`.", + "text_sha256": "4e2e5321caa2b8551df124896634f32ecdcd314d40dadde918a6310f297acf1b", + "context": "- For schema-package versioning (recommended), the version of the package SHOULD be prepended before the schema's ID, e.g. `https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json`. Since a package combines multiple schemas, the package version does in general not match the individual schema version.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:70" + }, + { + "id": "OOLD-VER-46b9", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "identification", + "summary": "A schema that carries an x-oold-uuid should also use it in its $id.", + "text": "A schema carrying `x-oold-uuid` SHOULD also use that UUID in its `$id`, so the identifier stays stable across a move between hosts or paths and the two identifiers cannot disagree about which schema they name.", + "text_sha256": "001c99d80b7203c504c23e8d611aa7425921edd311ef5da9d92f3f447db59f44", + "context": "A schema carrying `x-oold-uuid` SHOULD also use that UUID in its `$id`, so the identifier stays stable across a move between hosts or paths and the two identifiers cannot disagree about which schema they name.", + "machine_checkable": true, + "since": "1.0.0-rc.2", + "deprecated": false, + "source": "08-identification-versioning.md:7" + }, + { + "id": "OOLD-VER-534a", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "versioning", + "summary": "The schema version should be part of the schema location URL.", + "text": "The version SHOULD be part of the schema's location:", + "text_sha256": "9e4671a42c0df7845c72b1cb55c9723532573150183495259835ccfab7f4d6e2", + "context": "The version SHOULD be part of the schema's location:\n- For single-schema versioning, the version SHOULD be appended after the schema name, e.g. `https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0`.\n- For schema-package versioning (recommended), the version of the package SHOULD be prepended before the schema's ID, e.g. `https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json`. Since a package combines multiple schemas, the package version does in general not match the individual schema version.\n- or a release tag on a code-hosting service, e.g. `https://raw.githubusercontent.com/MyOrg/my-package/refs/tags/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json`. Such a location SHOULD name an immutable ref: a branch name identifies a moving target, whose content changes with every push, rather than a fixed version.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:67" + }, + { + "id": "OOLD-VER-befc", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "versioning", + "summary": "Under single-schema versioning, the version should be appended after the schema name in the $id.", + "text": "For single-schema versioning, the version SHOULD be appended after the schema name, e.g. `https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0`.", + "text_sha256": "3e485bd18653ac3e879efe279ac5938bf1e8657575a547e99f5084e3f1cb9089", + "context": "- For single-schema versioning, the version SHOULD be appended after the schema name, e.g. `https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0`.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:69" + }, + { + "id": "OOLD-VER-c92e", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "versioning", + "summary": "A schema published for long-term reuse should be identified by a persistent identifier that resolves to its current hosting.", + "text": "A raw hosting URL is convenient, but it binds the identifier to one host and one repository layout and carries no persistence guarantee, so a schema published for long-term reuse SHOULD be identified by a persistent identifier - a [w3id.org](https://w3id.org/) or [PURL](https://purl.archive.org/) redirect, or a DOI for a released package - that resolves to wherever the schema is currently hosted.", + "text_sha256": "f7d5ceea2f5d25ad799d9be7b2deadfd850969955652e4225f504a6d8ab1efaf", + "context": "A raw hosting URL is convenient, but it binds the identifier to one host and one repository layout and carries no persistence guarantee, so a schema published for long-term reuse SHOULD be identified by a persistent identifier - a [w3id.org](https://w3id.org/) or [PURL](https://purl.archive.org/) redirect, or a DOI for a released package - that resolves to wherever the schema is currently hosted. The persistent identifier is then the `$id`, and the raw URL is only where it happens to resolve today, so the schema survives a move between hosts without changing identity.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:73" + }, + { + "id": "OOLD-VER-d826", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "versioning", + "summary": "A version carried in a schema location should be pinned to an immutable ref, not a mutable branch.", + "text": "Such a location SHOULD name an immutable ref: a branch name identifies a moving target, whose content changes with every push, rather than a fixed version.", + "text_sha256": "639ac34295b99014677516da3066defd8cf90756ab98b1ccdd0945716b9a72cd", + "context": "- or a release tag on a code-hosting service, e.g. `https://raw.githubusercontent.com/MyOrg/my-package/refs/tags/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json`. Such a location SHOULD name an immutable ref: a branch name identifies a moving target, whose content changes with every push, rather than a fixed version.", + "machine_checkable": false, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:71" + }, + { + "id": "OOLD-VER-edb9", + "area": "VER", + "level": "SHOULD", + "applies_to": "document", + "section": "identification", + "summary": "A schema should carry an x-oold-uuid annotation holding a UUID value.", + "text": "The schema SHOULD have an annotation `x-oold-uuid` with a UUID value.", + "text_sha256": "0d1901b754364d33a17411f33fe61ba98d469d1df7389adab8f0a44c9276f355", + "context": "OO-LD schemas MUST have a `$id` (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema. The value of `$id` MAY be an absolute URI (details below). The schema SHOULD be resolvable via this URI. The schema SHOULD have an annotation `x-oold-uuid` with a UUID value.", + "machine_checkable": true, + "since": "1.0.0-rc.1", + "deprecated": false, + "source": "08-identification-versioning.md:5" + } + ] +} diff --git a/src/oold/validation/meta/1.0.0-rc.3/oold-rules.schema.json b/src/oold/validation/meta/1.0.0-rc.3/oold-rules.schema.json new file mode 100644 index 0000000..a56a86d --- /dev/null +++ b/src/oold/validation/meta/1.0.0-rc.3/oold-rules.schema.json @@ -0,0 +1,171 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://oo-ld.org/latest/meta/oold-rules.schema.json", + "title": "OO-LD rule catalog", + "$comment": "Describes meta/oold-rules.json, which scripts/extract_rules.py generates from the :rule[...] markers in spec/sections/*.md. The catalog is data that downstream validators read to decide which requirements exist and how hard a violation lands, so a truncated or malformed copy does not fail loudly on its own: it just looks like a specification with fewer rules. This schema is what turns that into an error.", + "type": "object", + "required": [ + "spec_version", + "rules" + ], + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "format": "iri-reference", + "description": "This document's schema. Released copies stamp their version in place of `latest`." + }, + "$comment": { + "type": "string" + }, + "spec_version": { + "$ref": "#/$defs/version", + "description": "The specification release this catalog was generated from. Moves with every tag, unlike a rule's `since`." + }, + "areas": { + "type": "object", + "description": "Area code to human-readable scope. Every rule's `area` is one of these keys.", + "propertyNames": { + "$ref": "#/$defs/area" + }, + "additionalProperties": { + "type": "string", + "minLength": 1 + } + }, + "applies_to": { + "type": "object", + "description": "Binding to what enforcing it would take. Every rule's `applies_to` is one of these keys.", + "propertyNames": { + "$ref": "#/$defs/binding" + }, + "additionalProperties": { + "type": "string", + "minLength": 1 + } + }, + "rules": { + "type": "array", + "items": { + "$ref": "#/$defs/rule" + } + } + }, + "$defs": { + "area": { + "enum": [ + "CNF", + "SCH", + "CMP", + "INS", + "RT", + "VER", + "EXT" + ] + }, + "binding": { + "enum": [ + "document", + "implementation", + "advisory" + ] + }, + "version": { + "type": "string", + "minLength": 1 + }, + "rule": { + "type": "object", + "required": [ + "id", + "area", + "level", + "applies_to", + "section", + "summary", + "text", + "text_sha256", + "machine_checkable", + "since", + "deprecated", + "source" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "pattern": "^OOLD-(CNF|SCH|CMP|INS|RT|VER|EXT)-[0-9a-f]{4}$", + "description": "Permanent and never reused. The suffix is a minted hex value, not a sequential number, so a deprecated rule leaves no visible gap. Downstream checks cite the id, so the pattern is asserted rather than assumed; see meta/RULES.md." + }, + "area": { + "$ref": "#/$defs/area" + }, + "level": { + "enum": [ + "MUST", + "MUST NOT", + "SHALL", + "SHALL NOT", + "SHOULD", + "SHOULD NOT", + "REQUIRED", + "RECOMMENDED", + "NOT RECOMMENDED" + ], + "description": "The RFC 2119 keyword in the marked prose. A validator reads this to decide whether a violation fails or warns, and never hardcodes it." + }, + "applies_to": { + "$ref": "#/$defs/binding" + }, + "section": { + "type": "string", + "minLength": 1 + }, + "summary": { + "type": "string", + "minLength": 1 + }, + "text": { + "type": "string", + "minLength": 1, + "description": "The normative prose itself, cleaned of markup." + }, + "text_sha256": { + "type": "string", + "pattern": "^[0-9a-f]{64}$", + "description": "sha256 of `text`. meta/rules-baseline.json compares against this to catch a rule whose meaning changed under an unchanged id, so its shape is asserted here." + }, + "context": { + "type": "string", + "minLength": 1, + "description": "The containing block `text` was taken from, for display. May equal `text` when the rule's sentence is the whole block. Not hashed, and not part of the baseline comparison." + }, + "machine_checkable": { + "type": "boolean", + "description": "Whether the requirement is mechanically decidable by inspecting a document. Defaults to true for `document` rules only. This says nothing about whether any given validator actually enforces it - that is a separate, downstream fact." + }, + "since": { + "$ref": "#/$defs/version", + "description": "The release that first stated this rule. Carried forward once recorded; only an unseen id takes the current tag." + }, + "deprecated": { + "type": "boolean" + }, + "superseded_by": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "pattern": "^OOLD-(CNF|SCH|CMP|INS|RT|VER|EXT)-[0-9a-f]{4}$" + }, + "description": "Present only on a deprecated rule, naming what replaced it." + }, + "source": { + "type": "string", + "minLength": 1, + "description": "Where the marker sits, as `
:`. Regenerated on every run, so it is provenance rather than a stable reference." + } + } + } + } +} diff --git a/src/oold/validation/meta/1.0.0-rc.3/oold-ui-meta-schema.json b/src/oold/validation/meta/1.0.0-rc.3/oold-ui-meta-schema.json new file mode 100644 index 0000000..a7271aa --- /dev/null +++ b/src/oold/validation/meta/1.0.0-rc.3/oold-ui-meta-schema.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://oo-ld.org/latest/meta/oold-ui-meta-schema.json", + "$dynamicAnchor": "meta", + "title": "OO-LD UI dialect meta-schema", + "$comment": "The $id uses the versioned hosting at oo-ld.org/ (the source keeps the /latest/ placeholder; each released copy is stamped per release). The oold-ui vocabulary is declared optional (false) so that generic JSON-Schema 2020-12 validators still process the schema. The x-oold-ui-* keyword definitions live in $defs.keywords (plain anchor #keywords) so the main OO-LD meta-schema can include just them, without re-introducing the 2020-12 reference or a second dynamic anchor. Each keyword carries a description and an example so the vocabulary can be rendered into documentation. As with the core dialect, this meta-schema only validates that the keywords are well-formed; the behaviour is supplied by OO-LD-aware form generators (for example jedison).", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/core": true, + "https://json-schema.org/draft/2020-12/vocab/applicator": true, + "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, + "https://json-schema.org/draft/2020-12/vocab/validation": true, + "https://json-schema.org/draft/2020-12/vocab/meta-data": true, + "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, + "https://json-schema.org/draft/2020-12/vocab/content": true, + "https://oo-ld.org/latest/vocab/oold-ui": false + }, + "allOf": [ + { "$ref": "https://json-schema.org/draft/2020-12/schema" }, + { "$ref": "#keywords" } + ], + "$defs": { + "keywords": { + "$anchor": "keywords", + "properties": { + "x-oold-ui-widget": { + "description": "Widget hint for a value whose intended widget is not a registered JSON Schema format (for example table, tabs, grid, autocomplete, textarea, checkbox, markdown, color). Registered formats (date, uri, uuid, ...) stay in `format`. Maps to jedison `x-format`.", + "type": "string", + "examples": ["table", "autocomplete", "markdown"] + }, + "x-oold-ui-property-order": { + "description": "Display order of this property within its object or group; lower sorts first. Maps to jedison `x-categoryOrder`.", + "type": "integer", + "examples": [1] + }, + "x-oold-ui-property-group": { + "description": "Name of the group, tab or category this property belongs to. Maps to jedison `x-category` / `x-propGroup`.", + "type": "string", + "examples": ["General", "Contact"] + }, + "x-oold-ui-form-hidden": { + "description": "Hide this property in the editing form. Maps to jedison `x-hidden`.", + "type": "boolean", + "examples": [true] + }, + "x-oold-ui-render-hidden": { + "description": "Hide this property in the rendered (read) view.", + "type": "boolean", + "examples": [true] + }, + "x-oold-ui-enum-titles": { + "description": "Human display labels for the default language, aligned positionally with `enum`: the Nth label is the title of the Nth enum value. For `enum: [\"pi\", \"postdoc\", \"phd\"]` the value `[\"Principal investigator\", \"Postdoc\", \"PhD student\"]` labels each option. Localize with `x-oold-multilang-ui-enum-titles`. Distinct from the identifier-safe code names in `x-enum-varnames`. Maps to jedison `x-enumTitles`.", + "type": "array", + "items": { "type": "string" }, + "examples": [["Principal investigator", "Postdoc", "PhD student"]] + }, + "x-oold-multilang-ui-enum-titles": { + "description": "BCP-47 language map of `x-oold-ui-enum-titles` arrays (mirrors `x-oold-multilang-title`); each array aligns positionally with `enum`. For `enum: [\"pi\", \"postdoc\", \"phd\"]`: {\"en\": [\"Principal investigator\", \"Postdoc\", \"PhD student\"], \"de\": [\"Projektleitung\", \"Postdoc\", \"Doktorand\"]}.", + "type": "object", + "additionalProperties": { "type": "array", "items": { "type": "string" } }, + "examples": [{ "en": ["Principal investigator", "Postdoc", "PhD student"], "de": ["Projektleitung", "Postdoc", "Doktorand"] }] + }, + "x-oold-ui-hint": { + "description": "Short help text shown with the field, in the default language. Localize with `x-oold-multilang-ui-hint`. Maps to jedison `x-info`.", + "type": "string", + "examples": ["Full name"] + }, + "x-oold-multilang-ui-hint": { + "description": "BCP-47 language map of the `x-oold-ui-hint` text (mirrors `x-oold-multilang-title`).", + "type": "object", + "additionalProperties": { "type": "string" }, + "examples": [{ "en": "Full name", "de": "Vollständiger Name" }] + }, + "x-oold-ui-default-property": { + "description": "Whether this optional property is shown by default in generated user interfaces. Replaces the object-level `defaultProperties` array: a per-property boolean is overridable under composition (most-derived-wins), so a derived schema can set it false, whereas the merged array form was extend-only.", + "type": "boolean", + "examples": [true] + } + } + } + } +} diff --git a/src/oold/validation/meta/index.json b/src/oold/validation/meta/index.json index 06c91d0..f1d7afa 100644 --- a/src/oold/validation/meta/index.json +++ b/src/oold/validation/meta/index.json @@ -90,11 +90,34 @@ "oold-rules.json": "bf79dffda89063865ff8b7763576fd880655dd636e8720701db3545f27759536", "oold-rules.schema.json": "71e0d2e437d05a0a718612ed273993c3e216681c6c4cd426a6b3c1018f07e07a" } + }, + "1.0.0-rc.3": { + "tag": "v1.0.0-rc.3", + "commit": "28edc9923b5cbb672d976ce60b43f8d00b91542b", + "committed": "2026-08-23T13:31:04+02:00", + "added": "2026-08-23", + "id_base": "https://oo-ld.org/latest/meta/", + "prerelease": true, + "notes": "Mainly a normativity pass upstream. Four requirements that existed only inside a :::example, a :::note or a section marked .informative were moved into normative prose, so they can now be cited: OOLD-SCH-2d05 (an unmapped term is not a conformance failure), OOLD-SCH-21d7 (a schema should offer one complete mapping), OOLD-VER-46b9 (an x-oold-uuid should also appear in the $id) and OOLD-CMP-1257 (a composed object is closed with unevaluatedProperties). The UI section became normative, because its keywords are enforced by the meta-schema this dialect $refs, so disclaiming them contradicted what the schemas already validate. x-enum-varnames and x-enum-descriptions gained a normative section and moved from the UI meta-schema's $defs/keywords into oold-meta-schema-base.json's properties, which is why both of those files change here while oold-meta-schema.json and oold-pattern-lint.schema.json are byte-identical to v1.0.0-rc.2. The catalogue grew from 66 rules to 73 with none retired and no id reused; of the 66 already vendored, none changed level, applies or text, and OOLD-CMP-a05a changed machine_checkable to false, its trigger being authorial intent that no validator can see.", + "files": [ + "oold-meta-schema.json", + "oold-meta-schema-base.json", + "oold-pattern-lint.schema.json", + "oold-ui-meta-schema.json" + ], + "sha256": { + "oold-meta-schema.json": "7960a4508f8688b74b3096d7ac0828c9fe74089692d370c756eeef58b8785606", + "oold-meta-schema-base.json": "01fa8ded2ed24707292bcb7044a2e7edbcee0079d6d4f48525190298e3eff048", + "oold-pattern-lint.schema.json": "d89fce19cd2fd42fa740d92968fcf61a1764ea25e741ed5cd4e72040a45c9a86", + "oold-ui-meta-schema.json": "1a93b82e28d4d98252546eb2a579c9521496d3bb60be2bbb5af34b65b9fa6640", + "oold-rules.json": "9907c8b4227cec829d43377e85d542bcc4664356b3c37d46d24aed46fbcaae11", + "oold-rules.schema.json": "efdcb1fbbb592f7881b33fdbace62d5a785e36a37ad58312a39ddc5e85a10ae7" + } } }, "fixtures": { "$comment": "Provenance of the fixture slice in tests/data/oold/, which is a copy of the upstream examples/ directory. Recorded here rather than stated in that folder's README, because a tag is data: the README claimed v0.8.0 for a full release after the slice had moved to v1.0.0-rc.1, and nothing noticed. `tag` must name the newest entry in `versions`, so that fixtures and meta-schemas always come from one release; a test asserts it. The locally authored fixtures under broken/ and remote_context/ are not part of this slice and no refresh touches them.", - "tag": "v1.0.0-rc.2", + "tag": "v1.0.0-rc.3", "source": "examples/", "destination": "tests/data/oold/" }