GA4GH · Metaschema Processor
You author schemas the DRY way — types that inherit from a base. The processor
compiles that source into self-contained JSON Schemas a plain validator can run,
flattening the inheritance so nothing has to resolve a hierarchy at runtime.
The build pipeline
Source
# *-source.yaml — DRY, with a base type Variation: abstract: true properties: [id, type, digest, expressions] Allele: inherits: Variation properties: [location, state]
Like classes with extends — declare inheritance once, don't repeat base members.
Compile
Inlines base members first (order preserved), resolves every $ref, and injects boilerplate like type: object.
Artifacts
The type-system guarantees it enforces
Inlining preserves declaration order: inherited fields lead, the subtype's own fields follow.
stable field orderA subtype may narrow or annotate a field, but can't change an inherited name, type, const or default.
Concrete schemas reject unknown fields — additionalProperties: false, or unevaluatedProperties: false when composed; abstract bases stay open.
An abstract base compiles to its own schema, but nothing is built as one — subtypes reference it directly.
The invariant that makes it safe
Declare inheritance once — and the compiler guarantees every subtype's data still validates against its base type's schema.
Concretely: → *-source.yaml (JSON Schema 2020‑12 + GKS conventions) compiles to standalone per-class JSON Schema + reStructuredText docs. "base type" = an abstract class · "substitutable" = a parent schema always validates a subclass instance (Liskov).