Skip to content
Draft
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
7 changes: 7 additions & 0 deletions schemas/v1.2-dev/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ properties:
overlay:
type: string
pattern: ^1\.2\.\d+$
$self:
type: string
format: uri-reference
$comment: MUST NOT contain a fragment
pattern: "^[^#]*$"
info:
$ref: "#/$defs/info-object"
extends:
type: string
format: uri-reference
$comment: MUST NOT contain a fragment
pattern: "^[^#]*$"
actions:
type: array
minItems: 1
Expand Down
7 changes: 7 additions & 0 deletions tests/v1.2-dev/fail/extends-with-fragment.yaml
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: '$'
7 changes: 7 additions & 0 deletions tests/v1.2-dev/fail/self-with-fragment.yaml
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: '$'
10 changes: 10 additions & 0 deletions tests/v1.2-dev/pass/self-and-extends-identifier.yaml
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
10 changes: 10 additions & 0 deletions tests/v1.2-dev/pass/self-with-relative-extends.yaml
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
202 changes: 197 additions & 5 deletions versions/1.2.0-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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. |
Expand All @@ -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'
Comment thread
baywet marked this conversation as resolved.
...
```

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.
Expand Down Expand Up @@ -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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The 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.
Loading