Summary
While eliminating the project's SQLite testing fallback (routing local tests through the db compose service — real MariaDB, matching CI), a freshly-built cli image was found to produce false test failures at scale: 103 failures on a full-suite run that pass cleanly under the existing, proven ip2-test-php:8.4 local image against the exact same database. Root cause not found despite extensive isolation — documenting the investigation so it isn't lost, and so nobody re-trusts a freshly-built cli image without re-verifying first.
Symptom
Modules\Clients\Tests\Feature\ContactsTest::it_creates_a_contact_through_a_modal (and ~100 others, mostly Livewire fillForm()/mountAction()/callMountedAction() flows):
Component has errors: "mountedActions.0.data.relation_id" => ["The customer field is required."], ...
Failed asserting that false is true.
The form's fillForm($payload) call appears to have no effect by the time callMountedAction() validates — as if the filled values never reached component state. Confirmed via DB::listen() on a simpler case (UserProfileTest::it_saves_the_user_data_form): the resulting UPDATE statement is missing the field that was supposedly filled.
What was ruled out (all confirmed NOT the cause)
- Docker Compose networking/env injection — reproduces identically via plain
docker run bypassing compose entirely.
.env.testing file contents — reproduces with the file held constant (same file used against both the broken and working image).
HOME env var — explicitly setting HOME=/tmp to match the working invocation made no difference.
- Stale compiled views / config cache — cleared
storage/framework/views/*.php and bootstrap/cache/*.php; no change.
- Alpine vs Debian base — rebuilt the image on
php:8.4-cli (Debian trixie, matching the proven image); bug persisted.
- Extension set —
php -m diffed to a single extra module (pcntl) against ip2-test-php:8.4; removing it (rebuilding with the exact minimal extension list intl gd pdo_mysql bcmath zip exif — the one documented as producing the known-good image) made no difference.
- Stale test data from manual
tinker sessions during the investigation — ran php artisan migrate:fresh for a clean database; identical 103 failures on the clean DB.
- Full
php -i diff — apart from memory_limit, pcntl, and container hostname/HOME/PWD, output is identical between the two images.
- PHP version — both report
PHP 8.4.23 (cli), built via the same docker-library/php recipe (confirmed via docker history --no-trunc on the working image).
The one confirmed difference: the two php binaries have different SHA-256 hashes (built ~12 days apart per their respective Build Date), suggesting upstream Debian trixie package drift (glibc/openssl/etc.) between builds — plausible but unconfirmed as the actual mechanism. A concrete but unverified hypothesis: Livewire's component-snapshot checksum validation (HMAC'd with APP_KEY) silently rejecting/no-op'ing an update if something in the crypto/hash chain behaves subtly differently, rather than throwing — worth checking Livewire\Mechanisms\HandleComponents\ComponentContext/checksum verification path first.
Current state
docker-resources/php-cli/Dockerfile was reduced to the minimal, documented-working extension set as the best available mitigation, but this issue was not resolved by that change — it's flagged here specifically because the minimal-extension rebuild still reproduces the bug.
- Docs and
docker-compose.yml currently tell developers to verify docker compose run --rm cli php artisan test against a small known test (e.g. --filter=ContactsTest) before trusting a full local run, pending this investigation.
- The underlying
db (MariaDB) service + invoiceplane_v1_import-style init-script provisioning is unaffected and confirmed working — this is specifically about the cli PHP image's behavior under Livewire form-testing at scale.
Suggested next steps
Summary
While eliminating the project's SQLite testing fallback (routing local tests through the
dbcompose service — real MariaDB, matching CI), a freshly-builtcliimage was found to produce false test failures at scale: 103 failures on a full-suite run that pass cleanly under the existing, provenip2-test-php:8.4local image against the exact same database. Root cause not found despite extensive isolation — documenting the investigation so it isn't lost, and so nobody re-trusts a freshly-builtcliimage without re-verifying first.Symptom
Modules\Clients\Tests\Feature\ContactsTest::it_creates_a_contact_through_a_modal(and ~100 others, mostly LivewirefillForm()/mountAction()/callMountedAction()flows):The form's
fillForm($payload)call appears to have no effect by the timecallMountedAction()validates — as if the filled values never reached component state. Confirmed viaDB::listen()on a simpler case (UserProfileTest::it_saves_the_user_data_form): the resultingUPDATEstatement is missing the field that was supposedly filled.What was ruled out (all confirmed NOT the cause)
docker runbypassing compose entirely..env.testingfile contents — reproduces with the file held constant (same file used against both the broken and working image).HOMEenv var — explicitly settingHOME=/tmpto match the working invocation made no difference.storage/framework/views/*.phpandbootstrap/cache/*.php; no change.php:8.4-cli(Debian trixie, matching the proven image); bug persisted.php -mdiffed to a single extra module (pcntl) againstip2-test-php:8.4; removing it (rebuilding with the exact minimal extension listintl gd pdo_mysql bcmath zip exif— the one documented as producing the known-good image) made no difference.tinkersessions during the investigation — ranphp artisan migrate:freshfor a clean database; identical 103 failures on the clean DB.php -idiff — apart frommemory_limit,pcntl, and container hostname/HOME/PWD, output is identical between the two images.PHP 8.4.23 (cli), built via the samedocker-library/phprecipe (confirmed viadocker history --no-truncon the working image).The one confirmed difference: the two
phpbinaries have different SHA-256 hashes (built ~12 days apart per their respectiveBuild Date), suggesting upstream Debian trixie package drift (glibc/openssl/etc.) between builds — plausible but unconfirmed as the actual mechanism. A concrete but unverified hypothesis: Livewire's component-snapshot checksum validation (HMAC'd withAPP_KEY) silently rejecting/no-op'ing an update if something in the crypto/hash chain behaves subtly differently, rather than throwing — worth checkingLivewire\Mechanisms\HandleComponents\ComponentContext/checksum verification path first.Current state
docker-resources/php-cli/Dockerfilewas reduced to the minimal, documented-working extension set as the best available mitigation, but this issue was not resolved by that change — it's flagged here specifically because the minimal-extension rebuild still reproduces the bug.docker-compose.ymlcurrently tell developers to verifydocker compose run --rm cli php artisan testagainst a small known test (e.g.--filter=ContactsTest) before trusting a full local run, pending this investigation.db(MariaDB) service +invoiceplane_v1_import-style init-script provisioning is unaffected and confirmed working — this is specifically about thecliPHP image's behavior under Livewire form-testing at scale.Suggested next steps
php:8.4-clidigest matchingip2-test-php:8.4's build date and rebuild against that pinned digest instead oflatest— if the bug disappears, that confirms upstream package drift as the mechanism.HandleComponents) during a failingfillForm()call to see if it's rejecting the update silently.FROM php:8.4-clito a specific digest rather than floatinglatest, and document why.