Schema Evolution Tool
Build a Scala command-line tool that compares two versions of a JSON Schema (the files that describe what an API's data looks like) and reports which changes will break existing users and which are safe. For example, removing a field, making an optional field required, or narrowing a type breaks clients, while adding an optional field doesn't. Schemas can be read from files or downloaded with the http4s client, their $ref references are resolved, and the report is readable by people or by CI pipelines, which can block a release when something breaks. You'll learn JSON Schema, recursive comparison of tree structures, thinking about compatibility (for readers and for writers), Cats Effect, the http4s client, and property-based testing.
- Estimate
- ~14.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
sbt · Cats Effect · http4s
Project roadmap
- 01
Define the compatibility rules
~2.5hWrite RULES.md: which changes break clients that read the data (such as adding a new required field they don't expect, or widening a type) and which break clients that send data (such as a field becoming required, a type narrowing, an enum losing values, or a maximum decreasing), and which are safe. Decide which subset of JSON Schema you support (type, properties, required, enum, items, minimum, maximum, maxLength and $ref). Done when: RULES.md lists every change with its classification and an example.
- 02
Load and resolve schemas
~2.5hCreate an sbt project with Circe, Cats Effect and the http4s Ember client. Load a schema from a file path or a URL (with a timeout and clear errors), parse it with Circe into your own schema model, and resolve local $ref references (#/$defs/...), detecting cycles. Report unsupported keywords as warnings. Done when: sample schemas with references load into the model.
- 03
Compare schemas
~3hWrite a recursive comparison of the old and new schema models that walks properties and array items together, producing a list of changes, each with a JSON path (such as $.order.items[].price), a kind, the old and new value, and a classification from your rules. Keep the comparison as pure functions. Done when: comparing sample schema pairs finds exactly the expected changes.
- 04
Report the results
~1.5hPrint a report grouped by breaking and safe changes with their paths and explanations, and a summary. Add --format json for machines, a --mode option to check compatibility for readers, writers or both, and exit codes: 0 when no breaking changes, 1 when there are some, and 2 on errors. Done when: the report is clear, and the exit codes are right.
- 05
Compare many versions
~1.5hSupport comparing a folder of versioned schemas (v1.json, v2.json and so on) in order, reporting each step, and checking a new schema against all earlier ones if requested. Load several schemas concurrently with Cats Effect's parTraverse, with a limit. Done when: comparing a folder of versions reports each step's changes.
- 06
Handle edge cases
~1.5hHandle schemas with cycles through $ref, unsupported keywords (reported, not silently ignored), invalid JSON (with line and column), unreachable URLs, and schemas that are identical. Done when: each case gives a clear message and the right exit code.
- 07
Test it
~2hWrite munit tests for every rule in RULES.md with small schema pairs, and property-based tests with ScalaCheck: comparing a schema with itself finds no changes, and adding an optional property is never breaking. Test URL loading with an in-memory http4s server. Done when: sbt test passes.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack