Skip to content
Open
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
137 changes: 131 additions & 6 deletions versions/1.2.0-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,56 @@ 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

Each possible target [[OpenAPI]] Description document MUST be fully parsed in order to locate possible `extends` resolution targets before attempting to resolve an Overlay's `extends` value.
Comment thread
baywet marked this conversation as resolved.
Outdated
Reference targets include the root object's `$self` field when present.
Comment thread
baywet marked this conversation as resolved.
Outdated

Implementations MUST NOT treat an `extends` value as unresolvable before completely parsing all possible target OpenAPI Description documents provided to the implementation.

#### Fragmentary Parsing

**Fragmentary parsing** occurs when an implementation parses only the specific part of a target description that seems needed, rather than parsing complete candidate target descriptions first.
This practice is **strongly discouraged** and produces undefined behavior.
Comment thread
baywet marked this conversation as resolved.
Outdated

If only parts of a target description are parsed, implementations can miss the root `$self` field and incorrectly fail to resolve, or mis-resolve, `extends` values.
When fragmentary parsing causes resolution failures or unintended matches, the resulting behavior is _undefined_ and _implementation-defined_.

Implementations MUST parse complete candidate target descriptions before resolving `extends` values to ensure predictable and interoperable behavior.

#### Identifier-Based Referencing

To ensure interoperability, when an Overlay identifies a target [[OpenAPI]] Description by URI using `extends`, that URI MUST be the target description's `$self` URI if the target defines `$self`.

This means implementations MUST examine possible target OpenAPI Description documents to check for matching `$self` values before deciding no document matches the `extends` URI.

Implementations MAY support additional, non-interoperable lookup methods (such as retrieval URI matching), but relying on those methods is NOT RECOMMENDED.
Comment thread
baywet marked this conversation as resolved.
Outdated

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

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

#### Resolving URI Fragments

If a URI contains a fragment identifier, then 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.
Comment thread
baywet marked this conversation as resolved.
Outdated

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

### Schema

Expand All @@ -82,6 +129,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 SHOULD include a `$self` field to ensure portable, unambiguous reference resolution. |
Comment thread
baywet marked this conversation as resolved.
Outdated
| <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 +138,38 @@ 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).

The `extends` property is an identifier.
When candidate OpenAPI description documents define `$self`, the `extends` value MUST be matched to `$self` as described in [Identifier-Based Referencing](#identifier-based-referencing).
Comment thread
baywet marked this conversation as resolved.
Outdated

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 includes `$self` and identifies a target OpenAPI description with an absolute 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 @@ -587,7 +644,75 @@ Interoperable Overlay Documents MUST use RFC9535 JSONPath query expressions and

Some formats, like [YAML](https://yaml.org/) or [JSONC](https://jsonc.org/), support using comments which do not impact the semantic meaning of the description. Applying Overlay Actions to a description MAY result in the loss of such comments in the updated description. The exact behavior is specific to the tool implementing the Overlay Specification.

## Appendix A: Revision History
## Appendix A: Examples of Base URI Determination and Identifier Resolution
Comment thread
baywet marked this conversation as resolved.
Outdated

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

### Identity vs Location: Why `extends` Should Match `$self`
Comment thread
baywet marked this conversation as resolved.
Outdated

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.

## Appendix B: Revision History

| Version | Date | Notes |
| ---- | ---- | ---- |
Expand Down
Loading