Skip to content
Open
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
53 changes: 32 additions & 21 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@ Thank you for your interest in contributing to the Global Type System (GTS) Spec
### Prerequisites

- **Git** for version control
- **JSON Schema validator** (optional, for testing schema examples)
- **Python 3.8+** (optional, for running reference implementations)
- **Node.js 20+ and `ajv-cli`** (optional, for validating JSON Schema examples as CI does)
- **Python 3.9–3.14** (optional, for working on the conformance test suite)
- **Docker** (optional, and recommended for running the conformance test suite)
- **Your favorite editor** (VS Code with JSON Schema support recommended)

### Development Setup

```bash
# Clone the repository
git clone <repository-url>
git clone https://github.com/GlobalTypeSystem/gts-spec.git
cd gts-spec

# Optional: Install Python dependencies for reference implementations
pip install jsonschema

# Optional: Install JSON Schema validator
# Optional: install the JSON Schema validator used by CI
npm install -g ajv-cli
```

The conformance tests run against an external GTS implementation over HTTP; this repository does not contain a reference implementation. See [`tests/README.md`](tests/README.md) for Docker and local Python setup.

### Repository Layout

```
gts-spec/
├── README.md # Main specification document
├── README.md # Normative specification
├── CONTRIBUTING.md # This file
├── LICENSE # License information
── examples/ # Example GTS Types and instances
├── events/ # Event-related examples
├── types/ # GTS Type Schemas (JSON Schema documents)
└── instances/ # JSON instance examples
└── ... # Other domain examples
├── LICENSE # License
── NOTICE # Attribution notices
├── adr/ # Architecture Decision Records (+ template.md)
├── examples/ # GTS Types and Instances in JSON, YAML, and TypeSpec
├── tests/ # Implementation-independent HTTP conformance tests
└── .github/workflows/ # CI and release workflows
```

## Development Workflow
Expand All @@ -57,16 +57,26 @@ Use descriptive branch names:

Follow the specification standards and patterns described below.

#### Specification changes require an ADR

Any proposal that adds normative behavior to the specification or intentionally changes existing normative behavior **MUST go through the Architecture Decision Record (ADR) process**. Start by copying the project-adapted MADR [`ADR template`](adr/template.md) to the next sequentially numbered file under [`adr/`](adr/) and fill in all applicable sections. The specification, tests, and examples must reference or implement the decision where applicable.

Open the pull request with the ADR already at **`Status: Accepted`** — the decision is what is under review, so accepting the ADR *is* merging the pull request. There is no separate approval step and no `Proposed` state in the repository: an ADR on `main` is accepted by definition. A decision that is later replaced keeps its file and moves to `Status: Superseded`, with `Superseded by` pointing at the ADR that replaces it (and that ADR's `Supersedes` pointing back). The ADR may be reviewed in its own pull request or together with the resulting specification change; either way it must not be merged before the reviewers agree on the decision itself.

A confirmed bug fix does not require a new ADR when it only restores behavior already established by the specification or an accepted ADR. If fixing the issue requires choosing new semantics, it is a specification change and therefore requires an ADR.

### 3. Validate Your Changes

```bash
# Validate all schemas in a directory
ajv compile --strict=false -s "examples/events/types/*.schema.json"
# Validate the JSON Schema examples covered by CI
ajv compile -s "examples/*/types/*.schema.json" --strict=false

# Run Python reference implementation tests (if available)
python -m pytest tests/
# Run the conformance tests against a GTS server already listening on port 8000
python -m pytest tests/ --gts-base-url http://127.0.0.1:8000
```

Run the checks relevant to the files you changed. JSONC, YAML, TypeSpec, nested example directories, and unresolved `gts://` references may require their own format-aware validation in addition to the CI command above. For test-suite setup and targeted test invocations, follow [`tests/README.md`](tests/README.md).

### 4. Commit Changes

Follow a structured commit message format:
Expand Down Expand Up @@ -113,8 +123,9 @@ Specification development guidelines:

- Follow GTS identifier format rules strictly
- Ensure all schemas use correct `$id` values
- Validate schemas against JSON Schema Draft 7 or later
- Declare the intended JSON Schema dialect with `$schema` and use keywords valid for that dialect; GTS is dialect-agnostic, while repository examples generally use Draft-07 for interoperability
- Include both GTS Type Schemas (the canonical JSON definitions of types) and GTS Instance examples
- Keep normative specification changes, conformance tests, and examples aligned
- Document any deviations or implementation-specific choices

## Releases
Expand All @@ -139,8 +150,8 @@ When the specification moves to the next minor version (e.g. `0.11` → `0.12`),
Releases are produced from `github.com/GlobalTypeSystem/gts-spec`. The workflow is restricted to that repository; pushing a tag from a fork has no effect.

```bash
git tag v0.11.3
git push origin v0.11.3
git tag vX.Y.Z
git push origin vX.Y.Z
```

The [`Release Tests Image`](.github/workflows/release-tests-image.yml) workflow:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,7 @@ Given an inheritance chain `S₀ → S₁ → … → Sₙ`:
- **`null` at any depth deletes that key** from the effective object (per RFC 7396). The principal use case is to revert an ancestor-set value and let the trait-schema's `default` re-apply via the materialization step described in the Completeness check below — that is, a descendant writes `"<key>": null` to "fall back to the schema default" without picking a specific value. If the deleted key is `required` and has no `default`, the completeness check (OP#13) fails for non-abstract types (the descendant must then either mark itself abstract or accept that "delete + required + no default" is an unresolvable contract). Authors who want `null` as an *intended* trait value cannot express it via this merge and must use a sentinel value documented as part of the trait shape.
- Defaults declared in the effective trait-schema MUST be materialized into the effective traits object before the Completeness check runs (per ADR-0003): for every property declared in the effective trait-schema with a `default` and not present in the chain-merged object, the registry MUST substitute the default value. The Completeness check below (OP#13) operates on the resulting *materialized* effective traits object.
- A publisher who wants a trait value to be **locked** across all descendants of a base type SHOULD declare `"const": <value>` for that property in `x-gts-traits-schema`. A descendant attempting to override the value will fail the standard JSON Schema validation that runs against the effective trait-schema (per the Completeness check below). No GTS-specific "immutability" rule is required — `const` is the mechanism.
- `const` constrains the **value** of a property, not its presence: per standard JSON Schema it asserts nothing when the property is absent. A publisher who additionally wants the trait to survive an RFC 7396 `null` deletion SHOULD either list the property in the containing object schema's `required` array (deletion then fails the Completeness check for non-abstract types) or declare a `default` equal to the `const` value (deletion then becomes a no-op, since materialization restores the value before validation). This is the general presence rule for traits — it is not specific to `const`: any optional inherited trait without a `default` can be removed by a descendant.
- A descendant MAY redeclare a trait value with the same value the ancestor already declared (idempotent restatement).
- See [`adr/0004-x-gts-traits-merge-strategy.md`](adr/0004-x-gts-traits-merge-strategy.md) for the rationale.

Expand Down
5 changes: 4 additions & 1 deletion adr/0001-derivation-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ This ADR does **not** make GTS a [JSON Schema Dialect](https://json-schema.org/l

## Considered Options

- Option 1 — Strict canonical form
- Option 2 — GTS Type Schema as a JSON Schema Extension (dialect-agnostic) *(chosen)*

Both options use the same running example.

### Running example used in this section
Expand Down Expand Up @@ -207,7 +210,7 @@ P-OK validates; P-BAD fails. Syntactically valid and semantically compatible —

## Decision Outcome

Chosen: **Option 2 — GTS Type Schema as a JSON Schema Extension (dialect-agnostic).**
Chosen option: **Option 2 — GTS Type Schema as a JSON Schema Extension (dialect-agnostic).**

Key normative consequences:

Expand Down
9 changes: 7 additions & 2 deletions adr/0002-x-gts-traits-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ ADR-0001 commits GTS to being an **extension of JSON Schema** (dialect-agnostic;

## Considered Options

Two options. Option 2 has two sub-variants (2A and 2B) which we evaluate inside Option 2.
- Option 1 — Trait-type as a separately-registered GTS Type (URI value)
- Option 2 — `x-gts-traits-schema` is a JSON Schema subschema, in two sub-variants:
- Option 2A — Subschema + implicit chain aggregation *(chosen)*
- Option 2B — Subschema + explicit composition by the author

Option 2's sub-variants share the keyword's value space and differ only in who composes the declarations along the chain; they are evaluated inside Option 2 below.

### Option 1 — Trait-type as a separately-registered GTS Type (URI value)

Expand Down Expand Up @@ -229,7 +234,7 @@ By construction, any value satisfying the effective trait-schema also satisfies

## Decision Outcome

Chosen: **Option 2A — `x-gts-traits-schema` is a JSON Schema subschema (object OR boolean); the registry composes declarations along the `$id` chain via `allOf`.**
Chosen option: **Option 2A — `x-gts-traits-schema` is a JSON Schema subschema (object OR boolean); the registry composes declarations along the `$id` chain via `allOf`.**

Normative consequences:

Expand Down
8 changes: 6 additions & 2 deletions adr/0003-x-gts-traits-completeness.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ ADR-0001 commits GTS to being an extension of JSON Schema (dialect-agnostic); AD

## Considered Options

- Option 1 — No spec-level enforcement (author's responsibility)
- Option 2 — Validate at instance creation time
- Option 3 — Validate at type registration (fail fast) *(chosen)*

Three top-level options on **when (or whether) to enforce completeness**.

### Option 1 — No spec-level enforcement (author's responsibility)
Expand Down Expand Up @@ -223,7 +227,7 @@ Three ways to make the registration succeed:

## Decision Outcome

Chosen: **Option 3 — validate at type registration; non-abstract types MUST be complete.**
Chosen option: **Option 3 — validate at type registration; non-abstract types MUST be complete.**
Comment thread
aviator5 marked this conversation as resolved.

### Definition of "complete"

Expand Down Expand Up @@ -254,7 +258,7 @@ At the registration of type T:
- **Non-abstract type with required-no-default and no explicit value.** Registration fails. Author resolves by (a) providing `x-gts-traits` value, (b) declaring a `default` in the schema, or (c) marking the type abstract.
- **Final non-abstract type.** Same rule as any non-abstract — must be complete. No special bullet needed.

## Implications
### Implications

- **OP#13 (Schema Traits Validation)** includes this rule; the operation explicitly conditions the completeness step on `x-gts-abstract != true`.
- **§9.7.5** carries the normative wording of the completeness check in the "Validation" bullet block, expressed in terms of "non-abstract types."
Expand Down
Loading