# Laravel 8 to 12 Implementer Sequence

## Scope

This document is local-only for `c:\Users\Fatih\Desktop\new\markest-local\propturk`.

Role: Implementer agent.

Current authorization only allows documentation work under `docs/upgrade/`. Do not change Composer dependencies, application code, database schema, environment files, public assets, or live servers until the user explicitly approves the relevant stage.

The Laravel 8 application is the behavior source of truth. Every route, page, admin workflow, listing workflow, API response, PDF, queue job, broadcast event, asset, storage path, and database behavior must remain equivalent after each approved stage.

## Baseline Captured On 2026-06-06

Commands already run locally for this sequence:

- `git status --short`
- `php -v`
- `composer --version`
- `node -v`
- `npm -v`
- `composer show --direct`
- `composer why-not laravel/framework ^12.0`
- `php artisan --version`
- `php artisan route:list`
- `php artisan route:list --json`
- `rg --files app routes resources/views config database tests | Measure-Object | Select-Object -ExpandProperty Count`
- `Get-Content composer.json`
- `Get-Content package.json`
- `Get-Content routes/web.php`
- `Get-Content routes/api.php`
- `Get-Content routes/channels.php`
- `rg --files app/Http/Controllers app/Models app/Console app/Events app/Mail app/Policies app/Providers app/Helpers database/migrations database/seeders resources/views | Sort-Object`
- `rg --files app/Http/Middleware app/Http/Requests config resources/js resources/css public/js public/css | Sort-Object`
- `rg "JwtMiddleware|CheckPostBank|bank|jwt.verify|Broadcast::channel|ShouldBroadcast|PDF|DomPDF|Image::|Intervention|Sluggable|uses\\(|HasSlug|Pusher|Echo|WebSockets|SmsSend|schedule|command\\(" app routes config resources database -n`
- `rg --files docs | Sort-Object`
- `Get-Content docs/laravel-12-local-upgrade-analysis.md`

Observed baseline:

- Laravel: `8.83.29`
- PHP CLI: `8.2.29`
- Composer: `2.9.5`
- Node: `20.20.2`
- npm: `10.8.2`
- Route inventory: `php artisan route:list` succeeds; `php artisan route:list --json` reports `94` routes.
- Local file inventory command over `app`, `routes`, `resources/views`, `config`, `database`, `tests` reported `223` files.
- Worktree state: already heavily dirty before this document. Preserve all existing edits. Do not revert unrelated changes.

## Protected Workflow Inventory

All implementation stages must preserve these route/page/workflow groups.

Public pages:

- `/` via `HomeController@index`, `resources/views/home/index.blade.php`
- `/search` via `HomeController@searchFilter`, search result and home listing rendering
- `/ihaleler/{slug}` via `HomeController@show`, `resources/views/property/index.blade.php`
- `/v/{slug}` short URL redirect
- `/getDistrictshome/{id}` public address AJAX
- `/iletisim`, `/hakkimizda`, `/isimiz`, `/nasil-edinirim`, `/cerez-politikasi`, `/gizlilik-politikasi`, `/kvkk`
- Bank/subdomain filtering through `DetectSubDomain` and `CheckPostBank`

Auth pages:

- `Auth::routes()`
- Login, logout, register, password reset, password confirm
- `resources/views/auth/login.blade.php`
- `resources/views/auth/register.blade.php`
- `RouteServiceProvider::HOME`, `Authenticate`, `RedirectIfAuthenticated`

User workflows:

- `/kullanici/{slug}` profile
- `/kullanici/{slug}/guncelle` edit profile
- `/kullanici/sms-aktivasyon/{slug}` GET/POST SMS activation
- `/kullanici/ihaleler/{slug}` user tender page
- `/kullanici/ihaleler/favoricrud/{slug}` and `/updateFavoritePosts/{slug}` favorites
- `PUT /ihaleler/{slug}` bid flow
- `/fastbuy/{slug}` fast buy
- `/tenderUserPermissionMail/{slug}` tender permission mail/SMS/PDF flow

Admin workflows:

- `/admin/home` dashboard
- `/admin/banks` CRUD
- `/admin/documents` CRUD
- `/admin/properties` CRUD, property type partials, show page, clone, active/passive tender status
- `/admin/properties/image/{slug}` image page, upload, delete
- `/admin/archive-files/{slug}` upload, download, delete
- `/admin/users` CRUD, custom mail, bank contract download
- `/admin/logs`, `/admin/logs/mailSms`, `/admin/logs/mailView/{log}`, log PDF download
- `/admin/tenderReportDownload/{id}` tender report PDF
- `/admin/getbankId/{id}`, `/getDistricts/{id}`, `/getNeighborhoods/{id}` AJAX helpers
- `IsAdmin`, `PropertyPolicy`, `UserPolicy`, log viewer authorization

API and realtime:

- `POST /api/rest/user/authenticate`
- `GET /api/rest/realty/all` behind `jwt.verify`
- `routes/channels.php` private `posts.{postId}` authorization
- `TenderOfferValueUpdateEvent`
- Echo/Pusher client setup in `resources/js/bootstrap.js` and listing detail Blade
- `beyondcode/laravel-websockets` dashboard/statistics routes until a replacement is approved

Documents, queue, and assets:

- DOMPDF templates under `resources/views/mail/pdf-templates`
- Mail classes under `app/Mail`
- SMS helper `app/Helpers/SmsSend.php`
- Scheduler commands `tender:everyminute` and `tender:offerrequest`
- Queue worker behavior from `app/Console/Kernel.php`
- Storage-backed listing images, archive files, bank logos, public assets, Mix manifests
- Admin/public frontend plugin assets: DataTables, Summernote, Dropzone, Lightbox, datepicker, masks, Bootstrap, jQuery

## Package Decision Points

Make these decisions before the first dependency edit in the stage where they become blockers. Record each decision in a stage note before implementation.

1. Framework ladder:
   - Use staged upgrades: Laravel 8 to 9, then 9 to 10, then 10 to 11, then 11 to 12.
   - Do not jump directly to Laravel 12.

2. WebSockets:
   - Current: `beyondcode/laravel-websockets 1.14.1`.
   - Blocker: supports through Laravel 10 and is abandoned.
   - Decision before Laravel 11/12: keep through Laravel 10 only if checks pass; choose Laravel Reverb or another Pusher-compatible replacement before Laravel 12.
   - Must preserve: private channel auth, bid update event names/payloads, Echo/Pusher client behavior, local live bidding verification.

3. CORS:
   - Current: `fruitcake/laravel-cors 2.2.0`.
   - Blocker: supports through Laravel 9.
   - Decision before Laravel 10: migrate to framework CORS while preserving `config/cors.php` behavior and API access.

4. JWT:
   - Current: `tymon/jwt-auth dev-develop`.
   - Blocker: installed line supports through Laravel 9.
   - Decision before Laravel 10/11: prove a compatible `tymon/jwt-auth` path or replace with behavior-compatible JWT middleware.
   - Must preserve: `/api/rest/user/authenticate` response shape, `jwt.verify`, protected realty endpoint.

5. Slugs:
   - Current: `cviebrock/eloquent-sluggable 8.0.8`.
   - Blocker: current installed line is Laravel 8-only.
   - Decision before Laravel 9: upgrade to a compatible line or replace with behavior-equivalent slug generation.
   - Must preserve: existing user/property/post slug generation and update rules.

6. DOMPDF:
   - Current: `barryvdh/laravel-dompdf 2.2.0`.
   - Blocker for Laravel 12: current line supports through Laravel 11.
   - Decision before Laravel 12: upgrade or replace while preserving facade/config behavior, remote assets, paper settings, Turkish text, PDF templates, downloads.

7. Laravel UI/auth scaffolding:
   - Current: `laravel/ui 3.4.6`.
   - Blocker: supports Laravel 8/9.
   - Decision before Laravel 10: remove runtime dependency only if current generated routes/controllers/views remain preserved, or choose a compatible path.
   - Must preserve: Bootstrap Blade login/register/password behavior and custom registration fields.

8. Sanctum:
   - Current: `laravel/sanctum 2.15.1`.
   - Blocker: supports through Laravel 9.
   - Decision before Laravel 10: upgrade only if token table/config behavior remains compatible; current active API auth appears JWT-based, but Sanctum route/table must not break.

9. Sitemap:
   - Current: `spatie/laravel-sitemap 6.4.0`.
   - Blocker: supports through Laravel 10.
   - Decision before Laravel 11/12: upgrade or replace with equivalent sitemap generation/output behavior.

10. Intervention Image:
    - Current: `intervention/image 2.7.2`.
    - Decision before any major version bump: keep v2 if compatible or adapt all `Image::make` upload/resizing code with explicit image upload verification.

11. Dev tooling:
    - Current blockers include `facade/ignition`, `nunomaduro/collision`, old `laravel/sail`, PHPUnit 9, Symfony 5, Flysystem 1, Monolog 2, Carbon 2.
    - Decision per stage: update only the minimum dev/runtime tooling needed for the target Laravel version.

## Branch And Rollback Discipline

Use one branch/checkpoint per approved stage.

Before every stage:

- Record `git status --short`.
- Save route baseline: `php artisan route:list --json > docs/upgrade/baseline-routes-l8.json` or the stage-specific equivalent if documentation output is approved.
- Record `composer show --direct`.
- Record `composer why-not laravel/framework ^<target>`.
- Confirm the dirty worktree belongs to current approved work or pre-existing user edits.

Rollback checkpoint for every stage:

- Git commit or tag the stage only after verification passes.
- If Composer resolution fails, rollback is the stage branch reset to its pre-stage commit. Do not reset unrelated user edits.
- If route/view/test verification fails after code edits, stop at the failed stage, document exact failing files/routes, and do not proceed to the next Laravel version.
- If a package replacement changes behavior, rollback the package decision and return to the previous verified stage.

Recommended checkpoint names:

- `upgrade/baseline-l8`
- `upgrade/l9-compat`
- `upgrade/l10-compat`
- `upgrade/l11-compat`
- `upgrade/l12-compat`
- `upgrade/l12-readiness-review`

## Stage 0 - Baseline Freeze And Coverage Harness

Goal: create an exact local behavior map before any code or dependency change.

Allowed touch scope after approval:

- Documentation: `docs/upgrade/*`
- Optional tests: `tests/Feature/*`, `tests/Unit/*`, `tests/TestCase.php`, `tests/CreatesApplication.php`
- Optional test fixtures/factories only if needed: `database/factories/*`, `database/seeders/*`

Do not touch:

- `composer.json`, `composer.lock`, app runtime code, migrations, views, public assets, `.env`

Required actions:

1. Snapshot routes:
   - Save JSON route list.
   - Identify duplicate user tender/favorite routes in `routes/web.php` and preserve resulting route behavior.
2. Build a workflow checklist from the protected inventory above.
3. Add smoke tests or manual scripts only after approval.
4. Record current DB migration state without running schema-changing migrations.
5. Confirm whether `2022_12_21_183247_add_archive_folder_to_posts_table` is pending locally, because archive code uses `posts.archive_folder`.

Verification gate:

- `composer validate`
- `php artisan --version`
- `php artisan route:list`
- `php artisan view:cache`
- `php artisan test`
- Manual route/page checklist prepared for public, auth, user, admin, API, realtime, PDF, queue, assets.

Rollback checkpoint:

- If any baseline command fails, stop and document the failure. Do not begin Laravel 9.

## Stage 1 - Laravel 8 To 9

Goal: move the framework to Laravel 9 while preserving the Laravel 8 app skeleton and route behavior.

Allowed touch scope after approval:

- `composer.json`, `composer.lock`
- `app/Exceptions/Handler.php`
- `app/Http/Kernel.php`
- `app/Http/Middleware/*`
- `app/Providers/*`
- `config/app.php`, `config/auth.php`, `config/cors.php`, `config/filesystems.php`, `config/logging.php`, `config/mail.php`, `config/sanctum.php`, `config/sluggable.php`
- `routes/web.php`, `routes/api.php`, `routes/channels.php`
- Compatibility-only test updates under `tests/*`

Package decisions in this stage:

- Upgrade Laravel framework and first-party packages to Laravel 9-compatible versions.
- Resolve `cviebrock/eloquent-sluggable` before or during this stage.
- Keep `laravel/ui` only if the selected version supports Laravel 9 and auth behavior remains unchanged.
- Keep `tymon/jwt-auth` only if the selected line supports Laravel 9 and API checks pass.
- Confirm `fruitcake/laravel-cors` remains valid only for this stage; plan its removal before Laravel 10.

