Repository navigation
Deterministic diff output, a sunset-aware deprecation lifecycle, and the OAuth flows that were never checked
oasdiff diff now returns the same output on every run of the same comparison. Removing a deprecated request or response property follows its x-sunset date instead of reporting a plain removal. The OAuth security checks cover all four flows rather than only implicit, and compare URLs by meaning. Two crashes are fixed. This is the same code as v1.35.0-rc.1.
CLI changes
Deterministic output
diffreturns the same output on every run (#1335). Parts of the diff were built by ranging over a map, and Go randomizes map iteration, so the order of added, deleted and modified entries moved between runs of the same comparison. Every map-based diff now goes through one helper that returns sorted lists, paths are listed by path then method,requiredandtypelists are sorted, the YAMLendpointssection is sorted, and an added and deleted media type that are equivalent are paired the same way every run. A new test compares 284 fixture pairs ten times each and requires identical JSON and YAML.- The duplicate endpoint error names both paths and how to fix it (#1336). It used to name one of the two clashing paths, picked at random, without saying what it clashed with. It now reports both paths with the file each came from, the same pair on every run, and suggests
--include-path-params. Thex-since-dateerror got the same treatment.
Deprecation
- Removing a deprecated property follows its sunset date (#1305, thanks @BogdanYarotsky). Request properties and required response properties now use the lifecycle that parameters and endpoints already had: removing a deprecated property with no
x-sunsetreportsrequest-property-removed-with-deprecationorresponse-required-property-removed-with-deprecationat info, removing one before its sunset date reportsrequest-property-removed-before-sunsetorresponse-required-property-removed-before-sunsetat error, and removing one after its sunset date is not reported. A sunset date that cannot be parsed keeps the plain removal id, since the deprecation checks already report the bad date.
Security schemes
- All four OAuth flows are checked (#1328). The checks read only the
implicitflow, so changes toauthorizationCode,passwordandclientCredentialswere never reported: moving anauthorizationCodeflow's URLs to another host and dropping one of its scopes gave "No changes to report". Every URL and scope finding now names its flow, since the same scope can appear in two flows of one scheme, andapi-security-component-oauth-refresh-url-changedis new. - Security scheme URLs are compared by meaning (#1328).
https://Login.Example.com:443/tokenandhttps://login.example.com/tokenare no longer reported as a change. The comparison follows RFC 3986: case in the scheme and host, a default port, an empty path, and percent-encoding of unreserved characters are all equivalent. The four URL checks now share one level,warning, with a comment explaining the verdict;api-security-component-openid-connect-url-changedwas an error, and the authorization and token URL checks were info.
Crashes
x-extensible-enumwith numeric values no longer panics (#1343). An integer parameter or property written asx-extensible-enum: [1, 2]crashedbreakingandchangelogwhen a value was removed, because the items were read as strings. A removed number is now reported like any other removed value.- A self-referencing callback no longer overflows the stack (#1344). A callback whose operation carries the same callback recursed until the stack overflowed, even when a spec was compared with itself.
diff,breaking,changelogandsummaryare all fixed, and each change is reported once, where the callback is first compared.
External $refs
- One exit code for a refused external
$ref(#1354). With--allow-external-refs=false, a refused$refexited 123 when oasdiff's own reader was installed, which--opendoes, and 102 otherwise, so a CI step keying off the code could not reliably offer the remedy. Both paths now exit 123, and the two forms of the refusal are recognized by one predicate. - The capture reader applies the policy by default (#1347, #1352). The reader
--openinstalls now refuses an external$refbefore any read, and a call site that does not name a document gets the policy rather than silently getting none. The fix itself shipped in v1.34.1 and is published as GHSA-6h5x-f3qr-cp23; what is new here is that the reader fails closed.
Misc
- kin-openapi v0.151.0 (#1332).
- Third-party actions are pinned by digest and workflow tokens are least-privilege (#1340, thanks @huguesducharme).
- A security policy (#1346), so a reporter has somewhere to send a finding.
Go package changes
- New
load.IsExternalRefDisallowed(err)(#1354). Answers for both refusal paths, oasdiff's reader and kin-openapi's own check, so a caller no longer has to match either form. The kin match is pinned by a test that runs the real loader, so a wording change upstream fails the test rather than silently reverting the behaviour. utils.StringSet.ToStringListreturns sorted values (#1335). This is what makes string-list diffs such asrequiredandtypedeterministic; a caller that relied on the previous arbitrary order now gets a stable one.- Four new checker ids (#1305):
RequestPropertyRemovedWithDeprecationId,RequestPropertyRemovedBeforeSunsetId,ResponseRequiredPropertyRemovedWithDeprecationId,ResponseRequiredPropertyRemovedBeforeSunsetId. Machine-readable output gains these ids, so a consumer matching on removal ids should expect them.