Skip to content

Review fixes: @type alias round-trip, enforce the $id MUST, document examples/default - #122

Open
simontaurus wants to merge 3 commits into
mainfrom
fix/rc2-corrections
Open

Review fixes: @type alias round-trip, enforce the $id MUST, document examples/default#122
simontaurus wants to merge 3 commits into
mainfrom
fix/rc2-corrections

Conversation

@simontaurus

@simontaurus simontaurus commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Addresses #117, #118 and #120 from the v1.0.0-rc.1 review (thanks @LukasOro - all three came out of porting the EU Battery Passport model from SAMM).

#117 - the type -> @type alias is not round-trip safe (bug)

Confirmed and fixed. The normative "Carrying the type inline" example declared type as a strict type: array but aliased it plainly ("type": "@type"), and a plain-string term cannot carry @container - so a single @type compacted back from RDF as a scalar and failed the spec's own re-validation MUST.

Verified with jsonld.js:

@context term round-trip result
"type": "@type" "schema:Person" - scalar, fails type: array
"type": { "@id": "@type", "@container": "@set" } ["schema:Person"] - array, re-validates

The example now uses the @container: "@set" form, and the prose says explicitly that a strict-array type property needs it like any other strict-array property. Scope is that one example: the examples/ schemas alias type too but declare no strict-array type property, which is why the self-suite did not catch it.

#118 - nothing enforced the $id MUST (now it does)

The premise that JSON Schema cannot express a root-only requirement turns out not to hold - it can, via $dynamicAnchor scoping, which is exactly what the standard 2020-12 meta-schema does. The dialect is now two-tier:

  • meta/oold-meta-schema.json (unchanged URL, what $schema points at) carries the document-level obligations - required: ["$id"] - and $refs the body.
  • meta/oold-meta-schema-base.json (new) holds the keyword syntax and $dynamicAnchor: "meta". Nested subschemas recurse into the base via the standard $dynamicRef, so a fragment in properties / $defs / x-oold-range is validated against the dialect without being required to carry $id.

Verified in both target ecosystems - ajv 8 and Python jsonschema 4.26 - with the real files: root with $id and $id-less nested fragments passes; a root without $id is rejected. No new tooling support is required: the official 2020-12 meta-schema is itself built on $dynamicAnchor/$dynamicRef, and our meta-schemas already declared the anchor.

Fallout, all mechanical: compliance fixtures that are document roots gained a $id (28 in oold-vocab.json, 5 feature schemas in roundtrip-patterns.json - the lintSchemas group is checked against the pattern lint, not the meta-schema, so it is untouched), and validate.mjs registers the base and reads the keyword list from it.

#120 - examples / default are load-bearing (documented)

The harness generates instances with useExamplesValue / useDefaultValue, so those annotations must satisfy their own subschema even though JSON Schema does not validate them. The behaviour is worth keeping (it caught real upstream defects), it was just undocumented and surfaced as a confusing GEN-INVALID. docs/tooling.md now states it and notes that a GEN-INVALID pointing at such a value indicates the annotation, not an unsatisfiable schema.


Not included: #119 (generator guidance) is deferred pending the SAMM evaluation - the direction there is that SAMM's URNs do allow deriving a context, the open question is preserve-vs-mint, and x-oold-uuid should be a UUIDv5 seeded from the stable source identifier so regeneration does not churn. #115 (persistent $ids) is a separate concern from enforcement and is untouched here.

Rendered spec regenerated; check_spec.py passes; self-suite 147/147.


Added after review of the keyword listing

  • x-sssom renamed to x-oold-sssom (both the schema-level block and the per-entry block inside x-oold-context). The name was OO-LD's own pick - SSSOM specifies slots and a TSV/JSON serialization, not a JSON Schema keyword - so an unprefixed x-sssom claimed a global extension name we do not own and broke the "every OO-LD keyword is x-oold--namespaced" rule. @context is now the single exception, and it is a genuinely forced one (JSON-LD fixes the name). Doing this in an RC rather than after v1.0.
  • @context and x-oold-sssom were missing from the rendered keyword table and from the validator's vocabulary-coverage assertion: both the vocabulary() macro and validate.mjs filtered on the x-oold- prefix, so two keywords that are defined in the meta-schema were invisible and unchecked. Both now included; the all-keywords compliance fixture exercises @context.
  • "OO-LD-proprietary" reworded to "OO-LD-specific": x- is a vendor extension in the JSON Schema / OpenAPI sense - the namespace marks the defining project, not commercial or closed status.

…examples/default

Addresses #117, #118 and #120 from the rc.1 review.

- #117: the inline-type example declared `type` as a strict array but aliased
  it plainly ("type": "@type"), which cannot carry @container, so a single
  @type compacted back as a scalar and failed the spec's own re-validation
  MUST. Verified with jsonld.js: the plain alias returns "schema:Person",
  { "@id": "@type", "@container": "@set" } returns ["schema:Person"].
- #118: the $id MUST is now enforced by the meta-schema instead of going
  unchecked. Split it into a two-tier dialect: oold-meta-schema.json (what
  $schema points at) carries required: ["$id"] and $refs the new
  oold-meta-schema-base.json, which holds the keyword syntax and
  $dynamicAnchor "meta". Nested subschemas recurse into the base via
  $dynamicRef, so fragments in properties/$defs are exempt, as they must be.
  Verified in ajv 8 and Python jsonschema 4.26; the standard 2020-12
  meta-schema uses the same idiom, so no new support is required.
  Compliance fixtures that are document roots gained a $id.
- #120: document that instance generation uses useExamplesValue /
  useDefaultValue, so `examples` and `default` must satisfy their own
  subschema even though JSON Schema treats them as annotations.
…y table

The keyword name was OO-LD's own pick, not something SSSOM mandates (SSSOM
defines slots and a TSV/JSON serialization, not a JSON Schema keyword), so an
unprefixed x-sssom claimed a global extension name we do not own and broke the
"every OO-LD keyword is x-oold-namespaced" rule. Renamed at both levels: the
schema-level block and the per-entry block inside x-oold-context. @context
remains the single exception, since JSON-LD fixes that name.

Also fixes a gap the rename surfaced: the vocabulary() macro and the validator's
coverage check both filtered on the x-oold- prefix, so @context and the former
x-sssom were defined in the meta-schema but absent from the rendered keyword
table and unasserted by the coverage check. Both are now included, and the
all-keywords compliance fixture exercises @context.

"OO-LD-proprietary" reworded to "OO-LD-specific": x- is a vendor extension in
the JSON Schema / OpenAPI sense, marking the defining project, not commercial
or closed status.
- Enforce the existing MUST that a schema closing its objects
  (additionalProperties/unevaluatedProperties false) must PERMIT the @context
  and $schema members an exported instance carries. It is a conditional
  obligation about permitting, not declaring: an open schema permits them
  implicitly, an instance held inside an application may omit both, and an
  embedded object never carries them - so the meta-schema does not require
  every schema to declare them. Probing the compiled schema with each member
  added is also what distinguishes additionalProperties from
  unevaluatedProperties correctly under composition, which a static check
  cannot.
- Fix a boundSchema bug this surfaced: $id/$schema were stripped at every
  node, including inside property maps, where those are instance member names
  rather than schema keywords - so a schema legitimately declaring a $schema
  or $id member lost it from the validation view (and was then falsely
  reported as not permitting it).
- Constrain the shape of a schema's own @context to the four forms JSON-LD
  allows (map, IRI reference, array of either, null). W3C publishes no JSON
  Schema for a context, and the community one on SchemaStore checks only this
  same union; the term definitions inside are verified by the JSON-LD
  processor tier instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant