Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ Implementation notes:

### 9.7 - GTS Type Schema Traits (`x-gts-traits-schema` / `x-gts-traits`)

**OP#13 - Schema Traits Validation**: Validate that `x-gts-traits` values in derived schemas conform to the `x-gts-traits-schema` defined in their base schemas. Verify that, for non-abstract types, all required trait properties in the effective trait-schema are resolved (via explicit value in the chain-merged `x-gts-traits` or via `default` in the effective trait-schema), and that the chain-merged trait values satisfy the effective trait-schema's other constraints (including `const`, which a publisher uses to lock individual trait values across descendants — see §9.7.5). Both `x-gts-traits-schema` and `x-gts-traits` are schema-only keywords and MUST NOT appear in instances. `x-gts-traits-schema` MUST be a valid JSON Schema [subschema](https://json-schema.org/learn/glossary#subschema) (object, `true`, or `false`). Uses the same validation endpoints (`/validate-type-schema`, `/validate-entity`).
**OP#13 - Schema Traits Validation**: Validate that `x-gts-traits` values in derived schemas conform to the `x-gts-traits-schema` defined in their base schemas. Verify that, for non-abstract types, all required trait properties in the effective trait-schema are resolved (via explicit value in the chain-merged `x-gts-traits` or via `default` in the effective trait-schema), and that the chain-merged trait values satisfy the effective trait-schema's other constraints (including `const`, which a publisher uses to lock individual trait values across descendants — see §9.7.5). Both `x-gts-traits-schema` and `x-gts-traits` are GTS Type Schema annotation keywords. `x-gts-traits-schema` MUST be a valid JSON Schema [subschema](https://json-schema.org/learn/glossary#subschema) (object, `true`, or `false`). Uses the same validation endpoints (`/validate-type-schema`, `/validate-entity`).

A **schema trait** is a semantic annotation attached to a GTS Type Schema that describes **system behaviour** for processing instances of that type. Traits are not part of the object data model — they do not define instance properties. Instead, they configure cross-cutting concerns such as:

Expand All @@ -1353,7 +1353,7 @@ Two JSON Schema annotation keywords are used together:
| **`x-gts-traits-schema`** | JSON Schema (object \| boolean) | Defines the **shape** of the trait — property names, types, constraints, and `default` values | Base / ancestor schemas |
| **`x-gts-traits`** | Plain JSON object | Provides concrete **values** for the trait properties | Derived (leaf) schemas; may also appear alongside `x-gts-traits-schema` in the same schema |

**Schema-only keywords:** Both `x-gts-traits-schema` and `x-gts-traits` are **schema annotation keywords** and MUST only appear in JSON Schema documents (documents with `$schema`). They MUST NOT appear in instance documents. Implementations MUST reject instances that contain these keywords.
**Schema annotation keywords:** Both `x-gts-traits-schema` and `x-gts-traits` have GTS meaning only in JSON Schema documents (documents with `$schema`). In instance documents, fields with these names are ordinary data and have no GTS trait semantics unless the instance's own JSON Schema assigns constraints to them.

**Keyword placement:** Both `x-gts-traits-schema` and `x-gts-traits` are type-level keywords and MUST appear at the **top level** of the GTS Type Schema document, adjacent to `$id` and `$schema` — NOT nested inside an `allOf` entry or any other subschema. A misplaced occurrence MUST be rejected (fail fast). This governs only the position of the keyword itself, not the contents of `x-gts-traits-schema` (which is an ordinary JSON Schema subschema and may freely use `$ref`, `allOf`, etc.). The same rule applies to the modifiers `x-gts-final` / `x-gts-abstract` (§9.11).

Expand Down Expand Up @@ -1557,7 +1557,7 @@ A **schema modifier** is a boolean annotation on a GTS Type Schema that restrict
| **`x-gts-final`** | `boolean` | Marks the type as **not inheritable** — no derived schemas may reference it as a base | Leaf schemas; enum-like types with a fixed set of well-known instances |
| **`x-gts-abstract`** | `boolean` | Marks the type as **not directly instantiable** — instances must conform to a concrete derived type | Base/ancestor schemas that serve purely as templates |

**Schema-only keywords:** Both `x-gts-final` and `x-gts-abstract` are **schema annotation keywords** and MUST only appear in JSON Schema documents (documents with `$schema`). They MUST NOT appear in instance documents. Implementations MUST reject instances that contain these keywords.
**Schema annotation keywords:** Both `x-gts-final` and `x-gts-abstract` have GTS meaning only in JSON Schema documents (documents with `$schema`). In instance documents, fields with these names are ordinary data and have no GTS modifier semantics unless the instance's own JSON Schema assigns constraints to them.

**Allowed values:** The only meaningful value is `true`. If the keyword is absent or set to `false`, it has no effect (the schema behaves normally — both inheritable and instantiable). Implementations MUST reject non-boolean values.

Expand Down Expand Up @@ -1715,7 +1715,7 @@ Result: ❌ NO MATCH (different major versions)

### 11.0 Relationship to JSON Schema

GTS Type Schemas **extend JSON Schema** with a vendor keyword set (`x-gts-*`) and a set of **registry-enforced semantic rules** (see §3.2 derivation, §9.11 modifiers, OP#12 derivation compatibility, OP#13 trait validation). GTS does **not** impose additional syntactic restrictions on the standard JSON Schema body: any syntactically valid JSON Schema body that carries a valid GTS `$id` is a syntactically valid GTS Type Schema. The constraints GTS does enforce on document structure concern only its own `x-gts-*` keywords — these are type-level annotations that MUST appear at the document top level and are rejected when misplaced, and that MUST NOT appear in instance documents (§9.7.1, §9.11). Implementations MUST treat the GTS keywords described in this specification as layered on top of the underlying JSON Schema dialect's semantics, alongside the standard JSON Schema keywords (`$id`, `$ref`, `allOf`, `const`, …) used here.
GTS Type Schemas **extend JSON Schema** with a vendor keyword set (`x-gts-*`) and a set of **registry-enforced semantic rules** (see §3.2 derivation, §9.11 modifiers, OP#12 derivation compatibility, OP#13 trait validation). GTS does **not** impose additional syntactic restrictions on the standard JSON Schema body: any syntactically valid JSON Schema body that carries a valid GTS `$id` is a syntactically valid GTS Type Schema. The constraints GTS does enforce on document structure concern only its own `x-gts-*` keywords in GTS Type Schemas — these are type-level annotations that MUST appear at the document top level and are rejected when misplaced (§9.7.1, §9.11). Implementations MUST treat the GTS keywords described in this specification as layered on top of the underlying JSON Schema dialect's semantics, alongside the standard JSON Schema keywords (`$id`, `$ref`, `allOf`, `const`, …) used here.

**Dialect-agnostic.** GTS does not pin Type Schemas to a single JSON Schema draft. The dialect of any concrete GTS Type Schema is set by its `$schema` URI, and implementations MUST honour that dialect when validating or interpreting the schema body. The reference examples in this specification declare `$schema: http://json-schema.org/draft-07/schema#` because Draft-07 has the broadest tooling support and is the safest baseline for cross-vendor interoperability; however, Type Schemas that declare a later dialect — Draft 2019-09 (`https://json-schema.org/draft/2019-09/schema`) or Draft 2020-12 (`https://json-schema.org/draft/2020-12/schema`) — are equally valid GTS Type Schemas. Authors who wish to use post-Draft-07 keywords (`$defs`, `prefixItems`, `unevaluatedProperties`, `unevaluatedItems`, `$dynamicRef`/`$dynamicAnchor`, `dependentRequired`, `dependentSchemas`, …) MAY do so, provided the dialect declared in `$schema` admits those keywords and the GTS-specific rules (derivation compatibility per OP#12, trait validation per OP#13, modifiers per §9.11) are satisfied.

Expand Down
60 changes: 60 additions & 0 deletions tests/test_op12_type_derivation_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,66 @@ def test_start(self):
]


class TestCaseTestOp12_NestedClosedDescendantOrphansAncestorProperty(
HttpRunner
):
"""OP#12 - Descendant nested AP:false must not orphan ancestor properties.

Base declares routing.source. The derived overlay keeps the top-level
routing object but closes that nested object while declaring only
routing.target. Under allOf, any routing.source value is rejected by the
derived branch, so the derived schema makes an ancestor property unusable
and must fail type-schema validation.
"""

config = Config(
"OP#12 - nested closed descendant orphans ancestor property"
).base_url(get_gts_base_url())

def test_start(self):
super().test_start()

teststeps = [
_register(
"gts://gts.x.test12.nested.orphan.v1~",
{
"type": "object",
"properties": {
"routing": {
"type": "object",
"properties": {
"source": {"type": "string"},
},
},
},
},
"register base with nested routing.source property",
),
_register_derived(
"gts://gts.x.test12.nested.orphan.v1~x.test12._.child.v1~",
"gts://gts.x.test12.nested.orphan.v1~",
{
"type": "object",
"properties": {
"routing": {
"type": "object",
"additionalProperties": False,
"properties": {
"target": {"type": "string"},
},
},
},
},
"register derived closing routing without restating source",
),
_validate_type_schema(
"gts.x.test12.nested.orphan.v1~x.test12._.child.v1~",
False,
"validate should fail - closed nested branch orphans routing.source",
),
]


class TestCaseTestOp12TypeDerivationValidation_InvalidDerivedSchema(
HttpRunner
):
Expand Down
Loading