Skip to content

SchemaDataValidator accepts any value for Semantic, Quantity, Optional and Handle members, and fractional components in an integer Vector #238

Description

@matt-edmondson

What's wrong

SchemaDataValidator.ValidateValue (Schema/Models/SchemaDataValidator.cs L226-295) handles:

  • primitives
  • vectors
  • colours
  • Enum, Object and Array

Every other type reaches default: break; (L292-293) and is never checked. That means Semantic, Quantity, Optional, Handle and Result values pass unchecked. These are the types samples/modernised.schema.json and CLAUDE.md now recommend ("Name the quantity, not the unit").

The vector cases have a gap of their own. They call ExpectNumericTuple (L460-483), which only checks that each component is a JSON number and ignores Vector.ElementType. So a Vector2<Int> accepts [1.5, 2.7].

Failure scenario (reproduced against 5ee8ed1)

Take a class Body with these members:

  • Id: Semantic(EntityId), where EntityId is over Long
  • Mass: Quantity(Mass)
  • Cell: Vector2 with elementType: Int
  • Maybe: Optional<Int>

This call returns 0 issues:

ValidateData(Body, "{ \"Id\": \"not a number\", \"Mass\": {\"x\":true}, \"Cell\": [1.5, 2.7], \"Maybe\": \"nope\" }", "data")

Suggested fix

  • Semantic: validate the value against the semantic type's representation. Follow the refinement chain to the underlying type, the way Represented in Schema.Validation.cs does. Skip chains that are unresolved or cyclic, because Validate() already reports those.
  • Quantity: get the arity from QuantityRegistry.TryResolve(...).Components.
    • Arity 1: expect a number.
    • Arity N: expect an array of N numbers.
    • Check each value against Storage, so Int and Long storage require integral values.
  • Optional: accept null. Otherwise validate the value against the element type.
  • Vector: validate each component against ElementType. Use ExpectIntegral for Int/Long, and check semantic components through their representation.
  • Handle / Result / Interface / Span: these have no data-file form. Emit an explicit "cannot be checked" warning instead of accepting them silently, as None already does.

Acceptance criteria

  • The payload above yields one error each for Id, Mass, Cell[0], Cell[1] and Maybe.
  • "Maybe": null yields no issues.
  • A correct Mass yields no issues: a number for a scalar quantity, or an array of the right arity for a vector one.
  • Tests in Schema.Test cover each type.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions