Repository navigation
Conversation
… old and new values A changed name under components.securitySchemes for an apiKey scheme showed up only as an operation-level change with no line-level detail, and none of the incompatible.security.scheme.* options could disable the breaking verdict, because the parameter name was never part of the scheme diff. What: - SecuritySchemeDiff captures the parameter name change on apiKey schemes (changedName), gated by the new incompatible.security.scheme.apikey.name.changed option (default true, since clients keep sending the old parameter name). - SecurityRequirementDiff falls back to matching a requirement scheme by its component key when the parameter name no longer matches, so a rename is diffed as a scheme change instead of a deleted plus re-added requirement. - When a security requirement is newly added at some level, the schemes it references are now also diffed against the other spec's components, so definition changes are not lost; they are collected in the new ChangedSecurityRequirements#getChangedSchemes list and feed into the backward-compatibility verdict like any other changed element. - The console, markdown and html renderers print the collected scheme changes with old -> new values (markdown follows the same shape as OpenAPITools#933). Why: The reporter saw a bare changed-operation line with no indication of which field changed and no way to turn the rule off. How: The flag flows through ChangedSecurityScheme#isCoreChanged (incompatible by default via the new option), and the renderers read the old and new values from the old/new SecurityScheme objects the model already carries. Fixes OpenAPITools#802
There was a problem hiding this comment.
2 issues found across 17 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java">
<violation number="1" location="core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java:113">
P2: This loop can emit a duplicate or misattributed scheme change when the same OAuth2 component appears in both a matched requirement and a newly added requirement. Track scheme refs already handled by matched requirements, or avoid reusing the cached requirement-scoped result before adding it to `changedSchemes`.</violation>
</file>
<file name="core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java">
<violation number="1" location="core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java:310">
P2: Extension-only OAuth flow changes are reported by the diff but disappear from Markdown because this method returns empty without a URL change. Render the flow extension diff or otherwise include that change in the output.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
| "%s* refreshUrl: %s -> %s\n", | ||
| indent(2), url(oldFlow.getRefreshUrl()), url(newFlow.getRefreshUrl()))); | ||
| } | ||
| if (sb.length() == 0) { |
There was a problem hiding this comment.
P2: Extension-only OAuth flow changes are reported by the diff but disappear from Markdown because this method returns empty without a URL change. Render the flow extension diff or otherwise include that change in the output.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java, line 310:
<comment>Extension-only OAuth flow changes are reported by the diff but disappear from Markdown because this method returns empty without a URL change. Render the flow extension diff or otherwise include that change in the output.</comment>
<file context>
@@ -152,9 +156,167 @@ protected void listEndpoints(
+ "%s* refreshUrl: %s -> %s\n",
+ indent(2), url(oldFlow.getRefreshUrl()), url(newFlow.getRefreshUrl())));
+ }
+ if (sb.length() == 0) {
+ return "";
+ }
</file context>
| // in the other spec's components. Diff those definitions as well so that their changes | ||
| // (e.g. an apiKey scheme whose parameter name changed) are not lost. | ||
| if (changedSecurityRequirements.getIncreased() != null) { | ||
| Set<String> diffedSchemeRefs = new HashSet<>(); |
There was a problem hiding this comment.
P2: This loop can emit a duplicate or misattributed scheme change when the same OAuth2 component appears in both a matched requirement and a newly added requirement. Track scheme refs already handled by matched requirements, or avoid reusing the cached requirement-scoped result before adding it to changedSchemes.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java, line 113:
<comment>This loop can emit a duplicate or misattributed scheme change when the same OAuth2 component appears in both a matched requirement and a newly added requirement. Track scheme refs already handled by matched requirements, or avoid reusing the cached requirement-scoped result before adding it to `changedSchemes`.</comment>
<file context>
@@ -104,9 +106,46 @@ protected DeferredChanged<ChangedSecurityRequirements> diff(
+ // in the other spec's components. Diff those definitions as well so that their changes
+ // (e.g. an apiKey scheme whose parameter name changed) are not lost.
+ if (changedSecurityRequirements.getIncreased() != null) {
+ Set<String> diffedSchemeRefs = new HashSet<>();
+ for (SecurityRequirement increasedSecurity : changedSecurityRequirements.getIncreased()) {
+ for (Map.Entry<String, List<String>> entry : increasedSecurity.entrySet()) {
</file context>
DrSatyr
left a comment
There was a problem hiding this comment.
Thanks for working on #802. changedName and the new apikey.name.changed switch are the right direction, but the scheme matching needs fixing. An apiKey scheme has a component key (PAT) and a name (the header clients send). The expected results are:
- Key renamed,
namesame: no change (already works on master). - Same key,
namechanged:apikey.name.changed. This is #802. - Both changed: removed + added (
requirements.decreased). Don't guess renames. - New alternative requirement added: compatible.
Problems:
- Case 4 is now reported as breaking. The new block in
SecurityRequirementsDiffthat diffs schemes of added requirements should be dropped. It also diffs schemes whose type changed (name: Authorization -> null). - Match by key first, then by
name. The current order mispairs schemes when there are several apiKeys. - Please add a test per case and use valid fixtures (operation-level
security,PAT: []). The #802 files are malformed, and the issue isn't 3.1-specific. - Renderers: keeping console/Markdown/HTML in this PR is fine, but the Markdown part duplicates #933. Please rebase onto #933 once it's merged and build on its code. Also make the three consistent: show schemes added or removed within a requirement in console/HTML too, avoid the empty "Changed security scheme :" item in HTML, and fix the 4-space Markdown indent, which renders as a code block.
…ecurity renderers What: - SecurityRequirementDiff pairs a requirement scheme with the other spec by component key first and only falls back to the apiKey parameter name, so several apiKey schemes in one requirement are no longer mispaired by name (a parameter-name swap between two schemes was silently swallowed before). - SecurityRequirementsDiff no longer diffs the schemes referenced by newly added requirements; the ChangedSecurityRequirements#changedSchemes list is dropped with it. A new alternative security requirement is compatible and no longer reports the referenced schemes as changed. - SecuritySchemeDiff only compares the parameter name while the scheme is still an apiKey on the other side. - Console, html and markdown renderers all show schemes added to or removed from a changed requirement; the html "Changed security scheme" item is skipped when it has no displayable change and now also shows description changes; markdown security details use a two-space nested-list indent so they no longer render as an indented code block. Why: Maintainer review of the PR: matching by name first mispairs schemes when several apiKeys exist, a new alternative requirement was reported as breaking, and the renderers were inconsistent. How: Requirement-level matching is unchanged, so the verdicts still follow the existing options (incompatible.security.requirements.decreased, incompatible.security.requirement.schemes.increased, incompatible.security.scheme.apikey.name.changed). The four expected outcomes are each covered by tests with valid operation-level fixtures (apiKey requirement "PAT: []"): key renamed with same name (no change), same key with changed name (OpenAPITools#802), both changed (removed + added, no rename guessing), and a new alternative requirement (compatible). Signed-off-by: Inf1mum <vadimlazuk5@gmail.com>
Fixes #802
Reworked after the review on this PR (#939 (review) — DrSatyr, CHANGES_REQUESTED). The scheme matching was rebuilt around the reviewer's four-case spec and the renderers were made consistent.
Behavior per the review spec
An apiKey scheme has a component key (
PAT) and a parametername(the header/query/cookie clients send). Actual results on this branch, verified with the CLI on valid fixtures (operation-levelsecurity,PAT: []):namesameno_changesnamechangedChanged security scheme name: Authorization -> pat(the #802 case)incompatible.security.scheme.apikey.name.changed(defaulttrue, can be switched off)namechangedNew security scheme/Deleted security scheme), no rename guessedNew security requirement: petstore_auth: [read], nothing elsecompatibleWhat changed since the last push
SecurityRequirementDiff). The previous name-first order mispaired schemes when a requirement contains several apiKeys — e.g. a parameter-name swap between two schemes was silently swallowed. Case 3 (both changed) falls through both matchers and is reported as removed + added; no rename is ever guessed.SecurityRequirementsDiff), as requested. It reported case 4 as breaking (and mis-attributed type changes). TheChangedSecurityRequirements#changedSchemeslist was removed with it, which also eliminates the duplicate/misattributed-scheme-change risk in that loop.SecuritySchemeDiffonly compares the parameter name while the right-hand scheme is still an apiKey, so a same-key type change can no longer be reported as (and suppressed by) the apiKey-name rule.Changed security scheme :item is skipped when it has no displayable change, and description changes are now rendered there;* Changed security requirement:with* ...children) so they render as a list — the previous four-space indent rendered as an indented code block.Review notes
issue-802-api-key-1.yaml,issue-802-api-key-2.yaml→ valid operation-levelsecurity, emptyPAT: []), theSecurityRequirementDifffallback ordering (superseded by the key-first matching above), theSecuritySchemeDiffchangedNameguard (only apiKey→apiKey), theMarkdownRenderfour-space indent (now a proper nested list), theSecurityRequirementsDiffduplicate/misattributed-scheme loop (block removed entirely), the empty htmlChanged security schemeitem (suppressed, description now rendered), and the console missingNew security scheme/Deleted security schemelines (now rendered). Refuted: theMarkdownRenderextension-only OAuth flow issue (extension-only flow changes vanish from markdown) — the model only flags a flow as changed when a URL changes (ChangedOAuthFlow#isCoreChangedreturnsno_changesotherwise), and none of the renderers render extension diffs for security entities; rendering extension diffs is a separate feature, not something this PR introduced. Happy to take it in a follow-up.Verification
./mvnw testgreen: core 285 tests, cli 13 (baseline was core 277 + cli 13; +8 from the per-case tests). New per-case tests:SecurityDiffTest(case 1–4 plus a two-apiKey name-swap regression proving key-first pairing), render tests per renderer for the name change and the removed+added shape,SecuritySchemeBCTest#apiKeyNameChangedfor the on/off switch.CLI output on the fixtures (console renderer):
Markdown (case 2) now renders as a proper nested list:
Original description below.
What
A changed
nameundercomponents.securitySchemesfor anapiKeyscheme is now captured in the diff model and rendered with old and new values in all three renderers:* Changed security scheme name: Authorization -> pat* Changed security scheme name:Authorization->pat``--html-detailed):Changed security scheme : name: Authorization -> patIt also feeds the backward-compatibility verdict through a new option,
incompatible.security.scheme.apikey.name.changed(defaulttrue), so the check can be disabled the same way as the other security-scheme rules — the reporter specifically noted there was no switch for it. Changing the parameter name means existing clients keep sending the old header/query/cookie name, so incompatible-by-default seemed like the honest default.Why
The model knew a security scheme changed but never recorded which field, so the renderers had nothing line-level to print. One note on the repro specs attached to the issue: in both
old.jsonandnew.jsonthesecuritySchemesblock sits underpaths(notcomponents), and thesecurityblock sits at path-item level. Both are silently dropped by the swagger parser, so as attached, no diff engine can see the scheme definitions at all — which is why only a bare changed operation shows up. The fixtures in this PR use valid locations.How
SecuritySchemeDiffsetschangedNameforAPIKEYschemes;ChangedSecurityScheme#isCoreChangedgates the incompatibility on the new option (same handling as the existingchangedSchemeflag).SecuritySchemeobjects the model already carries.Summary by cubic
Captures
apiKeysecurity scheme name changes so console, markdown, and HTML renderers report the old and new values instead of a bare operation-level change, and aligns the security renderers.incompatible.security.scheme.apikey.name.changedoption (defaulttrue) controls the backward-compatibility verdict, since existing clients keep sending the old parameter name.SecurityRequirementDiffpairs requirement schemes by component key first and only falls back to the parameter name when the key no longer matches, so a rename is diffed as a scheme change instead of a deleted plus re-added requirement, and severalapiKeyschemes in one requirement are no longer mispaired by name.Written for commit 0aa0347. Summary will update on new commits.