From 207e461dd818c1946d0065872c8faed5fb01dd28 Mon Sep 17 00:00:00 2001 From: Alexis Cote Date: Mon, 3 Aug 2026 10:52:47 -0400 Subject: [PATCH] fix: Allow to tag non-exhaustive union types Add a new OpenAPI annotation that allows to tag union types that are non-exhaustive. Union types are considered "non-exhaustive" when they can be extended through plugins. Generators can later leverage this annotation to support extension. --- CHANGELOG.md | 1 + DEVELOPER_GUIDE.md | 1 + spec/schemas/_common.aggregations.yaml | 1 + spec/schemas/_common.analysis.yaml | 4 ++++ spec/schemas/_common.mapping.yaml | 1 + spec/schemas/_common.query_dsl.yaml | 2 ++ spec/schemas/_core.search.yaml | 1 + spec/schemas/ingest._common.yaml | 1 + tools/src/linter/SchemasValidator.ts | 3 ++- tools/src/tester/SchemaValidator.ts | 3 ++- 10 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a23b2c6..f9cd17edc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added `query` to TermsLookup to support terms lookup by query - Added `mapper_type` and `mapper_settings` to `IngestionSource` index settings ([#1155](https://github.com/opensearch-project/opensearch-api-specification/pull/1155)) - Added `search` and `warm` node roles to `NodeRole`, and modeled the pre-3.0 `search` role (renamed to `warm` in 3.0) as a version-scoped branch ([#1006](https://github.com/opensearch-project/opensearch-api-specification/pull/1006)) +- Added `x-non-exhaustive` vendor extension to mark plugin-extensible union types (`Property`, `Analyzer`, `TokenizerDefinition`, `TokenFilterDefinition`, `CharFilterDefinition`, `QueryContainer`, `SpanQuery`, `AggregationContainer`, `ProcessorContainer`, `FieldSuggester`) ### Deprecated - Marked the plural `_aliases` URL forms of `put_alias` and `delete_alias` as deprecated; the singular `_alias` form is the canonical path ([#1131](https://github.com/opensearch-project/opensearch-api-specification/pull/1131)) diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 15cff676e..3f1c2a721 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -144,6 +144,7 @@ This repository includes several OpenAPI Specification Extensions to fill in any - `x-default`: Contains the default value of a parameter. This is often used to override the default value specified in the schema, or to avoid accidentally changing the default value when updating a shared schema. - `x-distributions-included`: Contains a list of distributions known to include the API. - `x-distributions-excluded`: Contains a list of distributions known to exclude the API. +- `x-non-exhaustive`: Denotes that a discriminated union (tagged type) is non-exhaustive, meaning plugins can register additional variants at runtime. Code generators should treat these unions as open/extensible. Use `opensearch.org` for the official distribution in `x-distributions-*`, `amazon-managed` for Amazon Managed OpenSearch, and `amazon-serverless` for Amazon OpenSearch Serverless. diff --git a/spec/schemas/_common.aggregations.yaml b/spec/schemas/_common.aggregations.yaml index d7b02073f..3d1eed4c2 100644 --- a/spec/schemas/_common.aggregations.yaml +++ b/spec/schemas/_common.aggregations.yaml @@ -1425,6 +1425,7 @@ components: - skewness - variance AggregationContainer: + x-non-exhaustive: true allOf: - $ref: '#/components/schemas/Aggregation' - type: object diff --git a/spec/schemas/_common.analysis.yaml b/spec/schemas/_common.analysis.yaml index 3c334454e..d99453b80 100644 --- a/spec/schemas/_common.analysis.yaml +++ b/spec/schemas/_common.analysis.yaml @@ -8,6 +8,7 @@ components: schemas: Analyzer: type: object + x-non-exhaustive: true discriminator: propertyName: type oneOf: @@ -401,6 +402,7 @@ components: $ref: '#/components/schemas/CharFilterDefinition' CharFilterDefinition: type: object + x-non-exhaustive: true discriminator: propertyName: type oneOf: @@ -500,6 +502,7 @@ components: $ref: '#/components/schemas/TokenFilterDefinition' TokenFilterDefinition: type: object + x-non-exhaustive: true discriminator: propertyName: type oneOf: @@ -1586,6 +1589,7 @@ components: $ref: '#/components/schemas/TokenizerDefinition' TokenizerDefinition: type: object + x-non-exhaustive: true discriminator: propertyName: type oneOf: diff --git a/spec/schemas/_common.mapping.yaml b/spec/schemas/_common.mapping.yaml index a18bbd566..f1aed1158 100644 --- a/spec/schemas/_common.mapping.yaml +++ b/spec/schemas/_common.mapping.yaml @@ -159,6 +159,7 @@ components: - xy_shape Property: type: object + x-non-exhaustive: true discriminator: propertyName: type x-default: object diff --git a/spec/schemas/_common.query_dsl.yaml b/spec/schemas/_common.query_dsl.yaml index 9bd0b6ea0..bd52b4ca5 100644 --- a/spec/schemas/_common.query_dsl.yaml +++ b/spec/schemas/_common.query_dsl.yaml @@ -17,6 +17,7 @@ components: # eslint-enable yml/sort-sequence-values QueryContainer: type: object + x-non-exhaustive: true properties: agentic: $ref: '#/components/schemas/AgenticQuery' @@ -1951,6 +1952,7 @@ components: - little SpanQuery: type: object + x-non-exhaustive: true properties: span_containing: $ref: '#/components/schemas/SpanContainingQuery' diff --git a/spec/schemas/_core.search.yaml b/spec/schemas/_core.search.yaml index 6f43fb904..52ee8c629 100644 --- a/spec/schemas/_core.search.yaml +++ b/spec/schemas/_core.search.yaml @@ -1039,6 +1039,7 @@ components: description: The named suggesters. $ref: '#/components/schemas/FieldSuggester' FieldSuggester: + x-non-exhaustive: true allOf: - type: object properties: diff --git a/spec/schemas/ingest._common.yaml b/spec/schemas/ingest._common.yaml index eaaded4c2..b98c5876d 100644 --- a/spec/schemas/ingest._common.yaml +++ b/spec/schemas/ingest._common.yaml @@ -30,6 +30,7 @@ components: $ref: '_common.yaml#/components/schemas/Metadata' ProcessorContainer: type: object + x-non-exhaustive: true properties: attachment: $ref: '#/components/schemas/AttachmentProcessor' diff --git a/tools/src/linter/SchemasValidator.ts b/tools/src/linter/SchemasValidator.ts index a0664e28f..1dd6fbd1d 100644 --- a/tools/src/linter/SchemasValidator.ts +++ b/tools/src/linter/SchemasValidator.ts @@ -24,7 +24,8 @@ const ADDITIONAL_KEYWORDS = [ 'x-protobuf-excluded', 'x-protobuf-data-type', 'x-protobuf-name', - 'x-protobuf-required' + 'x-protobuf-required', + 'x-non-exhaustive' ] export default class SchemasValidator { diff --git a/tools/src/tester/SchemaValidator.ts b/tools/src/tester/SchemaValidator.ts index 76cf531fb..39b11235c 100644 --- a/tools/src/tester/SchemaValidator.ts +++ b/tools/src/tester/SchemaValidator.ts @@ -27,7 +27,8 @@ const ADDITIONAL_KEYWORDS = [ 'x-protobuf-excluded', 'x-protobuf-data-type', 'x-protobuf-name', - 'x-protobuf-required' + 'x-protobuf-required', + 'x-non-exhaustive' ] export default class SchemaValidator {