Managing SAF versions in an OAD #5350
handrews
started this conversation in
Enhancements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I had thought this was going to be very difficult, but after writing up a great deal of complicated exploration, it distilled down to something quite simple. The length here is due to showing several examples to handle different possible outcomes of #5349.
There are a few things to solve here:
Informing about versions
Versions and publications
Deciding on the publication mechanisms and related version granularity is taking place in discussion #5349.
This document assumes that SAFs are versioned somehow, and discusses both proposed possibilities of individual SAF versioning or SIG-level SAF group versioning. For this discussion, it doesn't matter if these versions come from registry entries, formal specifications, or some mix of things.
Semantic versioning
Semantic versioning (semver) is assumed, for reasons . While I have had my concerns with semver and specifications in the past, with SAFs we are moving more towards a standard library (the OAS proper) plus additional libraries (SAFs, or SIG-granularity SAF collections), which is the sort of versioning interaction semver was designed to support.
Declaring versions in a document
We currently have two specification versions that we declare in document-scoped fields in the OpenAPI Object:
openapifor the OAS versionjsonSchemaDialectfor the JSON Schema dialect, which includes dialects from different drafts/versions; this has a default value if absentWe need to also declare SAF versions to ensure correct parsing and conflict detection, as will be seen further down.
The simplest thing to do would be to add a field where the SAFs in use in the document are listed, together with their versions. The names of the SAFs would be provided by each SAF's specification. This field could be called something like
featureVersions,usingFeatures, etc. (just notfeaturesas we proably want to reserve that for the actual SAF Objects). PerhapsusingFeatureGroupsif the usage is at the SIG granularity.SAF-granularity example
If we have versioning at the SAF granularity (regardless of whether any of them are grouped into the same specification document), it could look something like:
Pros:
Cons:
SIG-granularity example, explicit SAFs
If we want to have SIG-granularity specifications using only explicitly listed SAFs (and not allow mixing SAFs from different versions of the same specification), we could have something like this:
You'll notice
regsitrywhich is where the experimental/3rd-party SAFs, which I'm assuming here are versioned individually, live. There are various possibilities here depending on the granularity of registered SAFs, but this example shows that a hybrid approach is possible.Pros:
Cons:
If SAFs within a SIG grouping interact with each other, allowing individual SAF enabling / disabling might allow users to shoot themselves in the foot. However, we could just make it clear which ones do that and mandate that if tools don't see the right dependencies, they MUST raise an error.
SIG-granularity example, all SAFs in each SIG assumed active
In this approach, using a SAF group means all SAFs are considered to be in use:
Note that we still need the
registryfield as individually registered SAFs wouldn't have a group to list.Pros:
Cons:
This shifts more responsibility away from the tools and to the OAD author, which feels a bit questionable to me.
To make the "con" more concrete, let's say you included the
httpSAF group specification because you wanted its cache control feature, but your API also uses rate limiting. But your rate limiting usage is very simple so you just want to use aconstschema for theRateLimit-Policyresponse header (assuming we allowheadersat the API scope as discussed in #5314, just to make this example easier):This would cause a problem because using the Rate Limiting SAF (implicitly included in the
httpgroup) creates an exception for theRateLimit-Policyheader. If we fail-fast (see below), this is not too bad. The OAD author may have wasted some effort and need to refactor, but it would be clear how to do so. But this would remove some flexibility.Detecting and reporting conflicts
Fail-fast
When introducing this amount of complexity, the best UX is for conflicts between SAFs and the "regular" way of doing things to immediately cause a clear error.
This is not what happens today with Security Schemes. You can have an
in: header, name: Authorizationparameter and it is silently ignored. Multiple of us in a recent TDC call affirmed that this has led to production OADs that have this error, without OAD authors realizing the problem at all.Let's never do this again, please.
Document scope conflict checking
The
openapiandjsonSchemaDialectfields are document-scoped, sousingFeature[Group]s(or whatever we call it) needs to be as well. The document is the unit of parsing, so this is the only thing that really makes sense (see farther down for how this works with multi-document OADs).Each SAF would specify what exceptions it creates and how to handle them. For example, the Rate Limiting SAF might specify that it
RateLimit-PolicyandRateLimitheadersThis example assumes
headersis available at all levels as proposed (but not necessarily agreed-to) in #5314.First, let's look at it without SAFS:
With SAFs in use, but not changing the rest of the OAD.
Using SAFs correctly, assuming a
featuresfield at multiple levels (levels per #5314) — please do not take this syntax too seriously, I just made it up right now:Handling multiple documents and versions
For OAS 3.2, we decided that since updating from 3.1 is so trivial (aside from extensions), we did not need to specify how to mix 3.1 and 3.2 documents in the same OAD.
With SAFs, the simplest thing to do, and perhaps where we should start even if we revisit it before shipping 3.3, is to just require that all major and minor (X.Y) versions across an OAD match exactly (except JSON Schema dialects, which are already well-defined for cross-version behavior).
X.Yin theiropenapi: X.Y.ZfieldAnything else MUST be treated as an error.
I have thoughts on how we could handle multiple compatible versions, but let's discuss that separately if/when we think it's reasonable to add. We are already adding complexity by allowing SAFs to version more-or-less independently. And initially, we won't have a bunch of versions of the same SAF anyway.
Beta Was this translation helpful? Give feedback.
All reactions