# Validation support contract

This document describes the implementation available in this directory, not the
eventual feature target. The selected dialect is JSON Schema 2020-12.

## Implemented assertions and applicators

| Area | Keywords / behavior |
| --- | --- |
| Schema roots | Boolean or object; malformed roots are rejected |
| Types | `type`, including integer-valued decimal numbers and type unions |
| Equality | `const`, `enum`; nested numbers use mathematical equality |
| Numbers | `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`; no tolerance |
| Strings | `minLength`, `maxLength` count Unicode code points; `pattern` uses the supported regex profile |
| Objects | `properties`, `patternProperties`, `additionalProperties`, `required`, `propertyNames`, `minProperties`, `maxProperties`, `dependentRequired`, `dependentSchemas` |
| Arrays | `prefixItems`, `items`, `contains`, `minContains`, `maxContains`, `minItems`, `maxItems`, `uniqueItems` |
| Composition | `allOf`, `anyOf`, `oneOf`, `not`, `if`, `then`, `else` |
| References | Same-document static `$ref` resolved at compile time into an indexed plan arena |

Type-specific assertions are ignored for other instance types, as the dialect
requires. `minContains`/`maxContains` have no effect without `contains`.
`additionalProperties` considers both named properties and every matching
property pattern. `items` applies only beyond `prefixItems`. `enum` follows
2020-12: any array, including the empty array, which matches nothing.

## References

Local static `$ref` is supported within the compiled document. Supported
shapes: `#` and the empty reference (root), `#/pointer` JSON Pointer
fragments, RFC 6901 escapes (`~0`, `~1`), RFC 3986 percent-encoded fragments
decoded as UTF-8 before pointer unescaping, array segments
(`#/prefixItems/0`, canonical indices only) and empty pointer tokens.
References may be forward, repeated, chained and mutually recursive; 2020-12
sibling semantics apply, so `$ref` is evaluated alongside its adjacent
keywords. Targets may be boolean schemas and schemas located under unknown
extension keywords or annotations, which compile on first reference only.
Compiled plans form an owned indexed arena: recursive schemas compile once,
and every reference jump consumes one evaluation-depth unit, so cyclic
references raise `EvaluationError::DepthLimit` instead of looping or
expanding exponentially.

Dangling pointers, out-of-range array tokens, malformed `~` escapes, malformed
percent escapes, non-UTF-8 fragments and non-schema targets (numbers, strings,
other scalars) are `InvalidKeyword` compile errors. References that name
another resource (absolute/relative URIs, URNs, remote files) and plain-name
anchor fragments (`#name`, which requires `$anchor`) are explicit
`UnsupportedKeyword` errors. Compilation never performs I/O.

## Explicitly not implemented yet

The compiler rejects `$dynamicRef`, `$id`, `$anchor`, `$dynamicAnchor`,
`$vocabulary`, `unevaluatedProperties` and `unevaluatedItems`. Base-URI change
through `$id`, `$anchor`/`$dynamicAnchor` lookup, and remote or networked
reference resolution are therefore unsupported. There is no automatic network
access, remote reference fetching or registry.

`$schema`, when supplied, must identify
`https://json-schema.org/draft/2020-12/schema`. No older-draft compatibility is
implied. In particular, older tuple `items: [...]` syntax is rejected.

## Annotations

`format`, content keywords, titles, descriptions, examples and other annotations
do not assert instance validity. Supported annotation keyword shapes are checked.
`contentSchema` is compiled for schema-shape checking but content is not decoded.
Unknown extension keywords are permitted as annotations. Annotation collection
and arbitrary custom vocabulary execution are not public capabilities yet.

## Precise number contract

Use the library parser to retain number lexemes. A finite binary64 value without
a lexeme uses its shortest decimal rendering, not its expanded binary fraction.
The library
cannot reconstruct an original high-precision decimal discarded by another
parser. `repr`-bearing nodes must contain a valid JSON-number literal consistent
with their binary64 payload. Overflow/underflow of a valid literal is distinct
from an unrepresented nonfinite number.

