Skip to content

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

@aviator5

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions