An emitted document must satisfy its contract as written. Adding a missing
member or rounding its number before checking would approve a different
document. Use FromJSONSchemaStrict to compile a contract, then validate the
original bytes. This is separate from decoded application validation,
which permits defaults and treats null as absent.
Import arkoren.dev/foundation/validate. Examples use an existing
context.Context named ctx.
Compile a Contract
Require a nonnegative integer count while retaining a default as documentation:
check, err := validate.FromJSONSchemaStrict([]byte(`{
"type": "object",
"required": ["count"],
"properties": {
"count": {"type": "integer", "minimum": 0, "default": 1}
}
}`))
Check the construction error before using check. The published EncodedSchema
owns its compiled state, supports concurrent use, and retains no caller bytes,
application callbacks, or mutable defaults. Editing the schema byte slice
afterward cannot change it. Its zero value is invalid.
Check Exact Bytes
With a successfully compiled check, validate a count beyond binary64’s exact integer range:
err = check.Validate(ctx, []byte(`{"count":9007199254740993}`))
This passes without changing the document. A missing count fails required;
null fails the integer type; zero is supplied and passes the minimum. Defaults
never fill missing values or replace null, and default annotations need not
satisfy their schema. There is no Parse method and this check does not
implement typed Schema[T].
Bounds, integer assertions, multipleOf, and nested enum, const, and
uniqueItems compare exact decimal values. A maximum of 9007199254740992
rejects 9007199254740993; a fractional token cannot round into an integer.
Equivalent spellings such as 1e3 and 1000 compare equally. Numbers such as
1e1000 work within the budgets below, even outside float64 range.
No byte check can recover precision already lost before encoding a Go float. Keep an exact application representation or raw numeric tokens when those digits are part of the contract.
Choose Vocabulary
The strict compiler accepts self-contained draft-07 and 2020-12 documents.
Omitted or empty $schema selects 2020-12. Boolean schemas, type unions and
null, compositions and conditional branches, object/array constraints, and
local references/anchors are supported. Draft-07 $ref ignores assertion
siblings; 2020-12 evaluates them. Mixed embedded dialects fail.
References resolve only inside the supplied document: the compiler never fetches a URL or reads a file. References must select compiled schema locations, not arbitrary annotation values. Recursive schemas that descend through the instance work; unproductive cycles produce a resource failure.
Unknown keywords, unsupported dialects/types, malformed keyword values, and
unresolved references fail compilation with ErrInvalidSchema. x-* extensions
are annotations. Patterns use Go’s RE2 syntax, not the complete ECMA-262 dialect.
Consult the strict vocabulary contract
before importing contracts intended for another validator.
Formats, defaults, and content keywords annotate rather than assert formats or
decoded content. contentSchema is compiled for validity and references but
does not inspect decoded content. No custom check or normalizer executes. Run
typed business validation separately when the application needs it; strict wire
validation does not replace application policy.
Classify Failures
An instance mismatch returns fail-fast validate.Errors with a JSON Pointer
and keyword code, without instance values or schema literals. Do not assume
the typed validator’s full localized messages or exhaustive violation collection.
Other failures remain distinct:
| Failure | Identity |
|---|---|
| Invalid UTF-8/JSON, duplicate names, trailing documents | ErrEncodedJSON |
| Resource refusal | ErrEncodedLimit, never validate.Errors |
| Cancellation or deadline | The context error |
| Invalid compiled definition or zero schema | ErrInvalidSchema |
Using the standard errors package inside a function returning error, classify
a mismatch without swallowing operational failures:
var violations validate.Errors
if errors.As(err, &violations) {
return errors.New("output does not match its contract")
}
return err
Returned pointers can reveal private member names. Redact them before exposing diagnostics to an untrusted client. Do not describe resource or cancellation failures as instructions to correct a field.
Checking output after a mutation cannot undo that mutation. A failed check is not proof of rollback and does not justify automatic replay. The managed MCP adapter uses this strict boundary and separates operational failures from mismatches.
Apply Budgets
Both compilation and validation reject excess rather than round numbers or accept incomplete work:
| Budget | Limit |
|---|---|
| Schema or instance document | 8 MiB each |
| Container nesting | 256 levels |
| Compiled schema nodes | 16,384 |
| Decoding work and evaluation work | 1,000,000 steps each |
| Nested evaluation calls | 512 |
| Numeric coefficient | 4,096 digits |
| Explicit decimal exponent | -4096 through 4096, including for zero |
| Sum of coefficient digits plus absolute exponents | 64 × 1024 × 1024 per decoded document |
| Equality/uniqueness structural-key encoding | 64 MiB cumulatively per validation |
| URI/reference and traversed-pointer lengths | 16 KiB |
| Compiled URI-index keys, including aliases | 32 MiB |
Numeric limits are checked before rational allocation. Structural-key budgets include repeated comparisons and conservatively charged tags/length prefixes. These are data/work limits, not exact heap limits: copies, capacity growth, and runtime metadata also use memory. Keep application request-size and concurrency limits as well.
Cancellation is checked between tokens, visits, comparisons, branches, and
references, not within bounded standard-library operations such as regex or
rational arithmetic. Compilation has no context parameter and performs no
lifecycle I/O. Compilation resource failures also retain ErrEncodedLimit.
For the full vocabulary, error identities, and limits, see the
validate API reference.