Implementation notes:

- Preserve `Auth::routes()` behavior.
- Preserve route middleware aliases: `admin`, `bank`, `jwt.verify` or their exact current equivalents.
- Normalize only compatibility issues needed for Laravel 9. For example, `APIController::class` casing in `routes/api.php` may be corrected only in an approved compatibility edit, with API route output compared before and after.
- Avoid skeleton modernization unless required.

Verification gate:

- `composer validate`
- `composer why-not laravel/framework ^9.0`
- `composer update --with-all-dependencies` only after approval
- `php artisan --version` reports Laravel 9
- `php artisan route:list` route count and names compared to baseline
- `php artisan view:cache`
- `php artisan test`
- Public/auth/user/admin/API smoke checks from Stage 0

Rollback checkpoint:

- If route count/name/middleware changes without an approved reason, rollback Stage 1 and fix the plan.

## Stage 2 - Laravel 9 To 10

Goal: reach Laravel 10 with framework CORS, compatible auth/API packages, and unchanged workflows.

Allowed touch scope after approval:

- `composer.json`, `composer.lock`
- `app/Http/Kernel.php`
- `app/Http/Middleware/*`
- `app/Http/Controllers/ApiController.php`
- `config/cors.php`, `config/sanctum.php`, `config/auth.php`, `config/jwt.php`
- `routes/api.php`, `routes/web.php`
- Tests under `tests/*`

Package decisions in this stage:

- Remove or replace `fruitcake/laravel-cors` with Laravel framework CORS.
- Upgrade Sanctum to a Laravel 10-compatible version, or document why it remains unused but installed.
- Decide the Laravel 10-compatible JWT package path.
- Confirm `beyondcode/laravel-websockets` remains temporarily supported through Laravel 10.
- Upgrade dev tools: Collision, Ignition replacement, PHPUnit path as required.

Implementation notes:

- Keep API route URIs unchanged.
- Keep `jwt.verify` middleware behavior and error format unchanged.
- Preserve CORS headers for `/api/rest/user/authenticate`, `/api/rest/realty/all`, and `sanctum/csrf-cookie`.
- Do not replace WebSockets in this stage unless Laravel 10 checks require it.

Verification gate:

- `composer validate`
- `composer why-not laravel/framework ^10.0`
- `php artisan --version` reports Laravel 10
- `php artisan route:list`
- `php artisan view:cache`
- `php artisan test`
- API auth and protected realty endpoint checks
- Broadcast auth endpoint check
- Admin/public page smoke checks

Rollback checkpoint:

- If JWT, CORS, or auth behavior changes, rollback Stage 2 package decisions before continuing.

## Stage 3 - Laravel 10 To 11

Goal: reach Laravel 11 without forcing a Laravel 11 skeleton rewrite.

Allowed touch scope after approval:

- `composer.json`, `composer.lock`
- `bootstrap/app.php` only if required by the selected Laravel 11 compatibility approach
- `app/Console/Kernel.php`
- `app/Http/Kernel.php`
- `app/Providers/*`
- `routes/console.php`, `routes/channels.php`, `routes/web.php`, `routes/api.php`
- `config/*` files directly affected by upgraded packages
- Tests under `tests/*`

Package decisions in this stage:

- Decide whether to keep legacy kernel/provider structure or adopt minimal Laravel 11 bootstrap changes. Prefer the smallest behavior-preserving change.
- Upgrade/replace `spatie/laravel-sitemap` before it blocks Laravel 11.
- Decide WebSocket replacement timing. If `beyondcode/laravel-websockets` cannot stay, replace with a Pusher-compatible alternative and verify live bidding before proceeding.
- Confirm DOMPDF remains valid through Laravel 11.

Implementation notes:

- Preserve scheduled commands:
  - `tender:everyminute`
  - `tender:offerrequest`
  - `queue:work --once` schedule behavior
- Preserve broadcast channels and event payloads.
- Preserve admin log viewer route/view behavior if `rap2hpoutre/laravel-log-viewer` changes.
- Avoid moving routes or middleware into new Laravel 11 style unless required and verified.

Verification gate:

- `composer validate`
- `composer why-not laravel/framework ^11.0`
- `php artisan --version` reports Laravel 11
- `php artisan route:list`
- `php artisan view:cache`
- `php artisan test`
- `php artisan schedule:list` if available
- Run scheduler commands locally in dry/safe conditions where possible
- Realtime bid update manual/local verification if WebSockets changed

Rollback checkpoint:

- If Laravel 11 bootstrap changes hide middleware, providers, channels, or schedules, rollback and reapply with explicit mappings.

## Stage 4 - Laravel 11 To 12

Goal: reach Laravel 12 with every protected workflow still equivalent.

Allowed touch scope after approval:

- `composer.json`, `composer.lock`
- `bootstrap/app.php`
- `app/Http/Kernel.php` and middleware only if the final Laravel 12 structure requires mapping changes
- `app/Providers/*`
- `config/dompdf.php`, `config/filesystems.php`, `config/broadcasting.php`, `config/websockets.php` or replacement config
- `resources/js/bootstrap.js`, `webpack.mix.js`, `package.json`, `package-lock.json` only if asset/realtime package changes are approved
- Controllers/events/mail/views only for Laravel 12 compatibility fixes with before/after workflow verification
- Tests under `tests/*`

Package decisions in this stage:

- Resolve final Laravel 12 blockers from `composer why-not laravel/framework ^12.0`.
- Upgrade or replace DOMPDF with PDF output comparison.
- Finalize WebSocket replacement if not already done.
- Confirm JWT compatibility on Laravel 12.
- Confirm Sitemap compatibility on Laravel 12.
- Confirm Sluggable compatibility on Laravel 12.
- Confirm Intervention Image compatibility; avoid v3 API changes unless all image upload code is adapted and verified.
- Remove/replace obsolete dev packages.

Implementation notes:

- Keep route URIs/names/methods/middleware equivalent to the Stage 0 baseline unless the user approves a documented change.
- Keep current Blade auth and admin UI behavior.
- Keep storage disk paths and generated public URLs stable.
- Keep PDF filenames, paper settings, template data, and remote image behavior stable.
- Keep broadcast auth and Echo client channel names stable.

Verification gate:

- `composer validate`
- `composer why-not laravel/framework ^12.0` has no relevant blockers
- `php artisan --version` reports Laravel 12
- `php artisan route:list`
- `php artisan view:cache`
- `php artisan test`
- Public/auth/user/admin/API/realtime/PDF/queue/manual matrix completed
- Route JSON compared against Stage 0 for URI, method, name, action, middleware

Rollback checkpoint:

- If any protected route/page/workflow cannot be verified, stop at Laravel 11 or the last known good stage. Do not call the Laravel 12 upgrade ready.

## Stage 5 - Final Review And Manager Approval

Goal: separate "code reaches Laravel 12 locally" from "ready for real traffic".

Allowed touch scope after approval:

- `docs/upgrade/*`
- Tests and fixes only if the reviewer/manager explicitly approves follow-up implementation

Required independent reviews:

- Reviewer: check package compatibility, route diffs, regressions, missing tests, unsafe assumptions.
- Manager: check end-to-end readiness across routes, pages, workflows, packages, local rollback, production prerequisites.

Manager review must answer:

- Is Laravel 12 locally verified?
- Which workflows were manually tested?
- Which workflows are only covered by static review?
- Which package replacements changed risk?
- What production/live prerequisites remain?
- What rollback path exists from Laravel 12 to the previous verified stage?

Do not call the upgrade production-ready until production environment parity, secrets, queues, scheduler, storage, WebSocket endpoint, mail/SMS providers, database backups, and deployment rollback are explicitly verified by the user-approved production process.

## File And Module Touch Matrix

Composer and dependency metadata:

- May touch only in approved implementation stages: `composer.json`, `composer.lock`, `package.json`, `package-lock.json`, `webpack.mix.js`
- Never touch in documentation-only turns.

Routes:

- `routes/web.php`: preserve all public, auth-derived, user, admin, PDF, AJAX, archive, log, favorite, bid routes.
- `routes/api.php`: preserve JWT authenticate and protected realty endpoints.
- `routes/channels.php`: preserve private channel authorization.
- `routes/console.php`: preserve console commands.

HTTP layer:

