Skip to content

[P3] No static analysis in CI (PHPStan L9 finds 17 errors incl. the #21 coercion bug) and an open-ended >=8.1 PHP constraint #24

Description

@karlwaldman

Confirmed by execution, 2026-09-13. Two packaging gaps that let the coercion bug class in #15/#18/#21 reach a release.

1. No static analysis anywhere in the toolchain

composer.json:64-66 defines one script, "test": "phpunit". No phpstan, no psalm, no php-cs-fixer, no phpcs, and .github/workflows/test.yml runs only composer validate --strict and vendor/bin/phpunit.

Running PHPStan level 9 against src/ on the #18 branch reports 17 errors, six of which are precisely the defect filed as #21:

$ phpstan analyse --level=9 src
src/Price.php:96   Cannot cast mixed to string.  (cast.string)
src/Price.php:99   Cannot cast mixed to string.
src/Price.php:100  Cannot cast mixed to string.
src/Price.php:101  Cannot cast mixed to string.
src/Price.php:102  Cannot cast mixed to string.
src/Price.php:103  Cannot cast mixed to string.
src/Client.php:387 Cannot cast mixed to string.
src/Client.php:388 Cannot cast mixed to string.
src/Client.php:394 Cannot cast mixed to string.
src/Client.php:296 Strict comparison using !== between string and null will always evaluate to true.
src/Client.php:313 Call to function assert() with true will always evaluate to true.
src/Http/CurlTransport.php:27 Parameter #2 $options of curl_setopt_array ...
[ERROR] Found 17 errors

For a library whose defining hazard is PHP coercing untrusted JSON at a function boundary, a level-8/9 gate in CI is the cheapest possible control. declare(strict_types=1) is correctly present in all 19 PHP files, but it does not police an explicit (string)/(float) cast — which is exactly where both #15 and #21 live.

Suggested: add phpstan/phpstan to require-dev, a phpstan.neon at level 8 with a short baseline for the existing 17, a "lint"/"analyse" composer script, and a CI step. Ratchet the level up as the baseline shrinks.

2. "php": ">=8.1" is an open upper bound

composer.json:47. Composer will happily install this package on PHP 9.0 or 10.0, neither of which exists yet and neither of which is tested — the CI matrix is 8.1 through 8.5 (.github/workflows/test.yml:19). The honest constraint for a library is ^8.1, which covers 8.x and requires a deliberate release to claim 9.x.

Related: ext-curl: "*" carries no version floor either, which matters for #22 — libcurl < 7.58.0 forwards the Authorization header across a cross-origin redirect.

Found during the post-merge PHP expert review of #17/#18/#19.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Priority 3 - backlogbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions