3.4 KiB
Gemini Project Overview: jspg
This document outlines the purpose of the jspg project and the specific modifications made to the vendored boon JSON schema validator crate.
What is jspg?
jspg is a PostgreSQL extension written in Rust using the pgrx framework. Its primary function is to provide fast, in-database JSON schema validation against the 2020-12 draft of the JSON Schema specification.
It works by:
- Exposing a SQL function,
cache_json_schemas(...), which takes arrays of schema objects, compiles them, and caches them in memory. - Exposing a SQL validation function,
validate_json_schema(schema_id, instance), which validates a JSONB instance against one of the pre-cached schemas. - Using a locally modified (vendored) version of the
booncrate to perform the validation, allowing for custom enhancements to its core logic.
boon Crate Modifications
The version of boon located in the validator/ directory has been modified to address specific requirements of the jspg project. The key deviations from the upstream boon crate are as follows:
1. Correct Unevaluated Property Propagation in $ref
-
Problem: In the original
boonimplementation, if a schema validation failed inside a$ref, the set of properties that had been evaluated by that referenced schema was not correctly propagated back up to the parent validator. This caused the parent to incorrectly flag already-evaluated properties as "unevaluated," leading to spuriousunevaluatedPropertieserrors. -
Solution: The
Uneval::mergefunction invalidator/src/validator.rswas modified. The original logic, which performed an intersection of unevaluated properties (retain), was replaced with a direct assignment. Now, the parent validator's set of unevaluated properties is completely replaced by the final set from the child validator. This ensures that the most current state of evaluated properties is always passed up the chain, regardless of validation success or failure within the$ref.
2. Runtime Strictness Control
-
Problem: The
jspgproject requires that certain schemas (e.g., those for publicpuncs) enforce a strict "no extra properties" policy, while others do not. This strictness needs to cascade through the entire validation hierarchy, including all$refchains. A compile-time flag was unsuitable because it would incorrectly apply strictness to shared, reusable schemas. -
Solution: A runtime validation option was implemented.
- A
ValidationOptions { be_strict: bool }struct was added and is passed to the corevalidatefunction invalidator.rs. - The
jspgcode determines whether a validation run should be strict (based on thepunc'spublicflag or if we are validating a a globaltype) and passes the appropriate option. - The
Validatorstruct carries these options through the entire recursive validation process. - The
uneval_validatefunction was modified to only enforce this strict check ifoptions.be_strictistrueand it is at the root of the validation scope (self.scope.parent.is_none()). This ensures the check only happens at the very end of a top-level validation, after all$refs and sub-schemas have been processed. - When this runtime strictness check fails, it now generates a more descriptive
ADDITIONAL_PROPERTIES_NOT_ALLOWEDerror, rather than a genericFALSE_SCHEMAerror.
- A