Skip to content

fix(downgrader): inline $refs into webhooks and components.pathItems removed by 3.1 to 3.0 - #25

Merged
dinwwwh merged 5 commits into
mainfrom
claude/webhook-pathitems-refs-conversion-6eacc4
Sep 27, 2026
Merged

dinwwwh merged 5 commits into
mainfrom
claude/webhook-pathitems-refs-conversion-6eacc4

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Sep 27, 2026

Copy link
Copy Markdown
Member

3.1 → 3.0 no longer leaves $refs pointing into webhooks or components.pathItems, which it removes. References into them from any position are replaced by their converted target, and Link operationRefs into them become an operationId or are removed. The output validates as 3.0. Documents without such references convert exactly as before.

Fixes

  • Reference Objects, Path Item $refs and Schema $refs into the removed parts are inlined in converted form, following reference chains. A chain that leaves them ends at that $ref. A Reference Object's summary/description applies to the inlined target.
  • A Link operationRef into them becomes the target's operationId when that operation is still in the output. Otherwise the link is removed, together with Link $refs that lead to it.
  • discriminator.mapping entries pointing into them are removed.
  • Recursion is cut: a Schema becomes {}, a Path Item keeps its own fields, and other references are dropped. Acyclic input always gives acyclic output, and object cycles in dereferenced input are kept.
  • Each inlined target is converted once and shared, so reference fan-out no longer grows the output exponentially.
  • Path Item $refs inline only when they point at a Path Item.
  • Security scheme aliases resolve through any local ref, so mutualTLS removal and scope emptying also apply to escaped names and aliases into the removed parts.
  • Missing targets and reference loops are left as written, as before.

Behavior changes

  • Path Item $refs to components.pathItems that reach themselves through callbacks are now cut to their own fields instead of dangling.
  • A target inlined at several references is shared within the result, as 3.2 → 3.1 already does. The README contract says so.

Performance

Document (2,000 operations, no refs into removed parts) main this PR
3.1 → 3.0 5.7 ms 6.8–7.2 ms
3.2 → 3.1 10.3 ms 10.5 ms

Output is identical to main on both. The 3.1 → 3.0 cost is the per-$ref check, similar to what #24 added for 3.2 → 3.1.

Testing

  • 438 tests pass, with 100% coverage of packages/downgrader/src. Lint and type-check pass.
  • An end-to-end 3.1 document with refs from every position validates as 3.1 before and 3.0 after, and has no pointer into the removed parts.
  • Every issue confirmed in an adversarial review has a regression test. A fuzz run of 22,000 generated documents found no cyclic output.

Known limits

  • A pointer that passes through another $ref partway is not followed.
  • A Link naming a removed operation only by operationId is kept.
  • Where a recursive cycle is cut can depend on document key order.
  • 3.2 → 3.1 still has the shared-object cycle case from fix(downgrader): inline $refs into parts removed by 3.2 to 3.1 #24. The new convertInlined helper makes that a one-line follow-up.

dinwwwh and others added 5 commits September 27, 2026 15:06
…removed by 3.1 to 3.0

Co-Authored-By: Claude <noreply@anthropic.com>
… helpers

Resolve refs with parseLocalRef/resolveLocalRef, guard recursion with
isConverting and the pointers being inlined, and keep one schema finish
function per call so converted schemas are reused. The inline cap is no
longer needed.

Co-Authored-By: Claude <noreply@anthropic.com>
…h target once

An in-progress conversion is reused only within the same inline, so a
callback, own field, or shared object that leads back into content still
being converted is cut instead of forming a cycle. Inlined targets are
converted once per converter, Path Item $refs inline only at Path Item
locations, and security scheme aliases resolve through any local ref.

Co-Authored-By: Claude <noreply@anthropic.com>
…o 3.0 ref inlining

Fields a Path Item inherits from a later $ref hop are converted inside the
inline, a conversion cut inside an inline is redone when reached again
outside it so object cycles survive, and links are checked against the
operationIds that remain in the output.

Co-Authored-By: Claude <noreply@anthropic.com>
@pullfrog

pullfrog Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Pullfrog  | View workflow run | via Pullfrog | Using DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

@codecov

codecov Bot commented Sep 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@dinwwwh
dinwwwh merged commit 0ddcb9b into main Sep 27, 2026
6 of 7 checks passed
@dinwwwh
dinwwwh deleted the claude/webhook-pathitems-refs-conversion-6eacc4 branch September 27, 2026 13:04
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.

1 participant