Skip to content

v3.3: First pass at explaining SAFs - #5447

Open
handrews wants to merge 2 commits into
OAI:v3.3-devfrom
handrews:safs
Open

handrews wants to merge 2 commits into
OAI:v3.3-devfrom
handrews:safs

Conversation

@handrews

@handrews handrews commented Jul 25, 2026 •

Copy link
Copy Markdown
Member

This PR is to get conversation started on how we want to explain SAFs in the OAS. I'm not particularly attached to it, but as we get the SIG/SAF repositories up and running, we should figure out how to explain this to readers.

  • schema changes are included in this pull request

3huss99-ui
3huss99-ui previously approved these changes Jul 25, 2026
@karenetheridge
karenetheridge dismissed 3huss99-ui’s stale review July 26, 2026 01:50

This user appears to be farming participation events, possibly for future spamming or attempts to inject vulnerabilities into tooling or content.

@handrews
handrews marked this pull request as ready for review August 9, 2026 19:34
@handrews
handrews requested review from a team as code owners August 9, 2026 19:34
@handrews

handrews commented Aug 9, 2026

Copy link
Copy Markdown
Member Author

Clean rebase force-push, no changes to commits. This is ready for review.

miqui
miqui previously approved these changes Aug 11, 2026

@miqui miqui left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looks good to me. Perhaps a few more examples?

