fix(openapi): add ForbiddenError response, fix misplaced schemas, add $ref validation to schema generator#1600
Merged
jaypatrick merged 3 commits intomainfrom Apr 15, 2026
Merged
Conversation
…s, add $ref validator to generator - Add ForbiddenError response definition to components/responses in openapi.yaml - Move misplaced schemas (ConvertRuleRequest, AdminCreateLocalUserRequest, etc.) from components/responses to components/schemas in openapi.yaml (fixes all broken $ref paths) - Add validateLocalRefs() helper to generate-cloudflare-schema.ts that walks all local $ref pointers and exits 1 before writing output if any are unresolved - Regenerate cloudflare-schema.yaml and postman collection from the fixed source Agent-Logs-Url: https://github.com/jaypatrick/adblock-compiler/sessions/364c9ecc-e3fe-48c5-98d3-aa7d7c88ceb3 Co-authored-by: jaypatrick <1800595+jaypatrick@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix absent ForbiddenError in API schema
fix(openapi): add ForbiddenError response, fix misplaced schemas, add $ref validation to schema generator
Apr 15, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes Cloudflare API Shield upload failures by correcting OpenAPI component structure and ensuring local $ref integrity before schema generation and upload.
Changes:
- Added missing
ForbiddenErrortocomponents/responsesand ensured downstream generated schema includes it. - Corrected component placement so schemas live under
components/schemas(matching their$reftargets) and responses undercomponents/responses. - Added a pre-write local
$refresolution validation pass to the Cloudflare schema generator.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| scripts/generate-cloudflare-schema.ts | Adds a local $ref validator that fails generation early when refs can’t be resolved. |
| docs/api/openapi.yaml | Fixes component layout and defines ForbiddenError response so referenced responses exist. |
| docs/api/cloudflare-schema.yaml | Regenerated Cloudflare API Shield schema reflecting fixed refs and new ForbiddenError. |
| docs/postman/postman-collection.json | Regenerated Postman collection with updated request body example. |
Owner
|
@copilot apply changes based on the comments in this thread |
Per RFC 6901 §3, pointer segments must be unescaped before use as object keys (~1 → /, ~0 → ~). Without this, any $ref whose path contains a literal slash or tilde (encoded as ~1 or ~0) would be incorrectly reported as unresolved and cause the generator to exit 1. Agent-Logs-Url: https://github.com/jaypatrick/adblock-compiler/sessions/e2f13a31-41ae-4352-acd8-50e14dfc9c60 Co-authored-by: jaypatrick <1800595+jaypatrick@users.noreply.github.com>
Contributor
Author
Applied in fc68cd8. |
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.
deno task schema:uploadwas rejected by Cloudflare API Shield withreferenced object not found. Two root causes:ForbiddenErrorwas referenced in 7 path operations but never defined incomponents/responses; 25 schemas (ConvertRuleRequest,AdminCreateLocalUserRequest, etc.) were defined undercomponents/responsesbut referenced as#/components/schemas/X— broken per strict JSON pointer semantics.Description
Fixes broken
$refpointers inopenapi.yamland regenerates downstream artifacts. Also adds a pre-write$refvalidation pass to the schema generator to catch this class of bug before it reaches upload.Changes
docs/api/openapi.yamlForbiddenErrortocomponents/responses(was missing; referenced by 7 admin-route 403 responses)ConvertRuleRequest,AdminCreateLocalUserRequest,LocalSignupRequest,RuleSet*,Webhook*,LocalAuth*, etc.) fromcomponents/responses→components/schemaswhere their$reftargets actually pointscripts/generate-cloudflare-schema.ts— addedvalidateLocalRefs()that walks all#/-prefixed$refvalues in the parsed spec, resolves each via JSON pointer against the root, and exits 1 before writing the output file if any are unresolved.resolvePointer()applies RFC 6901 §3 unescaping (~1→/, then~0→~) on each path segment before indexing into the spec, ensuring$refs containing encoded slashes or tildes resolve correctly:docs/api/cloudflare-schema.yaml— regenerated from fixed source (deno task schema:cloudflare); all refs now resolve,ForbiddenErrorpresent incomponents/responsesdocs/postman/postman-collection.json— regenerated from fixed source (deno task postman:collection)Testing
deno task schema:generatepasses with✅ All local $refs resolve correctly;deno task openapi:validate→ 0 errorsZero Trust Architecture Checklist
Worker / Backend
*) on write/authenticated endpoints — N/A[vars]) — N/A.prepare().bind()(no string interpolation) — N/AFrontend / Angular
CanActivateFnauth guards — N/AlocalStorage) — N/AAPI Shield / Vulnerability Scanner
operationIdinopenapi.yaml— N/A (no new endpoints)/{id}path parameters) include asecurity:annotation — N/AWHERE user_id = ?) — N/A404(not403) to avoid leaking resource existence — N/Acloudflare-schema.yamlregenerated ifopenapi.yamlchanged (deno task schema:cloudflare) — ✅ regeneratedOriginal prompt
Problem
The
deno task schema:upload -- --skip-if-unchangedCI job fails with:Root cause:
ForbiddenErroris used as a$refin many path operations across bothdocs/api/openapi.yamlanddocs/api/cloudflare-schema.yaml(e.g.$ref: '#/components/responses/ForbiddenError'), but theForbiddenErrorentry is completely absent fromcomponents/responsesin both files. Cloudflare API Shield validates all$refs on upload and rejects the schema with areferenced object not foundcritical error.You can confirm this with a grep —
ForbiddenError:does not appear in either YAML file'scomponents/responsessection, whileUnauthorizedError:,BadRequestError:,ServiceUnavailable:, etc. all exist there.Fix Required
1. Add
ForbiddenErrortodocs/api/openapi.yamlundercomponents/responsesAdd it alongside
UnauthorizedError. Match the style conventions used by the other response entries in that file (compact inline style):Place it directly after
UnauthorizedError:in thecomponents/responses:block.2. Add
ForbiddenErrortodocs/api/cloudflare-schema.yamlundercomponents/responsesThe cloudflare schema uses expanded YAML style. Add it after
UnauthorizedError:incomponents/responses:, consistent with the style of that file:3. Add
$refvalidation toscripts/generate-cloudflare-schema.tsAfter generating the schema (before writing the output file), add a validation pass that walks all
$refvalues in the spec and checks that each one resolves locally within the document. If any unresolved$refs are found, log them and exit with code 1. This prevents a silent broken schema from being written and later failing at upload time.The validation function should:
#/(local JSON pointer$refs)Add it as a helper function
validateLocalRefs(spec: OpenAPISpec): string[]that returns an array of unresolved ref strings, and call it after the x-extension removal step and before the YAML stringify step.Files to change
docs/api/openapi.yaml— addForbiddenErrortocomponents/responsesdocs/api/cloudflare-schema.yaml— addForbiddenErrortocomponents/responsesscripts/generate-cloudflare-schema.ts— add local$refvalidation before writing outputImportant notes
docs/api/cloudflare-schema.yamlhas the header comment# DO NOT EDIT DIRECTLY— this is fine to edit directly for this fix since the sourceopenapi.yamlis also being fixed and the generator will produce the correct output going forward.cloudflare-schema.yamluses 4-space indentation with expanded YAML (no flow style). Match this exactly.openapi.yamluses compact/flow style for simple schemas like{ type: boolean, example: false }. Match that style for the new entry.The following is the prior conversation context from the user's chat exploration (may be truncated):
User: Run deno task schema:upload -- --skip-if-unchanged
Task schema:upload deno run --allow-read --allow-net --allow-env scripts/upload-cloudflare-schema.ts "--" "--skip-if-unchanged"
📋 Local schema: ./docs/api/cloudflare-schema.yaml (SHA-256: 21376c67f3ed0b94...)
📡 Found 0 existing schema(s) in zone ***
❌ Failed to upload schema: 400 {"result":{"upload_details":{"critical":{"code":21,"message":"referenced object not found","location":".paths["/admin/local-users"].post.requestBody.content["application/json"].schema"}}},"success":false,"errors":...
This pull request was created from Copilot chat.