|
1 | | -<!-- gts-spec-version: 0.11 --> |
2 | | -> **VERSION**: GTS specification draft, version 0.11 |
| 1 | +<!-- gts-spec-version: 0.12 --> |
| 2 | +> **VERSION**: GTS specification draft, version 0.12 |
3 | 3 |
|
4 | 4 | # Global Type System (GTS) Specification |
5 | 5 |
|
@@ -112,14 +112,15 @@ See the [Practical Benefits for Service and Platform Vendors](#51-practical-bene |
112 | 112 | | 0.9 | Add `x-gts-final` and `x-gts-abstract` schema modifiers; enforce final/abstract semantics in OP#6 and OP#12 | |
113 | 113 | | 0.10 | BREAKING: terminology unified around GTS Type / GTS Instance; rename API fields `schema_id` → `type_id` (also `old_schema_id`/`new_schema_id`/`to_schema_id`/`selected_schema_id_field`); rename API field `is_schema` → `is_type` (type-definition vs instance discriminator); `type_id` MUST be a GTS Type Identifier or `null` — no longer falls back to JSON Schema dialect URL; rename endpoints `/validate-schema` → `/validate-type`, `/schemas` → `/types`; rename OP#12 'Schema vs Schema Validation' → 'Type Derivation Validation'; rename OpenAPI components `ValidateSchemaRequest` → `ValidateTypeRequest`, `SchemaRegister` → `TypeRegister`; rename example directories `examples/**/schemas/` → `examples/**/types/` (file extensions `.schema.json` retained); add Terminology section | |
114 | 114 | | 0.11 | Introduce term **GTS Type Schema** as the canonical definition of a GTS Type; remove the standalone `Schema` term from Terminology; rewrite `GTS Type` entry to name the abstract registered entity; rename `GTS Type Registry` → `GTS Registry` (registry now scopes both Type Schemas and well-known Instances). **Conformance tests for reference implementations** also updated: rename API endpoints `/validate-type` → `/validate-type-schema` and `/types` → `/type-schemas`; rename OpenAPI components `TypeRegister` → `TypeSchemaRegister`, `ValidateTypeRequest` → `ValidateTypeSchemaRequest`; rename request field `TypeSchemaRegister.schema` → `TypeSchemaRegister.type_schema`; rename helper `validate_type` → `validate_type_schema`. | |
| 115 | +| 0.12 | BREAKING: reframe GTS Type Schemas as a dialect-agnostic JSON Schema extension; the prior `$defs MUST NOT` and post-Draft-07-keyword restrictions are dropped; derivation compatibility and the finality guard use the chained `$id` alone, `allOf`+`$ref` recommended but not required (ADR-0001). `x-gts-traits-schema` becomes a JSON Schema subschema (object/`true`/`false`); the registry chain-aggregates declarations along the `$id` chain via `allOf` (ADR-0002). Trait completeness is keyed on `x-gts-abstract` and enforced on non-abstract types against the materialized effective traits object (ADR-0003). Trait-value merge follows JSON Merge Patch (RFC 7396); cross-descendant locking moves to standard JSON Schema `const` in `x-gts-traits-schema` (ADR-0004). | |
115 | 116 |
|
116 | 117 | ## Terminology |
117 | 118 |
|
118 | 119 | This specification uses the following terms with precise meanings: |
119 | 120 |
|
120 | 121 | - **GTS Type**: a type entity identified by a GTS Type Identifier and defined by a GTS Type Schema. A GTS Type may exist as a standalone document (e.g., a `*.schema.json` file), be exchanged between systems, or be stored in a GTS Registry. |
121 | 122 | - **GTS Type Identifier**: a canonical GTS identifier ending with `~` that identifies a GTS Type. |
122 | | -- **GTS Type Schema**: the canonical definition of a GTS Type. It is an **extension of JSON Schema** that adds GTS-specific keywords (`x-gts-*`) and a set of registry-enforced semantic rules describing the type's instance shape, traits, and derivation. GTS is **dialect-agnostic**: the underlying JSON Schema dialect of any concrete Type Schema is set by its `$schema` (the spec's examples use Draft-07 as the baseline for maximum interoperability, but Draft 2019-09 and 2020-12 are equally supported). GTS does not publish a dedicated `$schema` URI or meta-schema and is therefore not a [JSON Schema Dialect](https://json-schema.org/learn/glossary#dialect) in the formal sense; see §11.0 for details. |
| 123 | +- **GTS Type Schema**: the canonical definition of a GTS Type — a JSON Schema document annotated with the GTS-specific keywords (`x-gts-*`), describing the type's instance shape, traits, and derivation. |
123 | 124 |
|
124 | 125 | Implementations MAY accept alternative source forms (e.g., TypeSpec, YAML) provided they deterministically map to a canonical GTS Type Schema. The canonical form, used for interchange, validation, and registration, is the JSON Schema document. |
125 | 126 | - **GTS Registry**: a registry that stores and resolves GTS entities — Type Schemas and well-known Instances — by GTS Identifier. |
@@ -1262,7 +1263,7 @@ It is recommended to make GTS Type references in JSON Schema `$ref` URI-compatib |
1262 | 1263 | } |
1263 | 1264 | ``` |
1264 | 1265 |
|
1265 | | -Note: local JSON Pointer references (e.g. `"$ref": "#/definitions/Foo"`) are Draft-07 compliant and remain valid. The `gts://` recommendation applies only when `$ref` targets a GTS Type Identifier. Under Draft-07 the canonical container for reusable subschemas is `definitions`; the `$defs` keyword (introduced in 2019-09) MUST NOT be used in GTS Type Schemas. |
| 1266 | +Note: local JSON Pointer references (e.g. `"$ref": "#/definitions/Foo"` under Draft-07, or `"$ref": "#/$defs/Foo"` under Draft 2019-09+) remain valid. The `gts://` recommendation applies only when `$ref` targets a GTS Type Identifier. The canonical container for reusable subschemas follows the dialect declared by `$schema`: `definitions` for Draft-07, `$defs` for Draft 2019-09 and later; both are admissible in GTS Type Schemas. |
1266 | 1267 |
|
1267 | 1268 | Implementation note: When `$ref` is expressed as `gts://...`, implementations should trim the `gts://` prefix and treat the remainder as the canonical GTS identifier for resolution, validation, comparison, and registry keys. The `gts://` prefix exists only to make `$ref` URI-compatible. |
1268 | 1269 |
|
@@ -1378,7 +1379,7 @@ See [`adr/0002-x-gts-traits-schema.md`](adr/0002-x-gts-traits-schema.md) for the |
1378 | 1379 |
|
1379 | 1380 | A type schema declares the trait shape — property names, types, constraints, and `default` values. Any type in the `$id` chain (base or descendant) MAY contribute its own `x-gts-traits-schema`; the registry composes all such declarations along the chain via JSON Schema `allOf` into a single effective trait-schema (see §9.7.5). |
1380 | 1381 |
|
1381 | | -The same derivation compatibility principle that governs host body schemas (§3.1) applies to `x-gts-traits-schema`: every value valid against the descendant's effective trait-schema MUST also be valid against each ancestor's trait-schema. This is enforced naturally by the `allOf` composition — contradictions across the chain (e.g., conflicting types, narrowed constraints that don't overlap, or different `default`s for the same property) produce an unsatisfiable effective trait-schema and fail registration. Typically a base declares the initial trait shape and descendants **narrow** existing trait properties (tighten constraints, `const`, narrower enums). Descendants MAY also **extend** the trait surface by introducing new top-level properties — but only if no ancestor's `x-gts-traits-schema` declares `additionalProperties: false` (or another restriction that would reject the new property); otherwise the new property is treated as "additional" against that ancestor's branch in the `allOf` composition and validation fails, by the same mechanic as §3.1 governs for host bodies. |
| 1382 | +The same derivation compatibility principle that governs host body schemas (§3.1) applies to `x-gts-traits-schema`: every value valid against the descendant's effective trait-schema MUST also be valid against each ancestor's trait-schema. This is enforced naturally by the `allOf` composition — contradictions across the chain (e.g., conflicting types, narrowed constraints that don't overlap) produce an unsatisfiable effective trait-schema and fail registration. Typically a base declares the initial trait shape and descendants **narrow** existing trait properties (tighten constraints, `const`, narrower enums). Descendants MAY also **extend** the trait surface by introducing new top-level properties — but only if no ancestor's `x-gts-traits-schema` declares `additionalProperties: false` (or another restriction that would reject the new property); otherwise the new property is treated as "additional" against that ancestor's branch in the `allOf` composition and validation fails, by the same mechanic as §3.1 governs for host bodies. `default` values are JSON Schema annotations and do not participate in narrowing: descendants MAY freely redeclare a property's `default` in their own `x-gts-traits-schema`. A publisher who wants a trait value to be fixed across descendants SHOULD declare `"const": <value>` (a real narrowing of the validation surface), not rely on a default. |
1382 | 1383 |
|
1383 | 1384 | **Inline definition:** |
1384 | 1385 |
|
@@ -1501,7 +1502,6 @@ Given an inheritance chain `S₀ → S₁ → … → Sₙ`: |
1501 | 1502 | - The registry MUST build an *effective trait schema* by composing all encountered `x-gts-traits-schema` values using JSON Schema `allOf`. |
1502 | 1503 | - Any `$ref` appearing inside `x-gts-traits-schema` MUST be resolved using standard JSON Schema `$ref` resolution rules (base URI resolution + JSON Pointer fragments). |
1503 | 1504 | - Derived schemas MAY further constrain (narrow) traits by adding additional schema constraints in their `x-gts-traits-schema` (this is naturally enforced by `allOf`). |
1504 | | - - **Immutable defaults:** `default` values declared in an ancestor's `x-gts-traits-schema` MUST NOT be changed by a descendant's `x-gts-traits-schema`. If a descendant redeclares a trait property with a different `default`, schema validation MUST fail. |
1505 | 1505 |
|
1506 | 1506 | - **Trait value merge** |
1507 | 1507 | - The registry MUST build an *effective traits object* by walking the type's `$id` chain root → leaf and applying each layer's `x-gts-traits` as a [JSON Merge Patch (RFC 7396)](https://datatracker.ietf.org/doc/html/rfc7396) against the chain-merged object so far. Top-level scalar / array / `null` leaves are overwritten by the descendant (last-wins). Object-valued top-level traits merge **recursively** — fields of an ancestor's object trait that the descendant does not restate are preserved. |
|
0 commit comments