- `app/Http/Kernel.php`: middleware alias/group compatibility only.
- `app/Http/Middleware/*`: Laravel compatibility only; preserve `IsAdmin`, `CheckPostBank`, `DetectSubDomain`, `JwtMiddleware`.
- `app/Http/Requests/StoreBankRequest.php`: validation compatibility only.
- `app/Exceptions/Handler.php`: Laravel exception compatibility only.

Controllers:

- Public/user: `HomeController`, `UserController`, `User/TenderController`, `ApiController`.
- Admin: `Admin/BankController`, `Admin/DocumentController`, `Admin/HomeController`, `Admin/PropertyController`, `Admin/UserController`, `Admin/AddressController`.
- Touch only when a stage fails due to Laravel/package API changes.

Models and data:

- `app/Models/*`, migrations, factories, seeders.
- Touch only for compatibility with slugging, casts, factories, or tests.
- Do not alter schema semantics during framework upgrade unless separately approved.

Realtime:

- `app/Events/*`, `routes/channels.php`, `config/broadcasting.php`, `config/websockets.php` or replacement config, `resources/js/bootstrap.js`, listing detail Blade.
- Touch only during approved WebSocket/realtime stage.

Mail, SMS, PDF:

- `app/Mail/*`
- `app/Helpers/SmsSend.php`
- `resources/views/mail/*`
- `resources/views/mail/pdf-templates/*`
- `config/mail.php`, `config/dompdf.php`
- Touch only for Laravel mail/PDF compatibility.

Views and assets:

- `resources/views/*`, `resources/js/*`, `resources/css/*`, `public/js/*`, `public/css/*`, `public/assets/*`.
- Touch only if a stage verification failure proves a compatibility need.
- Preserve current Bootstrap/jQuery/admin plugin behavior.

Config:

- `config/app.php`, `auth.php`, `broadcasting.php`, `cache.php`, `cors.php`, `database.php`, `dompdf.php`, `filesystems.php`, `jwt.php`, `logging.php`, `mail.php`, `queue.php`, `sanctum.php`, `services.php`, `session.php`, `sluggable.php`, `view.php`, `websockets.php`.
- Touch only for the package/framework being upgraded in that stage.

Tests:

- `tests/*` may be expanded after approval to protect route/page/workflow behavior.
- Test additions should be behavior-locking, not feature redesign.

## Minimum Verification Matrix Per Stage

Automated commands:

- `composer validate`
- `composer why-not laravel/framework ^<target>`
- `php artisan --version`
- `php artisan route:list`
- `php artisan view:cache`
- `php artisan test`

Public checks:

- Home page renders.
- Search filters render and submit.
- Listing detail renders.
- Bank/subdomain filtering works.
- Static content pages render.

Auth/user checks:

- Login, logout, register, password reset pages render and submit correctly.
- Profile show/edit opens.
- SMS activation page validates.
- Favorite add/remove works.
- Tender permission mail flow works.
- Bid flow works.
- Fast buy works.

Admin checks:

- Dashboard opens.
- Banks CRUD works.
- Documents CRUD works.
- Properties index/create/edit/show/delete works.
- Property image upload/delete works.
- Property clone works.
- Tender active/passive status works.
- Archive upload/download/delete works.
- Users CRUD works.
- Custom mail with contract PDFs works.
- Logs and log detail pages work.
- Tender report PDF downloads and opens.

API/realtime checks:

- JWT authenticate works.
- Protected realty API works.
- Broadcast auth works.
- Private `posts.{postId}` channel authorizes the expected users only.
- Live bid event updates the listing detail UI.

Background/document checks:

- Scheduler commands run locally without unintended external side effects.
- Queue processes one local mail job.
- DOMPDF contract and tender report render.
- Sitemap/static asset/storage link behavior remains stable.

## Stop Conditions

Stop implementation and report before proceeding if any of these happen:

- Composer cannot resolve the target stage without an unapproved package replacement.
- `php artisan route:list` fails.
- Route URI/name/method/middleware changes without approval.
- `php artisan view:cache` fails.
- Auth, bid, admin property, PDF, JWT, or realtime behavior cannot be verified.
- A package replacement requires redesign rather than compatibility adaptation.
- Existing dirty worktree changes make a safe stage diff impossible to isolate.

