Skip to content
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

Alternative: Clarify resolving implicit connections (3.1.1- alternative to #3823) #3856

Merged
merged 9 commits into from
Jun 13, 2024

Conversation

handrews
Copy link
Member

@handrews handrews commented May 25, 2024

This is an alternative approach to the one in PR #3823

The other PR pushes users more towards document-oriented resolution, which is what I personally prefer. But it only works if the documents are self-contained, and the way people organize multi-document OADs based on 2.0 conventions does not work with it. So the other PR provides two different approaches depending on how the OAD is structured. That's a bit complicated.

This PR advises one approach: resolve implicit connections from the entry document, and use URI-based alternatives to resolve locally.

This works because the ones where you are most likely to want local connections both have URI-based alternatives, while the ones without URI-based alternatives arguably make more sense associated with the API deployment, which is handled by the entry document:

  • local connections:
    • Discriminator Objects are used with hierarchies that are likely to be defined together, and mapping supports URIs
    • Link Objects need to worry about operationId collisions across multiple documents, and operationRef is a URI-based alternative that does that
  • deployment interface:
    • Security Requirement Objects linking to deployment-specific Security Schemes (using the component name as interface)
    • Operation Objects tagging based on deployment-specific Tag Object definitions, as the organization of operations is probably more of a deployment-specific concern (and tags that don't match tag objects still work as tags, they just don't come with ordering information or metadata)

I think we would want to still provide the missing URI-based alternatives in 3.2 because sometimes you will want to package up a set of Tag Objects or Security Schemes+Requirements. We in fact have issues open for both of those things.

But this is a more straightforward option, even if I'd prefer the self-contained document approach.


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

@handrews handrews requested a review from a team May 25, 2024 16:58
@handrews handrews marked this pull request as draft May 25, 2024 16:58
@handrews handrews added clarification requests to clarify, but not change, part of the spec re-use: ref/id resolution how $ref, operationId, or anything else is resolved labels May 25, 2024
@handrews handrews added the re-use: globals/defaults Default or global components that can be overridden in some way label May 25, 2024
@handrews handrews added this to the v3.1.1 milestone May 25, 2024
Copy link
Contributor

@ralfhandl ralfhandl left a comment

Choose a reason for hiding this comment

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

+1, with formulation proposal

versions/3.1.1.md Outdated Show resolved Hide resolved
@ralfhandl
Copy link
Contributor

I prefer this alternative over #3823.

ralfhandl
ralfhandl previously approved these changes May 28, 2024
@lornajane
Copy link
Contributor

A good discussion about this in TSC this week. Examples might be findable in https://github.com/OAI/oascomply/tree/main/reports to illustrate this point.

Copy link
Contributor

@jeremyfiel jeremyfiel left a comment

Choose a reason for hiding this comment

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

I've updated the text to clarify understanding and use cohesive terminology, throughout.


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.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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 easily resolved in single-document OADs, but the resolution process is _undefined_ in multi-document OADs. Therefore, implementation is defined within the constraints described in this section.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is not how we are using "undefined", which means "while some tools might do something here you cannot rely on it even being correct, except maybe by coincidence", while "implementation-defined" means "there are multiple correct alternatives, so you can't expect interoperability, but you can expect correct results."

[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.
Copy link
Contributor

Choose a reason for hiding this comment

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

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

Copy link
Member Author

Choose a reason for hiding this comment

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

@jeremyfiel I feel like, the extra comma, reads like, a Shatner, comma. 😉 Is there a specific grammar rule you're applying here?

More seriously, all of this section is about implicit connections, so a "fifth implicit connection" is no different from a "fifth connection". "implicit" is not a modifier to be set off in contrast to other connections, but an inherent part of the concept being named (of which there are five).

However, "involves appending the... to the.. url field" is a non-essential clause being set off from the sentence that otherwise stands on its own ("A fifth implicit connection is unambiguous because...") So it gets commas around it and a conjunction to introduce it.

Copy link
Member Author

Choose a reason for hiding this comment

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

I ended up taking your suggestion of splitting the sentence and removed all commas and "which" in the first sentence as I think that is correct and then we don't need to debate complex sentence structure.

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.
Copy link
Contributor

@jeremyfiel jeremyfiel Jun 6, 2024

Choose a reason for hiding this comment

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

Suggested change
This requires ensuring that all referenced documents have been parsed prior to determining an `operationId` to be unresolvable.
This requires all referenced documents to be parsed prior to determining an `operationId` unresolvable.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this still needs either a "that" before "all" or a "to" before "have". I'm fine with removing "ensuring", though.

Copy link
Contributor

Choose a reason for hiding this comment

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

as a native speaker, I don't know enough rules to argue for or against it. haha

I think this may sound better

versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Show resolved Hide resolved

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.
Copy link
Contributor

@jeremyfiel jeremyfiel Jun 6, 2024

Choose a reason for hiding this comment

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

Suggested change
There currently are no URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field.
Currently, there are no URI-based alternatives for the Security Requirement Object or the Operation Object `tags` field.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm... I wonder how to best make the intent more clear here.

In this sentence, the structure is making a distinction between the Security Requirement Object (as a whole, or more precisely all top-level keys in the Object) and the specific tags field in the Operation Object. Your rewrite reads to me like both the Operation Object and Security Requirement Object have tags fields, which is not the case.

Copy link
Contributor

Choose a reason for hiding this comment

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

you're right, that does seem to infer both of them have the tags. I added a the in there.. Not sure if that is sufficient.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it needs the repeated "for." I did remove the "currently", though.

versions/3.1.1.md Show resolved Hide resolved
versions/3.1.1.md Outdated Show resolved Hide resolved
Copy link
Member Author

@handrews handrews left a comment

Choose a reason for hiding this comment

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

@jeremyfiel I appreciate you going over this for consistency! We will need an effort like this on a larger scale before publishing, and I hope we can build up a style guide, which perhaps you could help with?

I've replied to a few where I interpret grammatical rules differently, or see other precedents in the existing text, or just think the sentence was unclear to start with which led you to fix the grammar in the "wrong" direction. But I appreciate this feedback and am merging several other comments.


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.
Copy link
Member Author

Choose a reason for hiding this comment

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

This is not how we are using "undefined", which means "while some tools might do something here you cannot rely on it even being correct, except maybe by coincidence", while "implementation-defined" means "there are multiple correct alternatives, so you can't expect interoperability, but you can expect correct results."

[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.
Copy link
Member Author

Choose a reason for hiding this comment

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

@jeremyfiel I feel like, the extra comma, reads like, a Shatner, comma. 😉 Is there a specific grammar rule you're applying here?

More seriously, all of this section is about implicit connections, so a "fifth implicit connection" is no different from a "fifth connection". "implicit" is not a modifier to be set off in contrast to other connections, but an inherent part of the concept being named (of which there are five).

However, "involves appending the... to the.. url field" is a non-essential clause being set off from the sentence that otherwise stands on its own ("A fifth implicit connection is unambiguous because...") So it gets commas around it and a conjunction to introduce it.

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.
Copy link
Member Author

Choose a reason for hiding this comment

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

I think this still needs either a "that" before "all" or a "to" before "have". I'm fine with removing "ensuring", though.

versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Show resolved Hide resolved

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.
Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm... I wonder how to best make the intent more clear here.

In this sentence, the structure is making a distinction between the Security Requirement Object (as a whole, or more precisely all top-level keys in the Object) and the specific tags field in the Operation Object. Your rewrite reads to me like both the Operation Object and Security Requirement Object have tags fields, which is not the case.

versions/3.1.1.md Show resolved Hide resolved
@handrews
Copy link
Member Author

handrews commented Jun 8, 2024

@jeremyfiel I've updated several areas that you commented on with changes that I think address your concerns in slightly different ways. There are a few I have not (yet) changed, pending your replies. I've also rebased the branch to resolve merge conflicts - while I had to force-push that, my latest changes are a separate commit if you want to look at them specifically.

ralfhandl
ralfhandl previously approved these changes Jun 10, 2024
@ralfhandl
Copy link
Contributor

a Shatner, comma

Amazing, the things I learn here 😁

handrews and others added 5 commits June 10, 2024 17:02
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.
Co-authored-by: Ralf Handl <ralf.handl@sap.com>
Co-authored-by: Jeremy Fiel <32110157+jeremyfiel@users.noreply.github.com>
@handrews
Copy link
Member Author

I have now added an example of resolving a Security Requirement in a referenced document. I am hoping that is sufficient and we don't need examples of everything.

Copy link
Contributor

@ralfhandl ralfhandl left a comment

Choose a reason for hiding this comment

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

+1, minor nits

versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Show resolved Hide resolved
versions/3.1.1.md Show resolved Hide resolved
Copy link
Contributor

@lornajane lornajane left a comment

Choose a reason for hiding this comment

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

I think the example works well, but must we provide that in JSON and YAML?

Co-authored-by: Ralf Handl <ralf.handl@sap.com>
@handrews
Copy link
Member Author

@lornajane we usually do but sometimes do not. I suppose I can add it.

@handrews
Copy link
Member Author

handrews commented Jun 11, 2024

@lornajane I remember why I didn't want to add the JSON It annoys me every time I see a $ref with a file extension but I know other people are baffled by omitting them. To me, showing a YAML example with a $ref: other.yaml and a JSON example with "$ref": "other.json" is a horrible anti-pattern as the whole point of supporting either format is to have the references work the same either way. So to make myself less frustrated with it I decided to just do one.

I really want either both references to be to just plain other, or there to only be one format. Doing both with a rewritten reference for the file extension... if folks insist I might be able to do it when I'm more awake. But I just think it's a really bad anti-pattern and I don't know what to do about that. ¯\(ツ)

Maybe I could frame it as HTTP content negotiation? This is the version you get with Accept: application/openapi+json and this is the version you get with Accept: application/openapi+yaml? That might make it palatable to the super-literal-URL-with-local-files faction? I realize I'm probably being unreasonably dogmatic... but it's also kind-of the entire point of the URI vs URL sections so maybe we should leverage that?

@ralfhandl
Copy link
Contributor

both references to be to just plain other

I like that!

@handrews
Copy link
Member Author

@lornajane @ralfhandl I've expanded the examples with both JSON and YAML showing the HTTP requests with Accept that produce the representation without file extensions.

Copy link
Contributor

@ralfhandl ralfhandl left a comment

Choose a reason for hiding this comment

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

Very nice!

versions/3.1.1.md Outdated Show resolved Hide resolved
Co-authored-by: Ralf Handl <ralf.handl@sap.com>
ralfhandl
ralfhandl previously approved these changes Jun 12, 2024
Copy link
Contributor

@jeremyfiel jeremyfiel left a comment

Choose a reason for hiding this comment

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

couple nits on the language.

I'm not a huge proponent of the conversational text, especially for a spec. But I won't rewrite the whole thing. :)

versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Outdated Show resolved Hide resolved
versions/3.1.1.md Outdated Show resolved Hide resolved
Co-authored-by: Jeremy Fiel <32110157+jeremyfiel@users.noreply.github.com>
@handrews
Copy link
Member Author

handrews commented Jun 12, 2024

@jeremyfiel

I'm not a huge proponent of the conversational text, especially for a spec. But I won't rewrite the whole thing. :)

That's an editing thing rather than a writing thing. With these PRs the point is to get the information in the spec.

In an ideal world someone like you who has a good eye for editing would go over everything and do wordsmithing. I do not care if my writing style is retained, as long as we first get the content in that I can provide (and no one else is currently both willing and able to do), and then worry about the style.

And preferably make a style guide! It would make it so much easier to add text if we had one.

But for just getting the content in- whoever does the work gets to determine how it's written up, especially when there's no style guide. And if someone wants to do an editing pass before publishing- I'm all for it.

@handrews
Copy link
Member Author

@jeremyfiel also, I tend to write more conversationally for examples, and less so for definitions. My preference would be to integrate the spec and the Learn site more closely and move most examples to the Learn site, which would have a different tone. But for now, people expect to find the examples in the spec, and (up to a point) we need to put some there. I struggle with where to draw the line on what goes in or doesn't – for now it's been "apparently I'm the one writing the PRs so the line is where I say it is", but that's not a viable policy long-term and leads to questions like in #3874.

@ralfhandl
Copy link
Contributor

Not merging, waiting for @jeremyfiel to approve the latest changes

@ralfhandl
Copy link
Contributor

@lornajane Please confirm whether the text now has sufficient examples.

Copy link
Contributor

@lornajane lornajane left a comment

Choose a reason for hiding this comment

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

Thanks for getting into the weeds to get this under control!

@lornajane lornajane merged commit e5b92d0 into OAI:v3.1.1-dev Jun 13, 2024
1 check passed
@handrews handrews deleted the implicit-alt-311 branch June 13, 2024 17:34
ralfhandl added a commit that referenced this pull request Jun 17, 2024
Resolving implicit connections (3.0.4 port of #3856)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clarification requests to clarify, but not change, part of the spec re-use: globals/defaults Default or global components that can be overridden in some way re-use: ref/id resolution how $ref, operationId, or anything else is resolved
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants