The Week a Schema Change Stopped Being a Project
Add one property. That is the entire request: sales needs `preferredChannel` on the customer record, three allowed values, by Friday.
The Week a Schema Change Stopped Being a Project
Add one property. That is the entire request: sales needs preferredChannel on the customer record, three allowed values, by Friday.
In most organizations that is not a one-line change, it is a coordination exercise. The JSON Schema in the API repository gets the property. Someone else has to remember the warehouse table, write the migration, and pick a type. Someone has to update the Avro record before the consumers redeploy, and someone has to tell the partner whose data contract references the same object. Eventually somebody notices that the three allowed values were written as an enum in one place, a CHECK constraint in another, and a comment in a third. The property ships the following week, and two of the five artifacts differ subtly from the other three.
Here is what that request looks like once JSON Schema stops being five files and becomes one governed model.
Day one: the schema comes in whole
You post your existing JSON Schema to the import endpoint — graph/transform/schema/import/{projectId}, format jsonschema — and read the response. It carries three things: whether it ran, a lossiness list, and the project it wrote into.
What lands in the project is not a blob of text. The root object is a Type. Every property is an Element with its own identity. required entries become required flags. Each enum becomes a Taxonomy whose terms are things you can point at, name, and reuse. Every $ref becomes a real reference between types, $defs entries become named types, an allOf over a $ref becomes inheritance, and arrays keep their minItems and maxItems as cardinality. Everything else you wrote — the $schema dialect line, description prose, format hints, your own x- extensions — is preserved verbatim, ready to be re-emitted exactly.
The lossiness list is usually empty. If your schema uses conditional combinators (anyOf, oneOf, if/then/else, not), you get one entry per occurrence naming the path and explaining that conditional logic cannot be modeled as structure — while the raw JSON stays preserved for exact re-emission. That list is the only thing you need to read before you trust the result.
Day two: the change happens once
preferredChannel gets added to the model, with a Taxonomy holding its three terms. That is the change: not five edits in five repositories, but one, where the meaning lives, reviewed by the people who own it.
If the field corresponds to a concept your organization has already agreed on, it carries an x-maps-to annotation naming the standard and the term URI. That annotation is not decoration — it travels through every export, so the same field stays recognizable as the same concept in a DDL comment, in a LinkML model, in an ontology export.
Day three: the artifacts are regenerated, not rewritten
One export endpoint — graph/transform/schema/export/{projectId} — and a format key:
jsonschemafor the API repository and anything that validates payloadssqlfor the warehouse, withvendorset topostgres,mysql, orsqlserveravrofor the streaming platformprotobuffor the service that speaks proto3odcsfor a partner-facing Bitol data contractlinkml,owl,shex,jsonldfor the modeling and semantic-web sideosiorosi-jsonfor an Apache Ossie semantic modelsynapsewhen you need the Sage Bionetworks draft-07 profile with a registered-schema$id
Every one of those responses carries its own lossiness list, and the lists differ because the formats differ. Postgres has no inline enum, so the allowed-value constraint on a taxonomy-typed column is reported as relaxed rather than quietly dropped. proto3 has no date-time scalar, so a timestamp degrades to string and says so. These are not failures; they are the review checklist you never used to get. success: true means the call ran — the lossiness list tells you what changed on the way out.
The shift is not speed. It is that the artifacts are now derived: nobody hand-edits the DDL, so nobody can hand-edit it wrong.
Day four: the partner's schema is different, and that is fine
The partner sends their own JSON Schema, and their field names do not match yours. This used to be a spreadsheet and a week of email.
The mapping endpoint — graph/transform/schema/map/{projectId} — takes your schema, theirs as a target hint, and a strategy: inferred (label and type matching), explicit (an authored guide with field mappings, taxonomy directives, and explicit drops), or ai (a proposal from a server-side model, put through exactly the same validation gate as everything else). Nothing is written to the project; every call is inherently a dry run.
What comes back is the transformed schema, the aggregated lossiness, and the plan — the executed mapping as a reviewable artifact. You store the plan. Next month, when the partner sends a new file, you replay it through graph/transform/plan/execute/{projectId}: the same plan against the same source produces the same output, which our tests assert. The mapping goes from tribal knowledge to a versioned object with a diff.
When it is the records that need to move rather than the schema, the data mapping endpoint runs the same gated plan over real values, reading and writing json, csv, jsonld, sql, or avro.
Day five: verification instead of hope
The last missing piece used to be the check: an engineer produces a sample payload and asserts that it looks right.
With the model in place, the validate_json tool regenerates the project's JSON Schema and validates a document against it — the same schema the exports come from, not a copy someone saved to a laptop last quarter. Over the MCP endpoint, an assistant can run that check mid-conversation.
What the team can do now that it could not before
- Answer "where else does this field exist?" without grep, because Elements and Taxonomies have identity and
x-maps-tocarries meaning across formats. - Ship a schema change in one review instead of five, with every derived artifact regenerated from the approved model.
- Read the price of each translation. Every export names what the target format could not hold exactly, by path, in plain language.
- Replay a mapping. The plan is stored, reviewable, and deterministic.
- Stop maintaining files a machine should be writing. The DDL, the Avro record, and the contract become build outputs.
None of this asks you to leave JSON Schema behind. Your services still validate against JSON Schema; your repositories still hold a JSON Schema file. What changes is where that file comes from — and the fact that when somebody asks for one more property, you can say yes and mean it.
For the request bodies behind each of these calls, see the schema transformation quickstart in the CoreModels docs.