Comment thread src/oas.md Outdated
| Field Name | Type | Description |
| ---- | :----: | ---- |
| <a name="oas-version"></a>openapi | `string` | **REQUIRED**. This string MUST be the [version number](#versions-and-deprecation) of the OpenAPI Specification that the OpenAPI document uses. The `openapi` field SHOULD be used by tooling to interpret the OpenAPI document. This is _not_ related to the [`info.version`](#info-version) string, which describes the OpenAPI document's version. |
| <a name="using-features"></a>usingFeatures | Map[`string`, `string`] | A map of [SAF](#standardized-api-features) names, as defined in various companion specifications, to a valid version string for the named SAF. Implementations MUST apply the SAF's rules, such as treating header parameters that are managed by the SAF as illegal in Parameter Objects, while processing the current document. The default is `{"legacySecurity": "3.3.0"}`. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What does this default value mean, and where is that meaning described?

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.

@ralfhandl oh, I don't think I meant to include this yet as it references something we have not decided, but the idea is:

  • We should move the existing Security Scheme, OAuth Flows, and OAuth Flow Objects to the SIG-Security specification and treat them as a SAF, which I was calling legacySecurity
  • For compatibility with OAS 3.2, if you don't explicitly set usingFeatures it assumes you are using the legacy security, as otherwise everyone's OAS 3.2 (or 3.1)-style security would break.
  • The 3.3.0 was me thinking that since the legacy security was coming from the original OAS specification revision stream, it should keep that numbering (implicitly, the security in past OAS versions could be considered a SAF with the matching version... why we'd want to do that idk, I'm just explaining my thought process).
  • The Security Requirement Object probably stays in the main OAS, although I think that will become clear one way or another as we work with stuff.

I am also happy to take this part (and anything else that suggests we've made a decision on security compatibility) out of this PR. We can add it back when we make a decision there.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanation, makes sense. Security evolves at a different speed than the core API description language.

I'd keep this out until it can be added with references to the new document describing security features.

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.

@ralfhandl I opted to explain it and add an example because I think this part of what we will discuss tomorrow. If we can't resolve it but want to merge the rest of this, I will take it out then.

@miqui

miqui commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

@handrews looks good. Can we add another example using more than one SAF?

usingFeatures:
  legacySecurity: 3.3.0
  lifeCycle: 1.0.0
$self: https://example.com/openapi
info:
  title: Example Pet Store App

@miqui

miqui commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

btw, i am open to other names for the life cycle SAF.

@handrews

handrews commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@miqui we need to figure out whether we're going to really do feature-level SAFs (as we originally decided) or specification-level SAFs (which would make the versioning story substantially easier; we could always go more complex later if there is demand.

Here's examples of it both ways (the exact SAF/specification names are unimportant right now).

The way we originally decided (rar is both OAuth Rich Authorization Requests and GNAP's Resource Access Rights — they were developed together with the same structure and acronym on purpose):

usingFeatures:
  legacySecurity: 3.3.0  # SIG-security, migrated from the OAS
  rar: 1.0.0             # SIG-security, enhancement to Security Requirements
  deprecation: 1.0.0.    # SIG-lifecycle
  sunset: 1.0.0          # SIG-lifecycle

Simplified: the version number is the version of the SIG specification, and you use the specification all-or-nothing.

usingFeatures:
  security: 1.0.0  # Includes legacy, RAR, anything else we add
  lifecycle: 1.0.0 # Includes sunset, deprecation, and anything else we add

@handrews

handrews commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Rebased the original commit unchanged and added a new commit in response to comments above.

@miqui

miqui commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Thanks @handrews for your feedback. I am going to nudge @ralfhandl to finish his review.

Comment thread src/oas.md
SAF or `openapi` version in a referenced document is not compatible
with the corresponding version in the entry document. Implementations
MAY raise an error if the major and minor versions are compatible but
not the same; otherise the behavior is implementation-defined.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
not the same; otherise the behavior is implementation-defined.
not the same; otherwise the behavior is implementation-defined.

Comment thread src/oas.md
| Field Name | Type | Description |
| ---- | :----: | ---- |
| <a name="oas-version"></a>openapi | `string` | **REQUIRED**. This string MUST be the [version number](#versions-and-deprecation) of the OpenAPI Specification that the OpenAPI document uses. The `openapi` field SHOULD be used by tooling to interpret the OpenAPI document. This is _not_ related to the [`info.version`](#info-version) string, which describes the OpenAPI document's version. |
| <a name="using-features"></a>usingFeatures | Map[`string`, `string`] | A map of [SAF](#standardized-api-features) names, as defined in various companion specifications, to a valid version string for the named SAF. Implementations MUST apply the SAF's rules, such as treating header parameters that are managed by the SAF as illegal in Parameter Objects, while processing the current document. The default is `{"legacySecurity": "3.3.0"}` (see below). |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
| <a name="using-features"></a>usingFeatures | Map[`string`, `string`] | A map of [SAF](#standardized-api-features) names, as defined in various companion specifications, to a valid version string for the named SAF. Implementations MUST apply the SAF's rules, such as treating header parameters that are managed by the SAF as illegal in Parameter Objects, while processing the current document. The default is `{"legacySecurity": "3.3.0"}` (see below). |
| <a name="using-features"></a>usingFeatures | Map[`string`, `string`] | A map of [SAF](#standardized-api-features) names, as defined in various companion specifications, to a valid version string for the named SAF. Implementations MUST apply the SAF's rules while processing the current document. The default is `{"legacySecurity": "3.3.0"}` (see below). |

I find this phrase hard to parse:

such as treating header parameters that are managed by the SAF as illegal in Parameter Objects

Does it mean that all parameters managed by a referenced SAF are illegal in Parameter Objects and their presence makes an OAD invalid?

@SensibleWood

Copy link
Copy Markdown

@miqui we need to figure out whether we're going to really do feature-level SAFs (as we originally decided) or specification-level SAFs (which would make the versioning story substantially easier; we could always go more complex later if there is demand.

Here's examples of it both ways (the exact SAF/specification names are unimportant right now).

The way we originally decided (rar is both OAuth Rich Authorization Requests and GNAP's Resource Access Rights — they were developed together with the same structure and acronym on purpose):

usingFeatures:
  legacySecurity: 3.3.0  # SIG-security, migrated from the OAS
  rar: 1.0.0             # SIG-security, enhancement to Security Requirements
  deprecation: 1.0.0.    # SIG-lifecycle
  sunset: 1.0.0          # SIG-lifecycle

Simplified: the version number is the version of the SIG specification, and you use the specification all-or-nothing.

usingFeatures:
  security: 1.0.0  # Includes legacy, RAR, anything else we add
  lifecycle: 1.0.0 # Includes sunset, deprecation, and anything else we add

@handrews my opinion on this is that the simplified version is the best match for how the discussion has evolved. My gut reaction on seeing rar as a feature is that this is too granular, and will take a lot of composition to manifest a bunch of features correctly.

Also rar doesn't really make sense on its own, as it should be considered in the context of something that implements it i.e. GNAP, OAuth, etc. It needs to be part of the wider security SAF to give it the right context i.e. this is used by a GNAP Object (however that manifests itself), this is used by an OAuth Profile Object, etc.

You could of course compose these relationships at a feature level, but then that requires a bunch of scaffolding that might be hard to maintain. Also humans would "probably" understand this stuff better as part of a larger "whole".

type: string
pattern: '^3\.3\.[0-9]+(-.+)?$'
usingFeatures:
type: object

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we want to add a propertyNames in this schema? In other words, do we want to constrain the names of SAFs and specify that 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.

nit: we'd have sigs instead of SAFs. Multiple Features (SAFs) are handled in a single area of interest (SIG).

No strong opposition to adding constraints close to programing languages variables

Comment thread src/oas.md

Occasionally, non-backwards compatible changes may be made in `minor` versions of the OAS where impact is believed to be low relative to the benefit provided.

### Standardized API Features

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This wording needs work but I think we should get the more difficult details in place and first and revisit before merging once we've got things more nailed down. (tl;dr on wording feedback: we could be clearer on problem/solution and remove some time references that won't age well)

@baywet

baywet commented Oct 8, 2026

Copy link
Copy Markdown
Member

Collecting some notes from the meeting

There's a general agreement that we should do SAF level entries, as opposed of feature level entries to reduce the overhead in terms of publishing etc...

So something closer to this to take the earlier examples

usingFeatures:
  security: 1.0.0  # Includes legacy, RAR, anything else we add
  lifecycle: 1.0.0 # Includes sunset, deprecation, and anything else we add

Additionally: we need to review the name usingFeatures to have a more explicit name.

And more people should review this pull request :)

Comment thread src/oas.md
Comment on lines +33 to +35
Many API features have behavior that is difficult or impossible to infer from
descriptions of paths, parameters, headers, or other operation elements that
this specification supports.

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.

@lornajane to provide a better wording suggestion :)

type: string
pattern: '^3\.3\.[0-9]+(-.+)?$'
usingFeatures:
type: object

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.

nit: we'd have sigs instead of SAFs. Multiple Features (SAFs) are handled in a single area of interest (SIG).

No strong opposition to adding constraints close to programing languages variables

Comment thread src/oas.md
| Field Name | Type | Description |
| ---- | :----: | ---- |
| <a name="oas-version"></a>openapi | `string` | **REQUIRED**. This string MUST be the [version number](#versions-and-deprecation) of the OpenAPI Specification that the OpenAPI document uses. The `openapi` field SHOULD be used by tooling to interpret the OpenAPI document. This is _not_ related to the [`info.version`](#info-version) string, which describes the OpenAPI document's version. |
| <a name="using-features"></a>usingFeatures | Map[`string`, `string`] | A map of [SAF](#standardized-api-features) names, as defined in various companion specifications, to a valid version string for the named SAF. Implementations MUST apply the SAF's rules, such as treating header parameters that are managed by the SAF as illegal in Parameter Objects, while processing the current document. The default is `{"legacySecurity": "3.3.0"}` (see below). |

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.

TODO: update the wording to SIG?

Comment thread src/oas.md
also illustrate another aspect of SAFs, which is that they often evolve
at a more rapid pace than the core of HTTP.

To better support security features and expand into other SAFs, the OpenAPI

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.

maybe add general guidance for discovery vs "constants" in the OpenAPI descriptions for things that are discoverable by nature? (or capture that for the SIGs later on)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants