Skip to content

tech-debt(validation) — ResponseBodyValidator に malformed-schema ガードが無く、非配列の schema が診断なく素通り / TypeError になる #256

@wadakatu

Description

@wadakatu

背景

PR #255(issue #254 — 非 JSON Content-Type に付いた schema の検証スキップを surface)の multi-agent レビュー(/pr-review-toolkit:review-pr)で silent-failure-hunter が指摘。#254 以前から存在する既存ギャップで、#254 のアダプタ/skip-surface 修正とは独立のためスコープ外として切り出し。

現状

RequestBodyValidatorrequestBody.content の各 media type entry を走査し、schema が非配列(schema: "oops" / schema: null 等)なら loud な spec エラーを返す:

// src/Validation/Request/RequestBodyValidator.php
if (array_key_exists('schema', $mediaTypeSpec) && !is_array($mediaTypeSpec['schema'])) {
    return new RequestBodyValidationResult([
        "Malformed 'requestBody.content[\"{$mediaType}\"].schema' ... expected object, got scalar.",
    ]);
}

一方 ResponseBodyValidator にはこの走査ガードが一切無いresponses[$status].content の media type entry の schema が非配列でも事前検証されない。

問題

ResponseBodyValidator で spec の content map の schema が非配列のとき:

  • JSON media type の場合schema がそのまま OpenApiSchemaConverter::convert() に渡り、配列を期待する箇所で TypeError になる(RequestBodyValidator のコメントが「array_key_exists rather than isset so an explicit `schema: null` is also flagged ... producing a confusing TypeError instead of a spec-level error」と明記しているのと同じ事象)。
  • 非 JSON media type の場合tech-debt(validation) — spec が宣言した非 JSON Content-Type のボディが診断なしで素通りする #254 で追加した skip 判定は isset($content[$matchedKey]['schema']) を使う。schema: nullisset が false を返すため「schema 無し」とみなされ、診断なしの silent success になる。リクエスト側は同じ schema: null を malformed spec エラーとして loud に落とすため、request/response で挙動が非対称。

contract-testing ツールの「malformed spec は隠さず surface する」原則に反し、かつ request 側との一貫性も欠く。

やること

  • ResponseBodyValidator::validate() に、RequestBodyValidator のループ前ガードと対称な malformed-schema 検出を追加する
    • content の各 media type entry について、array_key_exists('schema', ...) かつ !is_array(...) なら Malformed 'responses[...].content["..."].schema' 形式の spec エラーを返す
    • content / content[mediaType] 自体が非配列のケースも RequestBodyValidator のガード(Malformed 'requestBody.content' 等)に倣って揃えるか検討する
  • 非 JSON skip 判定(tech-debt(validation) — spec が宣言した非 JSON Content-Type のボディが診断なしで素通りする #254 で追加した isset(...['schema']))は、上記ガード追加後は schema: null がガードで先に弾かれるため isset のままで一貫する
  • TDD: 非配列 schemaschema: "oops" / schema: null)を持つ response spec に対し、(a) JSON media type で TypeError ではなく spec エラーが返ること、(b) 非 JSON media type で silent success ではなく spec エラーが返ること、を検証する失敗テストを先に追加

ゴール

  • ResponseBodyValidator が非配列 schemaRequestBodyValidator と同じ粒度の loud な spec エラーとして surface する
  • JSON media type の非配列 schemaTypeError が出ない
  • 非 JSON media type の schema: null が診断なしで素通りしない(request/response で挙動が揃う)

関連

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions