diff --git a/CHANGELOG.md b/CHANGELOG.md index ca76228..a46121e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- **Documentation.** Three divergences from the specification are now written + down rather than merely true: a percent-encoded delimiter inside a + `pipeDelimited`/`spaceDelimited` value is folded into the delimiter, a Header + Object carrying `name`/`in` is ignored rather than refused, and `example` + with `examples` are both kept instead of being refused as mutually exclusive. + No behaviour changed: the first agrees with how a PHP application reads the + same query, and changing it would break that agreement to gain agreement with + the text. + - **Fixed.** A YAML document under a kilobyte could exhaust memory and die with a fatal error rather than an `InvalidContract`. Anchors and aliases expand inside the parser, before any budget measures anything, and the byte budget diff --git a/README.md b/README.md index 2a99e17..c324952 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,17 @@ REQUIRED `description`, or an `encoding` declared on a media type the specification does not apply it to — accepted, because neither changes a verdict. Reach for a linter for the rest. +Three divergences from the specification are deliberate and pinned: + +| Where | The specification | This package | +|---|---|---| +| A percent-encoded delimiter inside a `pipeDelimited` or `spaceDelimited` value | `\|` and space MUST be percent-encoded inside a value, so `?ids=a%7Cb` is the single element `a\|b` | folds the encoded form into the delimiter and reads two elements — which is what a PHP application reading the same query does, and agreeing with the application is the point of a validator. A value containing the delimiter cannot be expressed | +| A Header Object carrying `name` or `in` | both MUST NOT be specified | ignored, not refused: the header's name comes from the map key either way | +| `example` and `examples` on the same object | mutually exclusive | both are kept as annotations and handed to consumers; the validator reads neither | + +`deepObject` is not among them: `f%5Ba%5D=1` and `f[a]=1` are the same +parameter here and in PHP's own query parsing. + ## Security **Declared `security` is not enforced.** Requirements are compiled, and a diff --git a/README.ru.md b/README.ru.md index 04078ed..f016fb5 100644 --- a/README.ru.md +++ b/README.ru.md @@ -375,6 +375,17 @@ instance path равен `$`; параметр печатается, но каж применяет, — принимаются, потому что вердикт от них не зависит. Для остального есть линтер. +Три расхождения со спекой сделаны осознанно и зафиксированы: + +| Где | Спека | Пакет | +|---|---|---| +| Percent-encoded разделитель внутри значения `pipeDelimited`/`spaceDelimited` | `\|` и пробел внутри значения MUST быть percent-encoded, поэтому `?ids=a%7Cb` — один элемент `a\|b` | складывает закодированную форму в разделитель и читает два элемента — ровно так же читает PHP-приложение, разбирающее тот же query, а согласие с приложением и есть смысл валидатора. Значение с разделителем внутри выразить нельзя | +| Header Object с `name` или `in` | оба MUST NOT be specified | игнорируются, а не отвергаются: имя заголовка в любом случае берётся из ключа карты | +| `example` и `examples` на одном объекте | взаимоисключающие | оба сохраняются как аннотации и отдаются потребителю; валидация не читает ни одно | + +`deepObject` в этот список не входит: `f%5Ba%5D=1` и `f[a]=1` — один и тот же +параметр и здесь, и в собственном разборе query у PHP. + ## Безопасность **Объявленный `security` не проверяется.** Требования компилируются, и diff --git a/llms.txt b/llms.txt index 2be7fff..e96664b 100644 --- a/llms.txt +++ b/llms.txt @@ -103,6 +103,14 @@ Rules: - `format: date-time` (and the other supported formats) are asserted, not treated as annotations — a pinned divergence from league/openapi-psr7-validator; +- three pinned divergences from the specification: a percent-encoded `|` or + space inside a `pipeDelimited`/`spaceDelimited` value is folded into the + delimiter (as PHP's own query parsing does, so `?ids=a%7Cb` is two elements + here and one per the spec — a value containing the delimiter cannot be + expressed); a Header Object carrying `name`/`in` is ignored rather than + refused; `example` and `examples` together are both kept instead of being + refused as mutually exclusive. `deepObject` is NOT one of them — + `f%5Ba%5D=1` and `f[a]=1` agree with PHP; - multi-file resolution is differentially tested against cebe/php-openapi (dev-only oracle, OAS 3.0): pinned divergences are the depth budget on deep `$ref` chains and fast rejection of cross-file cycles.