-
Notifications
You must be signed in to change notification settings - Fork 33
feat: adds support for self in overlay #322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4efbc49
afd5fc3
51fb0e0
8d3b482
a362675
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| overlay: 1.2.0 | ||
| info: | ||
| title: Invalid extends with fragment | ||
| version: 1.0.0 | ||
| extends: https://api.example.com/openapi/petstore.yaml#/paths/~1pets | ||
| actions: | ||
| - target: '$' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| overlay: 1.2.0 | ||
| $self: https://example.com/overlays/petstore.overlay.yaml#fragment | ||
| info: | ||
| title: Invalid self with fragment | ||
| version: 1.0.0 | ||
| actions: | ||
| - target: '$' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| overlay: 1.2.0 | ||
| $self: https://example.com/overlays/petstore.overlay.yaml | ||
| info: | ||
| title: Overlay with identifier-based extends | ||
| version: 1.0.0 | ||
| extends: https://api.example.com/openapi/petstore.yaml | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay-applied: true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| overlay: 1.2.0 | ||
| $self: https://example.com/overlays/petstore.overlay.yaml | ||
| info: | ||
| title: Overlay with relative extends | ||
| version: 1.0.0 | ||
| extends: ../openapi/petstore.yaml | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay-applied: true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,9 +65,40 @@ Where Overlay tooling renders rich text it MUST support, at a minimum, markdown | |
| While the framing of CommonMark 0.27 as a minimum requirement means that tooling MAY choose to implement extensions on top of it, note that any such extensions are by definition implementation-defined and will not be interoperable. | ||
| Overlay Description authors SHOULD consider how text using such extensions will be rendered by tools that offer only the minimum support. | ||
|
|
||
| ### Parsing Documents | ||
|
|
||
| Implementations MUST NOT treat an `extends` value as unresolvable before checking all possible target [[OpenAPI]] Description documents provided to the implementation. | ||
|
|
||
| To ensure interoperability, when a target [[OpenAPI]] Description defines `$self`, the Overlay's `extends` value MUST match the target's `$self` URI. | ||
| Implementations MUST examine all available target documents for matching `$self` values before concluding that no document matches the `extends` URI. | ||
|
|
||
| Implementations MAY also support retrieval URI matching, which can be useful when `$self` is not defined in the target document. | ||
|
|
||
| ### Relative References in URIs | ||
|
|
||
| Unless specified otherwise, all fields that are URI references MAY be relative references as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-4.2). | ||
| URIs used in an Overlay document, including `$self` and `extends`, are identifiers, and not necessarily locators (URLs). | ||
|
|
||
| Unless specified otherwise, all fields that are URI references MAY be relative references as defined by [RFC3986 Section 4.2](https://tools.ietf.org/html/rfc3986#section-4.2). | ||
|
|
||
| #### Establishing the Base URI | ||
|
|
||
| Relative URI references are resolved using the appropriate base URI, which MUST be determined in accordance with [RFC3986 Section 5.1.1 - 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.1). | ||
|
|
||
| The base URI for resolving relative references within an Overlay document is determined as follows: | ||
|
|
||
| - If the [`$self`](#overlay-self) field is present and is an absolute URI, the base URI is the `$self` URI (per [RFC3986 Section 5.1.1](https://tools.ietf.org/html/rfc3986#section-5.1.1): Base URI Embedded in Content). | ||
| - If the [`$self`](#overlay-self) field is present and is a relative URI-reference, it MUST first be resolved against the next possible base URI source per [RFC3986 Section 5.1.2 - 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.2) before being used as the base URI for resolving other relative references. | ||
| - If the [`$self`](#overlay-self) field is not present, the base URI MUST be determined from the next possible base URI source per [RFC3986 Section 5.1.2 - 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.2). The most common base URI source in this case is the retrieval URI of the Overlay document (per [RFC3986 Section 5.1.3](https://tools.ietf.org/html/rfc3986#section-5.1.3)), though other sources such as encapsulating entities ([RFC3986 Section 5.1.2](https://tools.ietf.org/html/rfc3986#section-5.1.2)) or application-specific defaults ([RFC3986 Section 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.4)) MAY apply. | ||
|
|
||
| #### Resolving URI Fragments | ||
|
|
||
| Where a URI appears in contexts such as CommonMark hyperlinks within `description` fields and contains a fragment identifier, the fragment MUST be resolved per the fragment resolution mechanism of the referenced document. | ||
|
|
||
| For Overlay Object fields that identify whole documents (`$self` and `extends`), fragment identifiers MUST NOT be used. | ||
|
|
||
| #### Relative URI References in CommonMark Fields | ||
|
|
||
| Relative references in CommonMark hyperlinks (such as those in `description` fields) are resolved in their rendered context, which might differ from the context of the Overlay document. | ||
|
|
||
| ### Schema | ||
|
|
||
|
|
@@ -82,6 +113,7 @@ This is the root object of the [Overlay](#overlay). | |
| | Field Name | Type | Description | | ||
| | ---- | :----: | ---- | | ||
| | <a name="overlay-version"></a>overlay | `string` | **REQUIRED**. This string MUST be the [version number](#versions) of the Overlay Specification that the Overlay document uses. The `overlay` field SHOULD be used by tooling to interpret the Overlay document. | | ||
| | <a name="overlay-self"></a>$self | `string` | A URI-reference for the Overlay document. This string MUST be in the form of a URI-reference as defined by [RFC3986 Section 4.1](https://tools.ietf.org/html/rfc3986#section-4.1). When present, this field provides the self-assigned URI of this Overlay document, which also serves as its base URI in accordance with [RFC3986 Section 5.1.1](https://tools.ietf.org/html/rfc3986#section-5.1.1) for resolving relative references within this document. The `$self` URI MUST NOT contain a fragment identifier. Overlay documents MAY include a `$self` field to ensure portable, unambiguous reference resolution. | | ||
| | <a name="overlay-info"></a>info | [Info Object](#info-object) | **REQUIRED**. Provides metadata about the Overlay. The metadata MAY be used by tooling as required. | | ||
| | <a name="overlay-extends"></a>extends | `string` | URI reference that identifies the target document (such as an [[OpenAPI]] document) this overlay applies to. | | ||
| | <a name="overlay-actions"></a>actions | [[Action Object](#action-object)] | **REQUIRED** An ordered list of actions to be applied to the target document. The array MUST contain at least one value. | | ||
|
|
@@ -90,29 +122,46 @@ This object MAY be extended with [Specification Extensions](#specification-exten | |
|
|
||
| The list of actions MUST be applied in sequential order to ensure a consistent outcome. Actions are applied to the result of the previous action. This enables objects to be deleted in one action and then re-created in a subsequent action, for example. | ||
|
|
||
| The `extends` property can be used to indicate that the Overlay was designed to update a specific [[OpenAPI]] document. Where no `extends` is provided it is the responsibility of tooling to apply the Overlay document to the appropriate OpenAPI document(s). | ||
| The `extends` property can be used to indicate that the Overlay was designed to update a specific [[OpenAPI]] description. | ||
| Where no `extends` is provided it is the responsibility of tooling to apply the Overlay document to the appropriate OpenAPI description(s). | ||
|
|
||
| In the following example, the Overlay identifies a target OpenAPI description using an absolute URI: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| info: | ||
| title: Overlay for the Tic Tac Toe API document | ||
| version: 1.0.0 | ||
| extends: 'https://api.example.com/openapi/tictactoe.yaml' | ||
| ... | ||
| ``` | ||
|
|
||
| In the following example the `extends` property specifies that the overlay is designed to update the OpenAPI Tic Tac Toe example document, identified by an absolute URI. | ||
| In the following example, the Overlay document also includes `$self`, which establishes the document's identity and base URI: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| $self: 'https://example.com/overlays/tictactoe.overlay.yaml' | ||
| info: | ||
| title: Overlay for the Tic Tac Toe API document | ||
| version: 1.0.0 | ||
| extends: 'https://raw.githubusercontent.com/OAI/learn.openapis.org/refs/heads/main/examples/v3.1/tictactoe.yaml' | ||
| extends: 'https://api.example.com/openapi/tictactoe.yaml' | ||
| ... | ||
| ``` | ||
|
|
||
| The `extends` property can also specify a relative URI reference. | ||
| Relative `extends` values are resolved using the base URI rules in [Relative References in URIs](#relative-references-in-uris): | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| $self: 'https://example.com/overlays/tictactoe.overlay.yaml' | ||
| info: | ||
| title: Overlay for the Tic Tac Toe API document | ||
| version: 1.0.0 | ||
| extends: './tictactoe.yaml' | ||
| extends: '../openapi/tictactoe.yaml' | ||
| ``` | ||
|
|
||
| With the above Overlay document, `extends` resolves to `https://example.com/openapi/tictactoe.yaml`. | ||
|
|
||
| #### Info Object | ||
|
|
||
| The object provides metadata about the Overlay. | ||
|
|
@@ -594,3 +643,146 @@ Some formats, like [YAML](https://yaml.org/) or [JSONC](https://jsonc.org/), sup | |
| | 1.2.0 | TBD | Release of the Overlay Specification 1.2.0 | | ||
| | 1.1.0 | 2026-01-14 | Release of the Overlay Specification 1.1.0 | | ||
| | 1.0.0 | 2024-10-17 | First release of the Overlay Specification | | ||
|
|
||
| ## Appendix B: Examples of Base URI Determination and Identifier Resolution | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @baywet Is there a reason you skipped the enclosing context and application-assigned cases that we have in OAS and Arazzo?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an oversight, thanks for calling this out, updated. |
||
|
|
||
| This appendix provides concrete examples demonstrating how the [`$self`](#overlay-self) field, Source Description URLs, and relative references work together across different deployment scenarios. | ||
|
|
||
| ### Base URI Within Content (Using `$self`) | ||
|
|
||
| Assume the following Overlay document is retrieved from `file:///Users/dev/projects/overlays/purchase.overlay.yaml`: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| $self: https://example.com/overlays/purchase.overlay.yaml | ||
| info: | ||
| title: Purchase overlay | ||
| version: 1.0.0 | ||
| extends: ../openapi/petstore.yaml | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay: purchase | ||
| ``` | ||
|
|
||
| The relative `extends` URI `../openapi/petstore.yaml` resolves against the `$self` base URI `https://example.com/overlays/purchase.overlay.yaml`, producing `https://example.com/openapi/petstore.yaml`, regardless of the retrieval URI. | ||
|
|
||
| ### Base URI From the Retrieval URI (No `$self`) | ||
|
|
||
| If the same Overlay document does not define `$self`: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| info: | ||
| title: Purchase overlay | ||
| version: 1.0.0 | ||
| extends: ../openapi/petstore.yaml | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay: purchase | ||
| ``` | ||
|
|
||
| Retrieved from `file:///Users/dev/projects/overlays/purchase.overlay.yaml`, the relative `extends` URI resolves to `file:///Users/dev/projects/openapi/petstore.yaml`. | ||
|
|
||
| ### Base URI From Encapsulating Entity | ||
|
|
||
| Per [RFC3986 Section 5.1.2](https://tools.ietf.org/html/rfc3986#section-5.1.2), the base URI can be provided by an encapsulating entity. For example, in a `multipart/related` response where an Overlay document is embedded: | ||
|
|
||
| ```http | ||
| Content-Type: multipart/related; boundary=example; type=application/json | ||
|
|
||
| --example | ||
| Content-Type: application/json | ||
| Content-Location: https://example.com/overlays/purchase.overlay.json | ||
|
|
||
| { | ||
| "overlay": "1.2.0", | ||
| "info": {"title": "Purchase overlay", "version": "1.0.0"}, | ||
| "extends": "../openapi/petstore.json", | ||
| "actions": [ | ||
| { | ||
| "target": "$.info", | ||
| "update": {"x-overlay": "purchase"} | ||
| } | ||
| ] | ||
| } | ||
| --example-- | ||
| ``` | ||
|
|
||
| The `Content-Location` header provides the base URI (`https://example.com/overlays/purchase.overlay.json`), so `../openapi/petstore.json` resolves to `https://example.com/openapi/petstore.json` even without a `$self` field. | ||
|
|
||
| ### Application-Specific Default Base URI | ||
|
|
||
| Per [RFC3986 Section 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.4), applications may define default base URIs. For documents loaded without explicit retrieval URIs (e.g., from a database), implementations typically generate a unique base URI per document using a fixed prefix plus a unique identifier. | ||
|
|
||
| For example, an API management platform might construct base URIs as `https://overlays.example.com/{uuid}` for each document: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| # No $self field | ||
| # Loaded from database, assigned base URI: https://overlays.example.com/a7b3c4d5 | ||
| info: | ||
| title: Purchase overlay | ||
| version: 1.0.0 | ||
| extends: specs/petstore.yaml # Resolves using application default | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay: purchase | ||
| ``` | ||
|
|
||
| If the application assigns base URI `https://overlays.example.com/a7b3c4d5` to this document, then `specs/petstore.yaml` resolves to `https://overlays.example.com/specs/petstore.yaml`. | ||
|
|
||
| **Note:** While a base URI of `https://overlays.example.com/` (with trailing slash) is technically valid per RFC3986, the final path component is an empty string. In practice, implementations typically assign unique identifiers as the final component to distinguish documents. | ||
|
|
||
| ### Resolving Relative `$self` | ||
|
|
||
| When `$self` is itself a relative URI-reference, it must be resolved before being used as a base URI: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| $self: overlays/purchase.overlay.yaml | ||
| info: | ||
| title: Purchase overlay | ||
| version: 1.0.0 | ||
| extends: ../openapi/petstore.yaml | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay: purchase | ||
| ``` | ||
|
|
||
| Retrieved from `https://example.com/v2/api-description.yaml`: | ||
|
|
||
| 1. First, resolve the `$self` relative reference `overlays/purchase.overlay.yaml` against the retrieval URI `https://example.com/v2/api-description.yaml`, which resolves to `https://example.com/v2/overlays/purchase.overlay.yaml` per [RFC3986 Section 5.2](https://tools.ietf.org/html/rfc3986#section-5.2). | ||
| 2. Then resolve the `extends` relative reference `../openapi/petstore.yaml` against the resolved `$self` base URI `https://example.com/v2/overlays/purchase.overlay.yaml`, which resolves to `https://example.com/v2/openapi/petstore.yaml`. | ||
|
|
||
| ### Why Potential Target Documents Should Be Checked for `$self` | ||
|
|
||
| An Overlay may be given this `extends` value: | ||
|
|
||
| ```yaml | ||
| overlay: 1.2.0 | ||
| info: | ||
| title: Overlay for approved API description | ||
| version: 1.0.0 | ||
| extends: https://apis.example.com/approved/petstore.yaml | ||
| actions: | ||
| - target: '$.info' | ||
| update: | ||
| x-overlay: approved | ||
| ``` | ||
|
|
||
| A candidate target OpenAPI description might be retrieved from `https://cdn.example.net/mirror/petstore.yaml` while declaring: | ||
|
|
||
| ```yaml | ||
| openapi: 3.2.0 | ||
| $self: https://apis.example.com/approved/petstore.yaml | ||
| info: | ||
| title: Petstore | ||
| version: 1.0.0 | ||
| paths: {} | ||
| ``` | ||
|
|
||
| Because `extends` is identifier-based, the match succeeds using the target description's `$self` URI, even though retrieval occurred from a different location. | ||
Uh oh!
There was an error while loading. Please reload this page.