Skip to content

feat(spec): x-gts-closed-derivations schema modifier (0.14 draft) - #91

Open
AndrejK666 wants to merge 1 commit into
GlobalTypeSystem:mainfrom
AndrejK666:feat/x-gts-closed-derivations
Open

feat(spec): x-gts-closed-derivations schema modifier (0.14 draft)#91
AndrejK666 wants to merge 1 commit into
GlobalTypeSystem:mainfrom
AndrejK666:feat/x-gts-closed-derivations

Conversation

@AndrejK666

@AndrejK666 AndrejK666 commented Aug 3, 2026

Copy link
Copy Markdown

Summary

Adds a third schema modifier, x-gts-closed-derivations. Declared on a base type (typically an open, abstract envelope), it requires every schema deriving from that base to resolve to a closed content model at its own top level (§4.4: effective additionalProperties: false after $ref/allOf resolution). Enforced at registration (when validation is enabled) and in OP#12 — regardless of how the schema is registered: API, config seeding, or macro-generated.

Motivation

The extensible-envelope pattern (per-tenant metadata, plugin payloads) needs the base open so derived schemas can declare their own payload properties (§3.1). But openness is inherited: if a derived schema is also open, a mistyped property (automation_levl next to a declared automation_level) validates successfully and is silently ignored — defeating server-side validation. §4.4.1 already recommends "closed envelope with designated open containers"; this modifier covers the complementary layout where the base itself is the open derivation anchor, and makes "derived must close its level" a registry-enforced invariant instead of a convention.

Agreed with the account-management/types-registry maintainers as the resolution of the open-envelope discussion (context: derived tenant-metadata schemas could not be registered at all; opening the base was acceptable only if derived schemas are guaranteed closed).

Changes
§9.11 title + intro: three modifiers instead of two.
§9.11.1: keyword table row, combination table (final+closed-derivations → INVALID; abstract+closed-derivations → the expected envelope pairing), mutual-exclusion paragraph.
New §9.11.4 "x-gts-closed-derivations semantics": derivation guard, typical use, why grandchildren need no extra checks (§3.1 blocks additions under a closed parent; re-opening fails §4.1 derivation compatibility — so implementations check only schemas whose immediate base declares the modifier), no propagation, evolution note (base payload stays property-free; a base payload field is a MAJOR bump), top-level placement.
§9.11.4/§9.11.5 renumbered to §9.11.5/§9.11.6; the one cross-reference updated.
§4.4.1: cross-reference from the recommended-pattern discussion.
Version: 0.14 (draft) row + header bump.
Notes for reviewers
The check is deliberately scoped to direct derivations — deeper levels are covered by existing rules (see §9.11.4 item 3), keeping OP#12 cost O(chain).
Conformance tests for OP#12: happy to add to tests/ in this PR or as a follow-up once the wording settles — maintainers' preference?
Reference implementation PR (gts-rust): GlobalTypeSystem/gts-rust#111

Summary by CodeRabbit

  • Documentation
    • Updated the specification from version 0.13 to draft 0.14.
    • Documented the new x-gts-closed-derivations modifier and its effects on schemas, inheritance, validation, registration, and related behaviors.
    • Updated references to the renumbered registration-enforcement section.

An (open) base type may require every derived schema to resolve to a
closed content model at its own top level, enforced at registration
and in OP#12. Motivated by extensible metadata envelopes: the base
stays open and abstract as a derivation anchor, while every derived
schema must reject undeclared properties - so a mistyped property
fails instance validation instead of being silently accepted.

Adds S9.11.4 semantics, keyword/combination tables, S4.4.1
cross-reference; renumbers S9.11.4/5 -> S9.11.5/6.

Signed-off-by: Andrej Kuchma <Andrej.Kuchma@constructor.tech>
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The README updates the GTS specification to draft 0.14. It defines x-gts-closed-derivations, its validation and registration rules, modifier interactions, inheritance behavior, and related section references.

Changes

Closed derivations specification

Layer / File(s) Summary
Draft 0.14 release documentation
README.md
The specification version changes to draft 0.14. The release notes and content-model guidance describe x-gts-closed-derivations.
Closed derivations modifier semantics
README.md
The documentation defines the modifier’s boolean semantics, restrictions, inheritance and instantiation behavior, evolution rules, OP#12 validation, registration enforcement, and trait interactions. Section cross-references are renumbered.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related PRs

  • GlobalTypeSystem/gts-spec#90: Extends schema evolution and resolved content-model compatibility rules related to x-gts-closed-derivations.

Suggested reviewers: artifizer, aviator5

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the new schema modifier and the specification version update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 118: Reorder the release history in README.md so the “0.14 (draft)” entry
appears below “0.13”, preserving the existing entry text and chronological
ordering.
- Line 1759: Update the Evolution note in §4.4 to make the major-version
recommendation conditional: adding a base payload property requires a new MAJOR
version only when it makes the effective accepted-instance set incompatible,
while preserving that optional properties in open models are not necessarily
breaking.
- Around line 1672-1686: Replace broad “every derived schema” wording with
“every directly derived schema” or equivalent immediate-base wording in
README.md lines 1672-1686, including the overview, table, and content-model
guidance; make the same wording correction at README.md line 703. Clarify that
x-gts-closed-derivations applies only when the modified schema is the immediate
base, not to transitive descendants.
- Line 1771: Update the “9.11.6 Registration enforcement” documentation to scope
x-gts-closed-derivations enforcement to schema registration and OP#12 endpoints
(/validate-type-schema and /validate-entity type validation), removing
/validate-instance. Keep each modifier’s enforcement endpoint listed separately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 133a7de7-2eda-4ad7-8e4f-3194f978eb7c

📥 Commits

Reviewing files that changed from the base of the PR and between cada310 and fb7928c.

📒 Files selected for processing (1)
  • README.md

Comment thread README.md
| 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 |
| 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`. |
| 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). The four document-level keywords (`x-gts-final`, `x-gts-abstract`, `x-gts-traits-schema`, `x-gts-traits`) MUST appear at the schema top level and are rejected (fail fast) when nested in a subschema (§9.7.1, §9.11). |
| 0.14 (draft) | Add `x-gts-closed-derivations` schema modifier: an (open) base type may require every derived schema to resolve to a closed content model at its own top level, enforced at registration and in OP#12 (§9.11.4). Motivated by extensible metadata envelopes: open abstract base + mandatory-closed derived schemas keeps payload extension possible while undeclared properties are still rejected at instance validation. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the release history chronological.

Move 0.14 (draft) below 0.13. The current order makes the version history ambiguous.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 118, Reorder the release history in README.md so the “0.14
(draft)” entry appears below “0.13”, preserving the existing entry text and
chronological ordering.

Comment thread README.md
Comment on lines +1672 to +1686
| **`x-gts-closed-derivations`** | `boolean` | Requires every **derived** schema to resolve to a **closed content model** (§4.4) at its own top level | Open abstract envelope bases (extensible metadata / plugin payloads) |

**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.
**Schema annotation keywords:** All three modifiers 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.

**Mutual exclusion:** A schema MUST NOT declare both `"x-gts-final": true` and `"x-gts-abstract": true`. This combination is semantically meaningless (a type that can be neither inherited from nor instantiated serves no purpose) and MUST be rejected during schema registration or validation.
**Mutual exclusion:** A schema MUST NOT declare both `"x-gts-final": true` and `"x-gts-abstract": true`. This combination is semantically meaningless (a type that can be neither inherited from nor instantiated serves no purpose) and MUST be rejected during schema registration or validation. Likewise, a schema MUST NOT declare both `"x-gts-final": true` and `"x-gts-closed-derivations": true` — a final type has no derivations to constrain. `x-gts-abstract` + `x-gts-closed-derivations` is the expected pairing for extensible envelope bases.

| Modifier combination | Inheritance allowed? | Direct instances allowed? |
|---|---|---|
| *(default / neither)* | Yes | Yes |
| *(default / none)* | Yes | Yes |
| `x-gts-abstract: true` | Yes | No |
| `x-gts-final: true` | No | Yes |
| Both `true` | **INVALID** — MUST be rejected | — |
| `x-gts-closed-derivations: true` | Yes — derived schemas must be closed | Yes |
| `x-gts-abstract` + `x-gts-closed-derivations` | Yes — derived schemas must be closed | No |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use direct-derivation wording consistently.

The normative rule applies only when the modified type is the immediate base. The overview, table, and content-model guidance say “every derived schema”. Implementers may enforce the rule on grandchildren and reject valid schemas.

  • README.md#L1672-L1686: replace broad wording with “immediately derived schemas” or “schemas whose immediate base declares the modifier”.
  • README.md#L703-L703: replace “every derived schema” with “every directly derived schema”.
📍 Affects 1 file
  • README.md#L1672-L1686 (this comment)
  • README.md#L703-L703
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 1672 - 1686, Replace broad “every derived schema”
wording with “every directly derived schema” or equivalent immediate-base
wording in README.md lines 1672-1686, including the overview, table, and
content-model guidance; make the same wording correction at README.md line 703.
Clarify that x-gts-closed-derivations applies only when the modified schema is
the immediate base, not to transitive descendants.

Comment thread README.md

5. **No propagation**: Like `x-gts-final`, the modifier applies only to the schema that declares it; a closed derived schema does not implicitly carry it further.

6. **Evolution note**: A base declaring this modifier SHOULD keep its own payload level property-free (an *envelope*). In an open content model, adding a base payload property later is not a compatible change (§4.5) — it is a new MAJOR version.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Qualify the compatibility and versioning guidance.

Section §4.4 says that adding an optional property to an open model is not necessarily backward incompatible. A new major version is required only when the effective accepted-instance set becomes incompatible. Replace the absolute wording with conditional guidance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 1759, Update the Evolution note in §4.4 to make the
major-version recommendation conditional: adding a base payload property
requires a new MAJOR version only when it makes the effective accepted-instance
set incompatible, while preserving that optional properties in open models are
not necessarily breaking.

Comment thread README.md
- **Abstract types may declare `x-gts-traits-schema`**: Doing so contributes to the effective trait-schema of descendants; the abstract type itself is not required to provide values.

#### 9.11.5 Registration enforcement
#### 9.11.6 Registration enforcement

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -C 4 'x-gts-closed-derivations|OP#12|OP#6|/validate-type-schema|/validate-instance|/validate-entity' .

Repository: GlobalTypeSystem/gts-spec

Length of output: 50384


Scope registration enforcement by endpoint.

The current ?validate=true enforcement list says x-gts-closed-derivations is enforced on /validate-instance. Derivation compatibility belongs to schema registration / OP#12 (/validate-type-schema / /validate-entity type validation); instance validation does not check base-chain derivation. Split the endpoint scope per modifier.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 1771, Update the “9.11.6 Registration enforcement”
documentation to scope x-gts-closed-derivations enforcement to schema
registration and OP#12 endpoints (/validate-type-schema and /validate-entity
type validation), removing /validate-instance. Keep each modifier’s enforcement
endpoint listed separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant