Declare the path parameters the exporter templates - #40
Open
VSN2015 wants to merge 1 commit into
Open
Conversation
Four accuracy bugs in the OpenAPI exporter, found in the same audit as
the wildcard templating below it.
OpenAPI 3.1 requires every {variable} in a path template to have a
matching path parameter, and the exporter emitted none — so every
document containing a member route was invalid, the committed golden
fixture included. Each operation now carries one path parameter per
variable in the path it was placed at, typed string, because a route
set does not say what an :id is and this exporter documents what
arrives rather than guessing. The invariant is asserted over the whole
document, so an operation added later cannot reintroduce it.
`rails_routes` kept only the first of a route's verbs, so the PATCH|PUT
pair `resources` generates exported PATCH and silently dropped PUT.
Every verb a route answers now gets its own descriptor.
ERROR_SCHEMA is the one hand-written part of the export, and it had
drifted twice: a violation on a field with `message:` carries a third
key it never mentioned, and the code enumeration never gained `depth`
from a :json field's max_depth: bound. Both are documented now, with
`message` optional since a violation without one keeps the bare shape,
and a spec renders a real violation and holds the schema to it — the
response half of "docs cannot drift" was the unguarded half.
Two controllers claiming one path and verb overwrote each other with no
indication anything was lost. The loser now lands in
x-permittable-controllers, where the exporter already puts an operation
it cannot place.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #29 — both edit
rails_routes, so this builds on it rather than conflicting. Merge #29 first and the base retargets tomaster.Four accuracy bugs in the exporter, from the same audit as #39. The headline claim is that an exported document cannot drift from what the server enforces; these are four ways it did.
1. A templated path variable was never declared as a parameter
OpenAPI 3.1 requires every
{variable}in a path template to have a matching path parameter. The exporter templated/users/:id→/users/{id}and then emitted noparametersat all, so every document containing a member route was invalid — including the committed golden fixture, which has a/users/{id}PATCH route and has been wrong since it was generated.Typed
stringand nothing cleverer: a route set doesn't say what an:idis, and this exporter documents what arrives rather than inventing a type. Derived from the templated path rather than from Journey internals, so it also works for hosts passing their ownroutes:descriptors — including the{path}wildcards #29 adds.Guarded as an invariant over the whole document rather than one assertion per operation, so an operation added later cannot quietly reintroduce it:
2. A route answering several verbs was documented for one
rails_routeskeptverb.split("|").first, so thePATCH|PUTpairresourcesgenerates — and anymatch via: [:patch, :put]— exported the PATCH operation and silently dropped PUT. Every verb a route answers now gets its own descriptor.3.
ERROR_SCHEMAhad drifted from what the server rendersIt is the one hand-written part of the export, and it had fallen behind twice:
message:(or with app I18n copy) carries{param:, code:, message:}. The schema documented onlyparamandcode, so a client generating types from it dropped the human-readable copy.codeenumeration never gaineddepth, which a:jsonfield'smax_depth:bound emits.messageis documented as an optional property —requiredstays%w[param code], since a violation without one keeps the bare shape — anddepthis listed. #27 guards the request-body half of the drift claim; the response half was unguarded, so there is now a spec that renders a real violation and holds the schema to the envelope:4. Two controllers on one path+verb overwrote each other
A document cannot carry two operations in one slot, and the second claim replaced the first with nothing to show it. The loser now lands in
x-permittable-controllers— which is exactly where the exporter already puts an operation it cannot place, so this needed no new vocabulary.Verification
264 examples, 0 failures; rubocop clean; coverage 96.97%.parameterson the one templated path,depthin the code description, and themessageproperty. Nothing else moved.Note on the CHANGELOG
This adds to the
## Unreleasedsection #29 opens. #39 opens one too, so those two will want a trivial merge resolution whichever lands second.🤖 Generated with Claude Code