Skip to content

format: tighten type and context validation constraints - #279

Open
gnidan wants to merge 1 commit into
mainfrom
architect-schema-constraints
Open

format: tighten type and context validation constraints#279
gnidan wants to merge 1 commit into
mainfrom
architect-schema-constraints

Conversation

@gnidan

@gnidan gnidan commented Jul 26, 2026

Copy link
Copy Markdown
Member

This PR closes six validation gaps found in the schema sweep. Each is a case where an invalid instance validated, or a legitimate one could not be expressed. All existing schema examples still validate, and I verified each fix against its offending instance.

  • type/elementary — forbid contains. The canonical elementary schemas never forbade a contains field, so { kind: bool, contains: { type: { id: 1 } } } validated as an elementary type — while the very same object is a complex type under type/base. That breaks the elementary-vs-complex discriminator the format relies on. Elementary types now reject contains, matching type/base.
  • type/complex/function — require kind and contains. function was the only one of the six complex-type schemas without a top-level required: [kind, contains], so { external: true } alone validated as a function and { kind: function, internal: true } (no contains) validated through the whole canonical type chain. Now required.
  • type/complex/function — allow parameters / contract by reference. The Parameters wrapper (and the external contract wrapper) pinned type to a concrete type, so neither could be given as an { id } reference — even though returns in the same file already permits one and the wrapper/specifier machinery exists precisely to allow it. Both now accept a type reference.
  • type/elementary/contract — type the flags. library and interface were constrained only inside the oneOf consts, so a nonsense value on the non-discriminating flag slipped through: { kind: contract, library: true, interface: 42 } validated. Both are now type: boolean at the top level.
  • program/context/name — non-empty name. name is meant to identify a context, but it was a bare type: string, so name: "" validated. It now carries minLength: 1, matching the identifier-like strings elsewhere in the context family.
  • pointer/region — require location. The location dispatcher's seven if clauses omitted required: [location], so an object with no location vacuously satisfied all seven and was rejected only by accident — with validator errors implicating every region type at once. location is now required at the top level (the change that actually rejects a location-less region), and each if guards on it so a missing location produces one clear error instead of seven.

Schema example and validity tests pass.

Six constraint fixes from the schema sweep, each closing a case where an
invalid instance validated (or a valid one could not be expressed):

- type/elementary: the canonical elementary schemas never forbade a
  `contains` field, so e.g. {kind: bool, contains: ...} validated as an
  elementary type while the same object was a *complex* type under
  type/base — breaking the elementary-vs-complex discriminator. Elementary
  types now reject `contains`, matching type/base.
- type/complex/function: alone among the complex types it had no top-level
  `required: [kind, contains]`, so {external: true} validated as a
  function. Now required.
- type/complex/function: `parameters` (and the external `contract`) were
  pinned to a concrete type, so they could not be given as an { id }
  reference even though `returns` and the wrapper machinery allow it. Both
  now accept a type reference.
- type/elementary/contract: `library` and `interface` were only
  constrained inside the oneOf consts, so {library: true, interface: 42}
  passed. Both are now typed `boolean` at the top level.
- program/context/name: `name` was a bare string, so `name: ""`
  validated; it now carries minLength: 1, matching the identifier-like
  strings elsewhere in the context family.
- pointer/region: the location dispatcher's `if` clauses omitted
  `required: [location]`, so a location-less object vacuously satisfied
  all seven branches and was rejected only by accident (with errors
  implicating every region type). `location` is now required at the top
  level, and each `if` guards on it, so a missing location yields one
  clear error.
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://ethdebug.github.io/format/pr-preview/pr-279/

Built to branch gh-pages at 2026-07-26 03:00 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

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