From a0613f899fa573e7b70479c8c1ae53c3b225ba28 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Thu, 2 May 2024 11:34:58 -0700 Subject: [PATCH 1/9] Clarify resolving implicit connections (3.1.1) This clarifies how to handle resolving implicit (non-URI-based) connections in multi-document OpenAPI Descriptions. While the behavior is implementation-defined overall, this RECOMMENDS a single approach based on how things behaved going back to the 2.0 referencing model. This allows Security Schemes and Tags to (like the top-level Server Objects) define a deployment-specific interface for referenced documents to access. This entry document interface approach makes less sense for the Discriminator Object, but it can use the URI syntax of `mapping` to keep things within the local document. This also aligns the search for matching `operationId`s with 3.1's full-document parsing requirements. Note that the term "complete OpenAPI document" has been defined in another change pending approval on the 3.0.4 branch. --- versions/3.1.1.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index f1486d64de..20e7023e6e 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -185,7 +185,7 @@ It is the responsibility of an embedding format to define how to parse embedded When parsing an OAD, JSON or YAML objects are parsed into specific Objects (such as [Operation Objects](#operationObject), [Response Objects](#responseObject), [Reference Objects](#referenceObject), etc.) based on the parsing context. Depending on how references are arranged, a given JSON or YAML object can be parsed in multiple different contexts: -* As a full OpenAPI Description document (an [OpenAPI Object](#oasObject) taking up an entire document) +* As a complete OpenAPI Description document * As the Object type implied by its parent Object within the document * As a reference target, with the Object type matching the reference source's context @@ -193,6 +193,38 @@ If the same JSON/YAML object is parsed multiple times and the respective context #### Resolving Implicit Connections +Several features of this specification require resolving a non-URI-based connection to some other part of the OpenAPI Description (OAD). + +These connections are easily resolved in single-document OADs, but the resolution process in multi-document OADs has never been spelled out, and is therefore _implementation-defined_, within the constraints described in this section. +In some cases, an unambiguous URI-based alternative is available, and OAD authors are RECOMMENDED to always use the alternative: + +Source | Target | Alternative +------ | ------ | ----------- +[Security Requirement Object](#securityRequirementObject) `{name}` | [Security Scheme Object](#securitySchemeObject) name under the [Components Object](#componentsObject) | _n/a_ +[Discriminator Object](#discriminatorObject) `mapping` _(implicit, or explicit name syntax)_ | [Schema Object](#schemaObject) name under the Components Object | `mapping` _(explicit URI syntax)_ +[Operation Object](#operationObject) `tags` | [Tag Object](#tagObject) `name` (in the Components Object) | _n/a_ +[Link Object](#linkObject) `operationId` | [Path Item Object](#pathItemObject) `operationId` | `operationRef` + +A fifth implicit connection, which involves appending the templated URL paths of the [Paths Object](#pathsObject) to the appropriate [Server Object](#serverObject)'s `url` field, is unambiguous because only the entry document's Paths Object contributes URLs to the described API. + +It is RECOMMENDED to consider all Operation Objects from all parsed documents when resolving any Link Object `operationId`. +This requires ensuring that all referenced documents have been parsed prior to determining an `operationId` to be unresolvable. + +The implicit connections in the Security Requirement Object and Discriminator Object rely on the _component name_, which is the property name holding the component in the appropriate typed sub-object of the Components Object. +For example, the component name of the Schema Object at `#/components/schemas/Foo` is `Foo`. +The implicit connection of tags in the Operation Object use the `name` field of Tag Objects, which (like the Components Object) are found under the root OpenAPI Object. +This means that resolving component names and tag names both depend on starting from the correct OpenAPI Object. + +For resolving component and tag name connections from a referenced (non-entry) document, it is RECOMMENDED that tools resolve from the entry document, rather than the current document. +This allows Security Scheme Objects and Tag Objects to be defined with the API's deployment information (the top-level Server Objects), and treated as an interface for referenced documents to access. + +The interface approach can also work for Discriminator Objects and Schema Objects, but it is also possible to keep the Discriminator Object's behavior within a single document using the relative URI-reference syntax of `mapping`. + +There are not currently URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field. +These limitations are expected to be addressed in a future release. + +Note that no aspect of implicit connection resolution changes how [URIs are resolved](#relativeReferencesURI), or restricts their possible targets. + ### Data Types Data types in the OAS are based on the types supported by the [JSON Schema Specification Draft 2020-12](https://tools.ietf.org/html/draft-bhutton-json-schema-00#section-4.2.1). From d202870e9d589c4cfff5a52454a1096a3a2e83b5 Mon Sep 17 00:00:00 2001 From: Henry Andrews Date: Tue, 28 May 2024 06:58:39 -0700 Subject: [PATCH 2/9] wording review feedback Co-authored-by: Ralf Handl --- versions/3.1.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index 20e7023e6e..50e585b49c 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -220,7 +220,7 @@ This allows Security Scheme Objects and Tag Objects to be defined with the API's The interface approach can also work for Discriminator Objects and Schema Objects, but it is also possible to keep the Discriminator Object's behavior within a single document using the relative URI-reference syntax of `mapping`. -There are not currently URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field. +There currently are no URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field. These limitations are expected to be addressed in a future release. Note that no aspect of implicit connection resolution changes how [URIs are resolved](#relativeReferencesURI), or restricts their possible targets. From 23ea5473a0883d710f71115d4745c0305e58bda7 Mon Sep 17 00:00:00 2001 From: Henry Andrews Date: Sat, 8 Jun 2024 13:22:08 -0700 Subject: [PATCH 3/9] Apply suggestions from code review Co-authored-by: Jeremy Fiel <32110157+jeremyfiel@users.noreply.github.com> --- versions/3.1.1.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index 50e585b49c..0d88a63f37 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -193,7 +193,8 @@ If the same JSON/YAML object is parsed multiple times and the respective context #### Resolving Implicit Connections -Several features of this specification require resolving a non-URI-based connection to some other part of the OpenAPI Description (OAD). +Several features of this specification require resolution of non-URI-based connections to some other part of the OpenAPI Description (OAD). +`` These connections are easily resolved in single-document OADs, but the resolution process in multi-document OADs has never been spelled out, and is therefore _implementation-defined_, within the constraints described in this section. In some cases, an unambiguous URI-based alternative is available, and OAD authors are RECOMMENDED to always use the alternative: @@ -210,10 +211,10 @@ A fifth implicit connection, which involves appending the templated URL paths of It is RECOMMENDED to consider all Operation Objects from all parsed documents when resolving any Link Object `operationId`. This requires ensuring that all referenced documents have been parsed prior to determining an `operationId` to be unresolvable. -The implicit connections in the Security Requirement Object and Discriminator Object rely on the _component name_, which is the property name holding the component in the appropriate typed sub-object of the Components Object. +The implicit connections in the Security Requirement Object and Discriminator Object rely on the _component name_, which is the property name holding the component in the appropriately typed sub-object of the Components Object. For example, the component name of the Schema Object at `#/components/schemas/Foo` is `Foo`. -The implicit connection of tags in the Operation Object use the `name` field of Tag Objects, which (like the Components Object) are found under the root OpenAPI Object. -This means that resolving component names and tag names both depend on starting from the correct OpenAPI Object. +The implicit connection of `tags` in the Operation Object use the `name` field of Tag Objects, which (like the Components Object) are found under the root OpenAPI Object. +This means resolving component names and tag names both depend on starting from the correct OpenAPI Object. For resolving component and tag name connections from a referenced (non-entry) document, it is RECOMMENDED that tools resolve from the entry document, rather than the current document. This allows Security Scheme Objects and Tag Objects to be defined with the API's deployment information (the top-level Server Objects), and treated as an interface for referenced documents to access. From b42fa95a191572e2321f9a86efc6eada870363c1 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Sat, 8 Jun 2024 13:27:01 -0700 Subject: [PATCH 4/9] More review feedback. --- versions/3.1.1.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index 0d88a63f37..72b0bf7a46 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -196,7 +196,7 @@ If the same JSON/YAML object is parsed multiple times and the respective context Several features of this specification require resolution of non-URI-based connections to some other part of the OpenAPI Description (OAD). `` -These connections are easily resolved in single-document OADs, but the resolution process in multi-document OADs has never been spelled out, and is therefore _implementation-defined_, within the constraints described in this section. +These connections are unambiguously resolved in single-document OADs, but the resolution process in multi-document OADs is _implementation-defined_, within the constraints described in this section. In some cases, an unambiguous URI-based alternative is available, and OAD authors are RECOMMENDED to always use the alternative: Source | Target | Alternative @@ -206,14 +206,15 @@ Source | Target | Alternative [Operation Object](#operationObject) `tags` | [Tag Object](#tagObject) `name` (in the Components Object) | _n/a_ [Link Object](#linkObject) `operationId` | [Path Item Object](#pathItemObject) `operationId` | `operationRef` -A fifth implicit connection, which involves appending the templated URL paths of the [Paths Object](#pathsObject) to the appropriate [Server Object](#serverObject)'s `url` field, is unambiguous because only the entry document's Paths Object contributes URLs to the described API. +A fifth implicit connection involves appending the templated URL paths of the [Paths Object](#pathsObject) to the appropriate [Server Object](#serverObject)'s `url` field. +This is unambiguous because only the entry document's Paths Object contributes URLs to the described API. It is RECOMMENDED to consider all Operation Objects from all parsed documents when resolving any Link Object `operationId`. -This requires ensuring that all referenced documents have been parsed prior to determining an `operationId` to be unresolvable. +This requires parsing all referenced documents prior to determining an `operationId` to be unresolvable. The implicit connections in the Security Requirement Object and Discriminator Object rely on the _component name_, which is the property name holding the component in the appropriately typed sub-object of the Components Object. For example, the component name of the Schema Object at `#/components/schemas/Foo` is `Foo`. -The implicit connection of `tags` in the Operation Object use the `name` field of Tag Objects, which (like the Components Object) are found under the root OpenAPI Object. +The implicit connection of `tags` in the Operation Object uses the `name` field of Tag Objects, which (like the Components Object) are found under the root OpenAPI Object. This means resolving component names and tag names both depend on starting from the correct OpenAPI Object. For resolving component and tag name connections from a referenced (non-entry) document, it is RECOMMENDED that tools resolve from the entry document, rather than the current document. @@ -221,7 +222,7 @@ This allows Security Scheme Objects and Tag Objects to be defined with the API's The interface approach can also work for Discriminator Objects and Schema Objects, but it is also possible to keep the Discriminator Object's behavior within a single document using the relative URI-reference syntax of `mapping`. -There currently are no URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field. +There are no URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field. These limitations are expected to be addressed in a future release. Note that no aspect of implicit connection resolution changes how [URIs are resolved](#relativeReferencesURI), or restricts their possible targets. From 59148a2951b94ad9098d90a6dd6072ec199fd4f2 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 10 Jun 2024 17:01:29 -0700 Subject: [PATCH 5/9] Add example resolution of Security Requirement --- versions/3.1.1.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index 72b0bf7a46..fef4ebd8c1 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -225,6 +225,9 @@ The interface approach can also work for Discriminator Objects and Schema Object There are no URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field. These limitations are expected to be addressed in a future release. +See [Security Requirement in a Referenced Document](#security-requirement-in-a-referenced-document) for an example of the possible resolutions, including which one is recommended by this section. +The behavior for Discrimator Object non-URI mappings and for the Operation Object's `tags` field operate on the same principles. + Note that no aspect of implicit connection resolution changes how [URIs are resolved](#relativeReferencesURI), or restricts their possible targets. ### Data Types @@ -3826,6 +3829,41 @@ security: - read:pets ``` +###### Security Requirement in a Referenced Document + +See [Resolving Implicit Connections](#resolvingImplicitConnections) for more information. + +Entry document `openapi.yaml`: + +```YAML +components: + securitySchemes: + MySecurity: + type: http + scheme: bearer + bearerFormat: JWT +paths: + /foo: + $ref: "other.yaml#/components/pathItems/Foo" +``` + +Referenced document `other.yaml`: + +```YAML +components: + securitySchemes: + MySecurity: + type: http + scheme: basic + pathItems: + Foo: + get: + security: + - MySecurity: [] +``` + +In this example, it is implementation-defined whether the Security Requirement for "MySecurity" in `other.yaml` resolves to `other.yaml#/components/securitySchemes/MySecurity` or the RECOMMENDED resolved location of `openapi.yaml#/components/securitySchemes/MySecurity`. + ### Specification Extensions While the OpenAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points. From 73d3d335d605855442ae22b8b8a942fd15c83b2f Mon Sep 17 00:00:00 2001 From: Henry Andrews Date: Tue, 11 Jun 2024 07:59:07 -0700 Subject: [PATCH 6/9] Fix stray random characters (review feedback) Co-authored-by: Ralf Handl --- versions/3.1.1.md | 1 - 1 file changed, 1 deletion(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index fef4ebd8c1..f0eeafacde 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -194,7 +194,6 @@ If the same JSON/YAML object is parsed multiple times and the respective context #### Resolving Implicit Connections Several features of this specification require resolution of non-URI-based connections to some other part of the OpenAPI Description (OAD). -`` These connections are unambiguously resolved in single-document OADs, but the resolution process in multi-document OADs is _implementation-defined_, within the constraints described in this section. In some cases, an unambiguous URI-based alternative is available, and OAD authors are RECOMMENDED to always use the alternative: From f5307502c7ed8ad874cfab0c1dd644ea96f29455 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 11 Jun 2024 09:33:42 -0700 Subject: [PATCH 7/9] example as YAML/JSON via HTTP negotiation --- versions/3.1.1.md | 73 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index f0eeafacde..467b94ff25 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -3832,9 +3832,38 @@ security: See [Resolving Implicit Connections](#resolvingImplicitConnections) for more information. -Entry document `openapi.yaml`: +First, our entry document is where parsing begins. It defines the `MySecurity` security scheme to be JWT-based, and it defines on Path Item as a reference to a component in another document: -```YAML +```HTTP +GET /api/description/openapi HTTP/1.1 +Host: www.example.com +Accept: application/openapi+json +``` + +```json +"components": { + "securitySchemes": { + "MySecurity": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + } +}, +"paths": { + "/foo": { + "$ref": "other#/components/pathItems/Foo" + } +} +``` + +```HTTP +GET /api/description/openapi HTTP/1.1 +Host: www.example.com +Accept: application/openapi+yaml +``` + +```yaml components: securitySchemes: MySecurity: @@ -3843,12 +3872,44 @@ components: bearerFormat: JWT paths: /foo: - $ref: "other.yaml#/components/pathItems/Foo" + $ref: "other#/components/pathItems/Foo" ``` -Referenced document `other.yaml`: +Next, we have our referenced document, `other`, that we presumably request in the same format we requested for the entry document. But the fact that we don't use file extensions gives the client the flexibilty to choose on a resource-by-resource basis, assuming both representations are available: -```YAML +```HTTP +GET /api/description/other HTTP/1.1 +Host: www.example.com +Accept: application/openapi+json +``` + +```json +"components": { + "securitySchemes": { + "MySecurity": { + "type": "http", + "scheme": "basic" + } + }, + "pathItems": { + "Foo": { + "get": { + "security": [ + "MySecurity": [] + ] + } + } + } +} +``` + +```HTTP +GET /api/description/other HTTP/1.1 +Host: www.example.com +Accept: application/openapi+yaml +``` + +```yaml components: securitySchemes: MySecurity: @@ -3861,7 +3922,7 @@ components: - MySecurity: [] ``` -In this example, it is implementation-defined whether the Security Requirement for "MySecurity" in `other.yaml` resolves to `other.yaml#/components/securitySchemes/MySecurity` or the RECOMMENDED resolved location of `openapi.yaml#/components/securitySchemes/MySecurity`. +In this `other` document, the reference path item has a Security Requirement for the Security Scheme "MySecurity". But there is a Security Scheme by that name in the `other` document as well. As discussed in [Resolving Implicit Connections](#resolvingImplicitConnections), which "MySecurity" gets used is [implementation-defined](#undefinedAndImplementationDefinedBehavior). However, as also documented in that section, it is RECOMMENDED that tools resolve component names from the [entry document](#documentStructure). As with all implementation-defined behavior, it is important to check tool documentation to determine which behavior is supported. ### Specification Extensions From 0555074d8b9692520438987cdfd99bd228d85901 Mon Sep 17 00:00:00 2001 From: Henry Andrews Date: Tue, 11 Jun 2024 11:19:26 -0700 Subject: [PATCH 8/9] Formatting fix (review feedback) Co-authored-by: Ralf Handl --- versions/3.1.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index 467b94ff25..33b08f81fc 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -3895,7 +3895,7 @@ Accept: application/openapi+json "Foo": { "get": { "security": [ - "MySecurity": [] + "MySecurity": [] ] } } From d2b0fe98d69e178fe8dd7437b68d762b562cf90d Mon Sep 17 00:00:00 2001 From: Henry Andrews Date: Wed, 12 Jun 2024 10:03:00 -0700 Subject: [PATCH 9/9] Apply suggestions from code review Co-authored-by: Jeremy Fiel <32110157+jeremyfiel@users.noreply.github.com> --- versions/3.1.1.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/versions/3.1.1.md b/versions/3.1.1.md index 33b08f81fc..ba2f17bf01 100644 --- a/versions/3.1.1.md +++ b/versions/3.1.1.md @@ -3832,7 +3832,7 @@ security: See [Resolving Implicit Connections](#resolvingImplicitConnections) for more information. -First, our entry document is where parsing begins. It defines the `MySecurity` security scheme to be JWT-based, and it defines on Path Item as a reference to a component in another document: +First, our entry document is where parsing begins. It defines the `MySecurity` security scheme to be JWT-based, and it defines a Path Item as a reference to a component in another document: ```HTTP GET /api/description/openapi HTTP/1.1 @@ -3875,7 +3875,7 @@ paths: $ref: "other#/components/pathItems/Foo" ``` -Next, we have our referenced document, `other`, that we presumably request in the same format we requested for the entry document. But the fact that we don't use file extensions gives the client the flexibilty to choose on a resource-by-resource basis, assuming both representations are available: +Next, we have our referenced document, `other`. The fact that we don't use file extensions gives the client the flexibility to choose an acceptable format on a resource-by-resource basis, assuming both representations are available: ```HTTP GET /api/description/other HTTP/1.1 @@ -3922,7 +3922,7 @@ components: - MySecurity: [] ``` -In this `other` document, the reference path item has a Security Requirement for the Security Scheme "MySecurity". But there is a Security Scheme by that name in the `other` document as well. As discussed in [Resolving Implicit Connections](#resolvingImplicitConnections), which "MySecurity" gets used is [implementation-defined](#undefinedAndImplementationDefinedBehavior). However, as also documented in that section, it is RECOMMENDED that tools resolve component names from the [entry document](#documentStructure). As with all implementation-defined behavior, it is important to check tool documentation to determine which behavior is supported. +In the `other` document, the referenced path item has a Security Requirement for a Security Scheme, `MySecurity`. The same Security Scheme exists in the original entry document. As outlined in [Resolving Implicit Connections](#resolvingImplicitConnections), `MySecurity` is resolved with an [implementation-defined behavior](#undefinedAndImplementationDefinedBehavior). However, documented in that section, it is RECOMMENDED that tools resolve component names from the [entry document](#documentStructure). As with all implementation-defined behavior, it is important to check tool documentation to determine which behavior is supported. ### Specification Extensions