Breaking changes to audit before any framework upgrade

Use captured schema and write behavior to turn a release-note warning into a concrete upgrade stop condition.
Connect the release note to a behavior
Laravel 11’s upgrade guide says that a changed column must explicitly repeat the modifiers it should retain. That warning becomes useful when it is connected to a specific column and a write that depends on its default. I recommend making that connection before approving an upgrade.
The reproduction below uses historical Laravel 10.50.3 and 11.0.0 under PHP 8.3.35 with SQLite 3.53.4. Both framework targets are unsupported. Their locked dependencies have known advisories in the bundled 13 October 2026 snapshot. This is isolated historical evidence, not an application dependency recommendation or a fresh security audit.
Capture the old state and the changed writes
Laravel 10 creates a synthetic invoices table with a nullable reference column and default draft, then inserts a legacy-note row. Laravel 11 changes reference from a declared varchar to TEXT. In the incomplete change, neither nullable nor default is repeated. SQLite’s column inspection then shows NOT NULL with no default, while the original non-NULL row is still readable.
The next write exposes the consequence. Omitting reference fails with SQLSTATE 23000; explicitly inserting NULL also fails. The same Laravel 10 query-builder writes fail against that changed database. Switching the runtime back therefore does not restore this schema’s previous write behavior. This probe does not perform a deployment rollback or database recovery.
A second baseline contains an existing NULL reference. Applying the incomplete change fails while SQLite copies rows into the replacement table, again with SQLSTATE 23000. The recorded failure identifies the NOT NULL constraint on the temporary table. No claim is made about the database state or recovery after that rejected copy.
Verify the complete modifier definition
Repeating nullable and default in the Laravel 11 change preserves both intended behaviors. A temporary omitted-value insert reads back draft, and an explicit NULL insert succeeds. The repaired upgrade’s column observations and original rows match a separately created fresh Laravel 11 schema. Temporary write probes are rolled back to keep the fixture rows unchanged.
The callback below is the exact context-dependent fragment in the executed probe. The downloadable bundle supplies its connection setup, database-generation steps and assertions. A complete application migration still needs its own surrounding migration class and deployment procedure.
$schema->table('invoices', function (Blueprint $table): void {
$table->text('reference')->nullable()->default('draft')->change();
});
Check what a successful statement can hide
The verifier runs fifteen cases, including two intentionally altered repaired definitions. Removing only default still permits an omitted-value insert, but its value becomes NULL. The default assertion catches that silent difference. Removing only nullable keeps draft as the default but rejects explicit NULL, and the nullability assertion catches it. A successful SQL statement is therefore insufficient evidence for the intended default.
The old and new query-builder readers return the same synthetic rows after the repaired change, including the baseline containing NULL. That establishes agreement for those queries and values. It does not certify application model casts, serialized jobs, authentication or a rolling deployment. The old framework creates and reads the fixture; it does not execute the change migration in this test. Retention under a Laravel 10 change is documented in the upgrade guide, not independently demonstrated here.
Download and extract the bundle, then run python3 frontend/content-quality/fixtures/laravel-schema/verify.py schema-results.json from its root with Docker available. The verifier checks runtime versions, executed source hashes and dependency locks. Builds may retrieve packages with Composer scripts and plugins disabled. Probes run without network or credentials, with bounded resources and only the disposable SQLite directory writable. Test containers, uniquely owned images and temporary files are removed.
Turn the result into an audit decision
For this reproduced case, I recommend stopping approval of the incomplete change and requiring the explicit modifiers plus the writer checks. The database-change reviewer should attach the column observations and failure results to the upgrade record. The release owner should separately establish how a failed migration is recovered before authorizing an application rollout.
I recommend applying the same method to the other boundaries the application uses. If an API client requires a JSON 401, check the rejected request rather than inferring compatibility from successful browser login. If old queued payloads may remain during deployment, write them with the old producer and exercise the new consumer; also test the reverse direction when overlap is intended. Those HTTP and worker tests were not performed by this schema fixture.
Package installation and dependency constraints answer a different question from those behavior checks. I recommend giving each relevant upgrade item an owner, its expected result and a stop condition. Mark an item inapplicable only after checking the actual code or configuration. Avoid replacing missing service evidence with a guessed universal error-rate threshold.
Repeat the engine-specific checks where they matter
This evidence is limited to SQLite schema-builder and query-builder operations. SQLite’s affinity documentation explains that VARCHAR length arguments are not enforced. The fixture does not establish MySQL or PostgreSQL precision, scale, unsigned handling or migration transaction behavior. I recommend repeating the relevant cases against the actual engine and patch version before using the result to approve that system.
Schema repair and historical data repair also need separate evidence. A code rollback cannot reconstruct information removed by a migration. I recommend recording what is restored, who decides to stop, and which recovery rehearsal proves that procedure. The tests here demonstrate a modifier regression and its checked alternative; they do not establish that every upgrade risk has been audited.
Reproduce the examples
Download the exact PHP schema probe, locked historical Laravel dependencies, observed results and assertions. The verifier runs fifteen SQLite cases, including intended failures. These unsupported historical versions are isolated test targets, not application dependency recommendations.
Download the source and tests (.zip)
