Skip to content

fix: the OpenAPI documents validate (OpenAPI 3.0) - #22

Merged
dskripchenko merged 2 commits into
masterfrom
fix/openapi-empty-properties
Oct 26, 2026
Merged

dskripchenko merged 2 commits into
masterfrom
fix/openapi-empty-properties

Conversation

@dskripchenko

@dskripchenko dskripchenko commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #21 (uses JsonSchemas::encodable() from it) — merge #21 first; until then this diff includes its commits.

Found how

Validating the OpenRPC output of #21 turned up "properties": []; the same check on the OpenAPI documents with @apidevtools/swagger-parser showed 14 of the 17 documents of the fixtures and the example are invalid OpenAPI 3.0. Pre-existing, for three reasons:

  1. "properties": [] — PHP's empty array encoded as a JSON list where a map is due (an @output without fields, envelope payloads, empty templates). 21 occurrences.
  2. "required": [] — OpenAPI 3.0's schemas are draft-4 based, where required needs at least one name. 9 occurrences (templates/envelope normalized with keepEmptyRequired).
  3. name inside every @output field schema — "pong": {"type": "boolean", "name": "pong", …}; a Schema Object has no such keyword. A leftover of the output builder (the nested branch takes the name from the key, never from it). 68 occurrences.

Fix

  • (3) at the source: DescriptorBuilder no longer puts name into output field schemas (so descriptors/MCP/OpenRPC are cleaner too).
  • (2) in OpenApiRenderer::render(): empty required lists are dropped from the document (draft-4 rule, so OpenAPI-only; templates keep theirs internally for merging).
  • (1) at the JSON boundary: /api/doc/{version} (and its on-disk spec cache) and the specs api:cache builds go through JsonSchemas::encodable(). Not in render(): PHP consumers of the array (TS generator, exporters) check empty($properties), which an stdClass would break.

After: 17/17 valid with swagger-parser (lint_broken throws by design). Parameter names untouched (checked).

Snapshots

17 OpenAPI spec snapshots change — and only in these lines: −68 "name": … inside field schemas, 21× "properties": [] → {}, −9 "required": [] (+ comma adjustments). The spec snapshot now pins the document as served (JsonSchemas::encodable() applied). TS types, exports, lint reports and routes: unchanged.

Tests

643 passing. New in OpenApiRendererTest: the served documents of 8 fixture APIs have no list properties, no empty required, no name in field schemas — fails on 8/8 without the fix. DescriptorBuilderTest updated (no name). CHANGELOG → Fixed.

🤖 Generated with Claude Code

dskripchenko and others added 2 commits October 26, 2026 21:39
With laravel-api.jsonrpc.enabled, POST /{prefix}/rpc/{version} serves
every action as a method controller.action with by-name params, through
Runtime\Dispatcher. Failures are errors (-32602 for 422, -32000 otherwise,
status and payload in data); batches and notifications per spec;
rpc.discover answers with an OpenRPC 1.3.2 document. ServedVersions and
NamedOperations are shared with MCP. JsonSchemas::encodable() writes empty
properties/$defs as {} — the OpenRPC validator rejected [].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
swagger-parser rejected 14 of the 17 documents of the fixtures and the
example: properties [] (an empty PHP array as a JSON list), required []
(draft 4 wants one name) and a name key inside every @output field
schema. The name keys and empty required lists are gone from
getOpenApiConfig(); the empty maps are written as {} at the JSON
boundary (/api/doc/{version}, api:cache). All 17 validate. TS types and
exports unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dskripchenko
dskripchenko merged commit 55af3eb into master Oct 26, 2026
7 checks passed
@dskripchenko dskripchenko mentioned this pull request Oct 26, 2026
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