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
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
200 changes: 195 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 portability, when a target [[OpenAPI]] Description defines `$self`, the Overlay's `extends` value SHOULD match the target's `$self` URI.
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.

[I also apologize for failing to hit send on this two days ago]

I apologize for not noticing this earlier, but I'm not sure "interoperability" is the ideal word here.

This is really more about portability (of the documents) than interoperability. Given the same input, implementations would be expected to resolve the references the same way. I suppose this is a bit more interoperable as implementations might have different ways to figure out the current document's location for resolving a relative extends, but... hmm... I think this is more about portability of document sets. idk, does anyone else think "interoperability" is better here?

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

I'm pretty sure that if there's no $self then whatever the past requirements for extends were would still apply. Presumably that was a "MUST match based on the retrieval URI" or some similar location thing?

I'm guessing that this wording is based on reading this from the OAS:

Implementations MAY support document retrieval, although see the Security Considerations sections for additional guidance.

The MAY there is referring to actually performing an I/O operation to fetch the document. That is optional, and potentially a security issue so it really shouldn't be on by default. But the rest of that paragraph basically says "or you handle this by letting the user tell you what the retrieval URI was."

Copy link
Copy Markdown
Member Author

@baywet baywet Apr 22, 2026

Choose a reason for hiding this comment

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

I re-read your comment, and the paragraph, multiple times to ensure I was understanding things properly here.

I feel this paragraph is actually redundant, the extends behaviour is documented in details for URI retrieval. My suggestion is to remove this entirely.

Essentially here is what we want people to do (in order, read like a truth table):

  1. extends, no self, no contextual information => do uri retrievial with extends
  2. extends, no self, contextual information => do uri retrieval with extends, then try the contextual information (tool specific)
  3. no extends, no self, contextual information => do uri retrivial from the contextual information
  4. no extends, no self, no contextual information => fail, there's no way to locate the OAI document
  5. extends, self, no contextual information => do uri retrievial with extends, if it's a relative uri, use self to build the uri
  6. extends, self, contextual information => do uri retrieval with extends, then try the contextual information (tool specific), if the uri is relative, use self like in 5 to build the uri
  7. no extends, self, contextual information => do url retrieval from context information, if the uri is relative, use self like in 5 to build the uri
  8. no extends, self, no contextual information => fail, there's no way to locate the OAI document

In any of those cases where uri retrivial is performed, there's a security risk.
In any of those case where self is present, the tool should additionally perform the comparison with the self of the OAD when present. Either with the full URI from extends, or with the resolved uri from overlay self + extends/contextual relative information.

Is that a faire representation? if so, do you think this is captured well enough in the current proposal?

Lastly, cases 1, 2, 3, 4 were already specified by earlier version of the specification. Cases 5, 6, 7, 8 are being added here.

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.

I agree that you can drop the paragraph and things will be less confusing.

Separately, part of the point of $self is to allow you to provide all of the referenced (including by extends) documents to the tool up front so you don't have to take the performance/reliability hit or the security risk of performing actual retrieval.


### 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,144 @@ 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
Comment thread
baywet marked this conversation as resolved.

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`.

Comment thread
baywet marked this conversation as resolved.
### 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