Repository navigation
Class constraints: nested JSON Schema for json and array values - #2220
Conversation
A Class's constraints entry can now describe nested values with type (including nullable), const, properties, required, additionalProperties, items and anyOf, up to 16 levels deep, checked identically in Rust and TypeScript with JSON pointer error paths. JSON Schema import keeps nested schemas, nullable types and anyOf below a property instead of refusing them, and export writes them back.
|
Run 5220 (Main (Mancave) / CI) failed on one test: I don't think this PR caused it. The test writes an agent profile through Generated by Claude Code |
|
Complexity review at head 4ecd556 (read the patches of all 12 files, not the fixture contents, the docs patches or the unchanged surrounding code). The design is sound: it extends the existing One thing to settle before merge: old readers. Also worth a line in the PR: TS Simplification (optional):
Generated by Claude Code |
Older nodes reject the nested keywords on write and skip the whole class when they read it. The JSON Schema importers reuse the constraint type list, the one-line keyword wrapper is inlined, and plain() says why only a bare @id link is unwrapped.
|
Thanks. These are addressed in 1774f4a. Old readers. Yes, it's the whole map. An old node can't parse a class's constraints, so
Simplifications. I did 2 and 3: the wrapper is inlined, and the importers reuse the constraint type list ( Generated by Claude Code |
|
Run 5231 on 1774f4a: the units, lint, build and the atomic-saas downstream all passed. E2E went red on all 4 shards with 7 failed and 7 flaky tests out of about 340. I don't think this PR caused it. The failures have no common feature. Most die in I've asked for one re-run when Mancave is quiet. If the same tests fail again, I'll treat them as this PR's and dig in. Generated by Claude Code |
Before: a Class's
constraintsentry could only check one level of a value (minimum,pattern,enum,minItemsand so on). A JSON Schema withproperties,itemsof objects, nullabletype: [X, "null"]oranyOfbelow a property was refused on import, so apps with structuredjsonvalues (Atomic Audio's tracks, for example) had to keep their own validator next to the ontology.After: a constraint can describe nested values with
type(including nullable),const,properties,required,additionalProperties(bool or schema),itemsandanyOf, up to 16 levels deep. Rust and TypeScript check them identically, and an error names the failing spot as a JSON pointer (... breaks required at /tracks/0: missing property "name"). JSON Schema import keeps these schemas instead of refusing them, and export writes them back.This replaces the parallel frozen-schema API from the closed #2045 (frozen app schemas) with the ordinary ontology model from #2151 (content-addressed properties, class constraints, JSON Schema interop), as agreed: schemas stay ordinary ontologies.
How:
lib/src/class_constraints.rsandbrowser/lib/src/class-constraints.tsget a recursiveparse_at/check_atwith a depth limit. Top-level behaviour is unchanged (anenumon an array still checks each item; nestedenumcompares the whole value).classis refused inside a nested schema. Where several classes constrain one property, nested keywords are not merged: the first class wins (documented).lib/src/schema/json_schema.rsandschema-json-schema.tsread nested schemas throughread_nested. Still refused, by pointer:oneOf, nested$ref, nestedformat, tupleitems,patternProperties,not,if,allOf, andanyOfon a class. The form builder'smoveClassConstraintnow moves the raw stored JSON instead of a parsedConstraint, which would have writtenRegExpobjects.Version skew: an older peer that reads a class with the new keywords cannot parse that class's constraints and skips them (existing behaviour for unparseable maps), so it does not enforce them but does not reject the data either.
Related Issues
Follows #2151 (ontology schemas: content-addressed properties, class constraints, JSON Schema). Needed to move Atomic Audio off #2045 (frozen app schemas, closed).
Checklist
lib/tests/fixtures/class-constraints.json, nested round trips injson-schema-interop.json, run by both Rust and TS)docs/src/schema/classes.md,docs/src/schema/json-schema.md)Local:
cargo test -p atomic_lib --features db-redb --lib794 passed (two redb "Database already open" lock flakes pass on rerun),cargo test -p atomic-server --lib387 passed, clippy and fmt clean,browser/lib1637 tests, lint and tsc clean, data-browser typecheck and lint clean.Generated by Claude Code