Exact equality is recursive for arrays and objects and independent of object
member order. Numeric predicates use decimal coefficient arithmetic, not
floating-point epsilon checks or rounded division.

## Pattern profile

Patterns use regexp.mbt's Unicode code-point matching, with explicit ASCII
`\d`/`\w` rewrites, the ECMA whitespace set for `\s`, and a dot excluding
LF, CR, U+2028 and U+2029. Positive shorthand classes inside bracket classes are
expanded as class contents, not nested brackets. Ordinary captures,
backreferences and Unicode property escapes are exercised by local regressions.

A leading, `^`-anchored chain of positive/negative lookaheads is supported, for
example `^(?=\d{3}$)\d+$`. Assertions must not capture or contain nested
lookarounds, and the consuming tail must not have a top-level alternative.
General/inner or unanchored lookahead, lookbehind, inline flags, negated shorthand
inside a class, and shorthand range endpoints are explicitly unsupported.

This is a documented precise-scenario profile, **not a promise to implement
all ECMA-262 regular expressions or its non-Unicode UTF-16 mode**. An unsupported
pattern produces `CompileError::UnsupportedPattern`; applying a publicly
returned `Unsupported` pattern raises `PatternError`, never an ordinary `false`.

## Errors and resource boundaries

- `CompileError` distinguishes malformed keywords, unsupported semantics,
  unsupported patterns, unknown dialect and depth exhaustion.
- Validation mismatches return `false` or diagnostic `Fault` entries.
- Invalid numeric instances and exhausted traversal budgets raise errors.
- Default schema/instance traversal limit is 128. Compile depth also bounds
  annotations and constants, avoiding unbounded copying of deeply nested data.
- Numeric literals currently require decimal exponent and resulting scale within
  ±100,000. Values outside this representation budget are rejected explicitly;
  arbitrary unbounded exponents are not claimed as supported.
- Count keywords beyond the supported signed 32-bit range are rejected as
  unsupported, not interpreted through an overflowing integer conversion.

Regular-expression execution currently depends on `moonbitlang/regexp`; a
compile-once plan is not a promise of bounded-time execution for arbitrary
backtracking patterns. Do not treat untrusted patterns as a hardened sandbox.

## Portability and evidence

The library has no filesystem/network dependency in its runtime package.
Native and JavaScript library test gates and a Wasm compile gate are required
for each milestone. The official conformance and performance executables are
native-only; this does not narrow the runtime library's target support.

The complete pinned official draft2020-12 corpus is downloaded and preserved
in CI rather than generated into `moon test`. Current native release results:

| Corpus | Passed / total | Mismatch | Unsupported | Rejected |
|---|---:|---:|---:|---:|
| Standard | **962/1301** | 0 | 337 | 2 |
| Optional | **535/1036** | 480 | 21 | 0 |
| Proposals | 0/0 | 0 | 0 | 0 |

The two standard rejections are `vocabulary.json` cases selecting a custom
meta-schema dialect. Empty `enum` now compiles and correctly rejects every
instance. Remote references/resource identifiers, dynamic scope, vocabulary
and unevaluated semantics account for unsupported groups. All gaps remain
coverage defects, not passing or skipped cases. Optional format mismatches are reported under the
explicit annotation-only configuration. See the full per-case artifact to
identify a specific limitation rather than assuming every optional mismatch
is caused by `format`.

A correctly rejected invalid instance counts as passing. Known compilation gaps
remain in the denominator. Unexpected parser/validation errors, disagreement
between boolean and diagnostic results, corrupt fixture counts, and missing
artifacts are harness failures and make CI fail. Check/build failures always
make CI fail, regardless of the conformance score. Only an ordinary conformance
runner exit of 1 is accepted as incomplete coverage.

Use [the official runner guide](../benchmarks/README.md) for file/group/case TDD
and [fixture provenance](fixture-provenance.md) for the revision and license.
Passing the full test corpus would be useful evidence, not a formal proof of
all dialect semantics. Unsupported groups are never counted as passing.

Benchmark claims must name the runtime, compiler, corpus, warmup, schema reuse,
error mode and precise numeric/pattern contract. No cross-library speed claim is
made at this milestone.
