Skip to content

Enforce a valid $schema dialect during structural schema validation #93

Description

@aviator5

Summary

GTS Type Schema structural validation (GtsStore::validate_schema, gts/src/store.rs) does not verify that a registered type schema declares a valid $schema (JSON Schema dialect) keyword. A schema with a missing or non-string $schema is currently accepted, and downstream validation silently falls back to the validator's automatic draft detection (Draft 2020-12 when $schema is absent).

This was surfaced by a CodeRabbit review on #92 for the trait-validation path specifically, but it is a general structural-validation gap, not limited to traits.

Current behavior

  • validate_schema (gts/src/store.rs:649) validates $ref / x-gts-ref and compiles against the JSON Schema meta-schema (skipping compilation when the document contains gts:// refs), but it never asserts that $schema is present and is a recognized dialect URI.
  • As a consequence, validate_schema_traits (gts/src/store.rs:834) reads the leaf's $schema to pin the dialect for trait-value validation and falls back to None (default draft) when it is missing/non-string (gts/src/store.rs:~898-916). So an invalid leaf schema is not rejected, and its trait values may be validated under a different draft than intended.

Why it matters

  • JSON Schema semantics differ across drafts (e.g. exclusiveMinimum, $ref sibling keywords, additionalProperties vs unevaluatedProperties). Validating a schema body or its trait values under an unintended draft can both accept invalid input and reject valid input.
  • The spec expects type schemas to declare their dialect via $schema; the registry should enforce that rather than guess.

Proposed direction

Enforce $schema once, at the structural layer, so the guarantee is uniform for every registered type schema (bodies, traits, modifiers) instead of being special-cased in the OP#13 trait path:

  • In validate_schema (structural), require $schema to be present and a string — and ideally one of the supported dialect URIs — rejecting otherwise with a clear error.
  • Once that holds, validate_schema_traits can assume a present $schema and drop its silent None fallback.

Out of scope / notes

  • Some unit-test fixtures in gts/src/schema_traits.rs omit $schema and rely on the current fallback; they would need to declare an explicit $schema (or use a documented test-only path) once enforcement lands.
  • This is intentionally broader than the trait path: the goal is a single place that guarantees every registered type schema has a valid dialect.

Originating review: #92 (CodeRabbit, gts/src/store.rs trait-dialect fallback).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions