# Read-path audit remediation and release gates

## Implemented

- Plot imports write within one transaction and invalidate project read caches once after commit, instead of once per plot.
- Cache invalidation errors after commit are logged but cannot make a successful checkout appear to fail. The legacy full-plot cache now expires after 15 minutes.
- `audits` and `audit_trails` are converted to InnoDB by migration `000006`; `000007` adds the `(userid, id, status)` order-list index. Both were applied to the local `miliki_db_new` dummy database. Its order-list `EXPLAIN` selected that index without a filesort.
- PHPUnit defaults to in-memory SQLite. Run `php artisan test`; the MySQL storage-engine assertion is intentionally skipped under SQLite.
- The deploy workflow runs `app:verify-migration-baseline` before `migrate --force` and uses locked Composer dependencies. When the legacy production history is incomplete, the `pushToServer` branch applies only the explicitly audited `000001` through `000007` migrations; other branches still fail closed.
- `symfony/yaml` was updated to 7.4.18, removing its three reported advisories.

## Before deploying to an existing database

Back up the database and verify that the `migrations` table accurately records the existing foundational `users`, `properties`, `property_plots`, and `orders` tables. Run `php artisan app:verify-migration-baseline` against the exact deployment database. Do not run a full `php artisan migrate --force` or manufacture migration records from table names alone when this check fails: legacy migrations may still be pending and schema differences need manual reconciliation. Until that reconciliation is complete, production deployment is deliberately limited to the seven scoped 2026 migrations. The imported local dummy has the same incomplete-history condition and was validated using those scoped migrations.

The engine conversions may lock tables while MySQL rebuilds them. Schedule production migration execution accordingly and verify all checkout/audit tables use InnoDB afterward.

## Outstanding security upgrade

`composer audit --locked` still reports five advisories affecting `laravel/framework` 9 and `firebase/php-jwt` 6. Passport 10 requires JWT 6 and Laravel 8/9, so JWT 7 cannot be installed independently. Laravel 12.61.1 is also blocked by the current app constraint, Passport 10, Livewire 2, auditing 13, several `epmnzava/*` packages, `fideloper/proxy`, and `fruitcake/laravel-cors`. This is a framework/integration migration, not a safe lockfile-only update.

Treat these remaining advisories as a release security gate. In a dedicated upgrade, replace or update the incompatible packages, adopt Laravel's built-in proxy/CORS middleware, upgrade Passport and PHP requirements, run migrations on an isolated production-like copy, and rerun the full test suite, authentication/checkout integration checks, and `composer audit --locked`. Do not suppress the advisories or claim they are remediated until the audited lockfile is clean.
