Skip to content

Ships the datamodel document's JSON Schema - #36

Merged
johnnyt merged 1 commit into
mainfrom
sd-630-datamodel-schema-file
Sep 26, 2026
Merged

johnnyt merged 1 commit into
mainfrom
sd-630-datamodel-schema-file

Conversation

@johnnyt

@johnnyt johnnyt commented Sep 26, 2026

Copy link
Copy Markdown
Member

Ships the datamodel document's JSON Schema, as ADR-0002 (merged at proposed) decides it. Refs sd-630.

What changes

  • priv/schemas/datamodel-document.schema.json: a hand-written draft-07 schema of the version-1 document. version is const: 1; scopes is a tuple of exactly three scope objects fixed by const to global, local, event; an entry requires name, path, type, label as strings, with fields (recursive), item_type, example (any value), note, one_of and a boolean sensitive?; a declaration requires name, kind (record or shape), label and fields; a field requires name and type, with a boolean required?. The nine closed spellings are listed under definitions.closed_type; type and item_type are plain strings (decision 6). No object sets additionalProperties: false (decision 7). $id is keyed on document version 1 (decision 8).
  • StatifierDatamodel.Schema: path/0 (the file in the installed application's priv) and json/0 (the text, embedded at compile time with @external_resource; not a decoded map). Nothing in lib/ calls either (decision 4).
  • mix.exs: priv/schemas joins the Hex files: list (decision 1); {:ex_json_schema, "~> 0.11", only: :test, runtime: false} (decision 10: test-only; mix hex.build lists no requirements). mix.lock gains ex_json_schema and decimal.
  • changelog.d/sd-630.md (Added).

Tests (test/statifier_datamodel/schema_test.exs)

  • Every document under test/fixtures/documents/ validates and indexes to a non-nil index. The two fixtures: ADR-0001's ## Worked shape JSON extracted verbatim, and a copy of the reference host's card-processing document (riddler/statifier_examples priv/fixtures/card-processing.datamodel.json at fed826ca9d0fed20e1c6152a528a0f2885d3d2fd), with one edit named below.
  • The near-misses, one each: scopes missing; two scopes; scopes out of order; an entry missing path; a string sensitive?; a declaration kind neither record nor shape; a declaration missing fields; a string required?; version 2. Each is rejected at the error path it breaks.
  • The advisory test: every near-miss that is a map with a list under scopes (all but "scopes missing") still indexes, and what it indexes to is pinned (the declared paths, the entries, the sensitive set, the declarations, the version, as the case needs). "scopes missing" is pinned to nil.
  • Drift: each spelling under definitions.closed_type indexes to a non-nil type through Index.type/2 (one entry per spelling, queried by its path), the listed set equals the nine, and float indexes to nil. An entry whose type names a declaration validates and indexes to {:declared, "cards.credit_txn"}.
  • The package file list includes priv/schemas/datamodel-document.schema.json (the files: entries expanded as Hex expands them); a real mix hex.build --unpack of this branch was also read and carries the file.
  • Every test carries a one-line sabotage note; each mutation was run and turned its test red, and the suite was green after each restore.

Provenance

  • Differences between the bead and the record, the record governing: the reference host's card-processing document omits description on all three scopes, which ADR-0001 decision 3 has a scope carry and ADR-0002 decision 5 requires, so the verbatim copy does not validate. The fixture adds a description to each scope and changes nothing else; a test deletes the three again and pins that the result fails at exactly #/scopes/0, #/scopes/1, #/scopes/2 and indexes identically to the fixture. The source document is not edited here.
  • Where decision 5 names keys without a type (a scope's label and description, a declaration's name and label), the schema requires the key and adds no type.
  • mix.exs groups_for_modules: Schema joins the "Document and index" group so the new module is not left ungrouped in the docs sidebar (a threading edit).
  • runtime: false on the test-only validator, beside the record's only: :test.
  • README.md is unchanged: the record does not require a README section; the module's two doctests run in the suite.

Pre-request review

Read the diff against ADR-0002 decisions 1-10, its typespecs and its worked example, and against the bead's acceptance. Checked: every key and requirement decision 5 lists is in the file and nothing is required that it does not list; the tuple, minItems/maxItems and the three const positions match the record's outline; closed_type holds exactly the nine spellings in index.ex's @types; no additionalProperties anywhere; json/0 returns the text; grep -rni schema lib outside schema.ex finds nothing, so no function's answer changes; the worked-example rows of ADR-0002 (event scope dropped, a string sensitive?, kind shap, version 2, a declared-name type) each hold as the record states them. The moduledoc claims (advisory, stricter than index/1, $id keyed on document version) each match a decision above.

Gate

Full mix quality on the committed tree, quoted whole:

Running quality checks...

✓ Format: No changes needed (243ms)
✓ Compile: dev + test compiled (warnings as errors) (330ms)

Running analysis stages in parallel...

○ Doctor: skipped (:doctor not installed)
○ Gettext: skipped (:gettext not installed)
○ Sobelow: skipped (:sobelow not installed)
✓ Doc links: 1 link checked (14ms)
✓ Dependencies: No unused dependencies (431ms)
✓ Credo: No issues (873ms)
✓ Docs: No warnings (896ms)
✓ Tests: 137 of 137 passed, 99.1% coverage (911ms)
✓ Dialyzer: No warnings (1.4s)

✓ All quality checks passed!

The commit is a bare git commit of a staged tree byte-identical to the tree this run passed on.

Adds priv/schemas/datamodel-document.schema.json, a hand-written
draft-07 schema of the version-1 document per ADR-0002, to the Hex
package, and StatifierDatamodel.Schema with path/0 and json/0 (the
text embedded at compile time). Nothing in lib/ calls it: index/1
stays the admission step and answers as before.

Tests validate with ex_json_schema, test-only: two fixture documents
(ADR-0001's worked shape, and a copy of the reference host's
card-processing document with the scope descriptions it omits), the
near-misses the schema rejects, each still indexing as before where it
is a document at all, the nine closed spellings pinned to the index,
and the built file list.

Refs: sd-630
@johnnyt
johnnyt merged commit c61a52a into main Sep 26, 2026
1 check passed
@johnnyt
johnnyt deleted the sd-630-datamodel-schema-file branch September 26, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant