Skip to content

compat: strict-mode options are accepted but not enforced #44

Description

@dNerdGuy

Summary

compat accepts Ajv's strict-mode options (strict, strictSchema, strictTypes, strictTuples, strictRequired) and declares them in compat.d.ts, but none of them appear to be enforced. Schemas that Ajv refuses to compile in strict mode compile without error.

This matters because the failure is silent rather than loud: a mistyped keyword does not raise anything, it just stops constraining. { type: 'string', maxLenght: 3 } compiles and the intended length limit is simply absent, so previously invalid data starts validating.

We hit this migrating a JSON Schema 2020-12 workload from Ajv 8.20.0. Runtime behaviour on our existing schemas is identical — we fuzzed 1,364 mutations of a real payload against both validators and found zero divergence, and the performance win is substantial. The only gap we found is authoring-time checking.

Reproduction

import Ata from 'ata-validator/compat';

const cases = {
  'mistyped keyword': { type: 'object', properties: { a: { type: 'string', maxLenght: 3 } } },
  'required property not defined': {
    type: 'object', properties: { a: { type: 'string' } },
    required: ['b'], additionalProperties: false,
  },
  'keyword on the wrong type': { type: 'string', minimum: 3 },
  'dangling $ref': { type: 'object', properties: { a: { $ref: '#/$defs/missing' } } },
};

for (const [name, schema] of Object.entries(cases)) {
  for (const opts of [{ strict: true }, { strict: 'log' }, { strictSchema: true }, { validateSchema: true }]) {
    try { new Ata(opts).compile(schema); console.log(`${name} -> compiled`); }
    catch (e) { console.log(`${name} -> threw: ${e.message}`); }
  }
}

All 16 combinations print compiled. Ajv 8.20.0 with { strict: true } throws on all four:

schema Ajv 8.20.0 ata-validator 1.17.2
maxLenght typo strict mode: unknown keyword: "maxLenght" compiled
required: ['b'] undefined strict mode: required property "b" is not defined at "#" compiled
minimum on a string strict mode: missing type "number" for keyword "minimum" compiled
$ref: '#/$defs/missing' can't resolve reference #/$defs/nope from id # compiled

Mitigating detail

A dangling $ref fails closed at validation time — the compiled function returns false for every input rather than passing everything. That is the safe direction, and worth preserving whatever else changes. The mistyped-keyword case is the one that fails open.

Environment

  • ata-validator 1.17.2, compat entry point
  • Node v26.8.2, Linux
  • Dialect: JSON Schema 2020-12

What would help

Any of these would resolve it for us, in rough order of preference:

  1. Implement the strict-mode checks behind the existing options.
  2. Have the constructor throw on strict options that are not yet enforced, so the gap is visible at startup rather than absent at runtime.
  3. Document in compat.d.ts and the README that these options are accepted for API compatibility and currently ignored.

Happy to help test a fix. Thanks for the library — the memory and throughput numbers against our real schema were a clear improvement over Ajv.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions