On this page

Platform schema

The platform schema is the fixed, platform-wide vocabulary of node and relationship types that every project shares. It is defined once, in the platform's own source, when the platform is built. It cannot be created, edited or deleted at runtime — by anyone, through any surface, in any project mode.

It is always named in full. It is never called an ontology, because that word is reserved for the vocabulary a project owns and can change: the project ontology. Two different things share one word in conversation, and this page exists because getting them the wrong way round produces a failure that reads exactly like a bug.

The short version

You are always editing the project ontology. There is no call that edits the platform schema, so you will never be told "you may not edit the platform schema" — no such request exists to refuse.

What actually goes wrong is narrower and easier to miss: you choose a name that the platform already owns. What happens next depends on which call you made, and in one of the three cases it comes back as a success.

What the platform schema contains

Two families of type, both platform-managed and neither of them yours to redefine.

The canonical vocabulary. The node and relationship types the platform models the world with — people, systems, processes, context, time, provenance and the relationships between them. They are organized into layers: the lower layers are base constructs, protected against redefinition, and the upper layer is deliberately left empty for the specializations that arrive with your own data. That empty layer is the room your project ontology is meant to occupy.

The data-estate catalog types. The types the data catalog uses to describe assets that live outside Wexa: DataService, Database, Table, Column, Dashboard, Pipeline, MLModel, GlossaryTerm, Classification and DataOwner. These carry the platform's own semantics: lineage and quality are computed against them, so a project that redefined Table to mean something of its own would break the catalog for that project in a way nothing would report.

The names in that second family are the ones most likely to collide with a name you would pick yourself, and they are the usual cause of everything below.

The three failures, and which call produces which

Declaring a platform catalog type through create-ontology

Declaring a node type whose label is one of the data-estate catalog types, under any category other than the reserved data category, is refused during validation, before anything is written. This check runs in both project modes. The message names the position and the label:

node[0] label "Table" is reserved for the platform data-estate catalog

This one is honest about itself. It is an error, it names the type, and it tells you the reason.

Writing a platform-managed label through save-context

A different set of labels is platform-managed for data writes — Organization, Project, User, Connector, Skill and others the platform maintains for itself. The two sets have no members in common, which is the part worth remembering: the label save-context refuses is not the label create-ontology refuses, so testing one and generalizing from it will mislead you. Saving a node with one of these labels, or a relationship with one of them at either end, is refused with a message that also says what to do instead:

node[0]: "User" is a platform-managed type and cannot be written through save-context —
use create-ontology to change the ontology, or choose a different label for your own data

Note what that message is not saying. It is not saying the platform schema can be changed with create-ontology. It is saying that if what you wanted was a type of your own, declare it in your project ontology under a name that is yours.

The one that looks like success

The two refusals above are the names the platform reserves at the edge, where validation can see them. They are not the whole list. Some names are owned further in, by the service that actually stores the vocabulary, and a declaration that uses one of those clears validation and is simply not stored.

In Simple mode that case is caught, but only after the fact: create-ontology does not stage anything, so it ensures the types and then reads the project ontology back to report what is genuinely there rather than echoing what you sent. If a label you declared did not survive, the call returns HTTP 200 with:

{
  "status": "partially_committed",
  "missing_labels": ["YourLabel"],
  "note": "…"
}

The note it carries says it plainly: these labels are not in the project ontology after the commit, they were declared but not stored, usually because the name is one the platform already owns — so rename them and retry. A name the platform owns is the common cause but not the only one; a label that breaks the PascalCase convention can produce the same result, so check the spelling of the label as well as the word before concluding the name is taken.

There is a fourth status, committed_unverified. That one is not about naming at all: it means the write was accepted but reading the vocabulary back afterwards failed, so the result cannot confirm the labels are there. Treat it as "probably fine, unconfirmed" and check again rather than as a refusal.

Why it is fixed

Three reasons, and they are the reasons a runtime write path was not built rather than reasons it was built and then locked.

It is what "shared" means. The platform schema is the vocabulary every project has in common. A runtime edit in one project either leaks into the others — which breaks isolation — or does not, which means it was never the platform schema in the first place. There is no third option, so the edit does not exist.

Platform behaviour is written against it. Lineage traversal, quality scorecards, classification and the relationship allow-list all read these types by name. They are compiled against the vocabulary, not configured with it, and a type whose meaning could change underneath them would make every one of those features conditionally correct.

A project has somewhere better to put the change. Nothing is lost by the restriction, because the thing a reader usually wants — a type of their own, with their own properties, related to things the platform already models — is exactly what the project ontology is for. The platform schema is the floor, not the ceiling.

What to do instead

If a name you wanted is taken, rename yours. Prefix it with your domain or your organization — AcmeTable, WarehouseTable, ContractTable — and declare it in your project ontology. Relate it to the platform's types rather than replacing them: a relationship from your own type to a Table gives you your meaning and keeps the catalog's.

If what you actually wanted was to describe a real warehouse table, you did not want a type at all — you wanted the data catalog, which already models it and keeps its lineage and ownership current.

And if you are not sure which of the project's four stores you are dealing with, that question has its own page: where your data goes.