# Upgrade Assessment: Laravel 8.64.0 → Laravel 13 + PHP 8.4

**Verdict: High complexity.** This is a 5-major-version jump with Livewire 2→3, Mix→Vite, abandoned packages, incomplete Jetstream teams, and production SOAP/payment integrations.

**Baseline**

| Item | Value |
|------|-------|
| Laravel installed | **8.64.0** (`composer.lock` / `Application::VERSION`) |
| Laravel required | `^8.54` in `composer.json` |
| PHP CLI (current machine) | **8.4.22** (incompatible with Laravel 8) |
| `php artisan --version` | Fatals on PHP 8.4 |
| Auth stack | Jetstream 2.4.3 + Fortify 1.8.2 + Sanctum 2.11.4 + Livewire 2.6.7 |

> Assessment only — no project files were modified during analysis.

---

## 1. Composer snapshot

| Constraint | Value |
|---|---|
| `laravel/framework` | `^8.54` → installed **v8.64.0** |
| `php` | `^7.3\|^8.0` |
| Auth stack | Jetstream **2.4.3** + Fortify **1.8.2** + Sanctum **2.11.4** + Livewire **2.6.7** |

---

## 2. Composer package matrix

Legend: ✅ compatible · ⚠️ version bump required · ❌ not supported · 🔄 replace/remove

| Package | Installed | Target for L13 | L9 | L10 | L11 | L12 | L13 | PHP 8.4 | Abandoned? | Recommendation |
|---|---|---|---|---|---|---|---|---|---|---|
| `laravel/framework` | 8.64.0 | ^13.0 | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ (L11+) | No | Step 8→9→10→11→12→13 |
| `laravel/jetstream` | 2.4.3 | ^5.5 | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | Maintenance-only (no new features) | Stay on Jetstream 5.x or migrate to Livewire starter kit later |
| `laravel/fortify` | 1.8.2 | latest 1.x (^1.20+) | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | No | Upgrade with Jetstream |
| `laravel/sanctum` | 2.11.4 | ^4.0 | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | No | Publish migrations at L11+ |
| `laravel/tinker` | 2.6.2 | ^3.0 | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | No | ^3.0 at L13 |
| `livewire/livewire` | 2.6.7 | ^3.x | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | ✅ | No | **Mandatory Livewire 3 migration** (23 components) |
| `diglactic/laravel-breadcrumbs` | 7.0.1 | ^10.0 | ⚠️ 9.x | ✅ 10.x | ✅ | ✅ | ✅ | ✅ | No | 9.x at L9; 10.x from L10+ |
| `fruitcake/laravel-cors` | 2.0.4 | — | 🔄 | — | — | — | — | N/A | Superseded | **Remove**; use framework CORS |
| `guzzlehttp/guzzle` | 7.4.0 | ^7.9+ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | No | Bump within 7.x |
| `joedixon/laravel-translation` | 1.1.2 | — | ⚠️ 2.x? | ❌ | ❌ | ❌ | ❌ | ❌ | Effectively unmaintained | Replace: fork, `ElegantEngineeringTech/laravel-translator`, or native `lang/` UI |
| `ricorocks-digital-agency/soap` | 1.5.0 | ^4.0 | ⚠️ 1.x | ⚠️ 2.x | ⚠️ 2–3 | ⚠️ 3.x | ✅ 4.x | ✅ (3+) | No | Bump per Laravel major; app mostly uses `Http::` anyway |
| `barryvdh/laravel-debugbar` | 3.6.3 | latest 3.x | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | ✅ | No | Keep as --dev |
| `facade/ignition` | 2.15.0 | — | 🔄 | 🔄 | 🔄 | 🔄 | 🔄 | ❌ | Yes (L8-era) | **`spatie/laravel-ignition`** |
| `fakerphp/faker` | 1.16.0 | latest | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | No | Bump |
| `kevincobain2000/laravel-erd` | 1.1 | — | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | Stale (docs: L6/L8) | Remove; optional `recca0120/laravel-erd` |
| `laravel/sail` | 1.12.0 | latest | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | ✅ | No | Bump each major |
| `mockery/mockery` | 1.4.4 | ^1.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | No | Bump |
| `nunomaduro/collision` | 5.10.0 | ^8.x | ⚠️ 6 | ⚠️ 7 | ⚠️ 8 | ✅ | ✅ | ✅ | No | Match each Laravel major |
| `phpunit/phpunit` | 9.5.10 | ^12.0 | ⚠️ 9 | ⚠️ 10 | ⚠️ 11 | ⚠️ 11 | ✅ 12 | ✅ | No | Match each Laravel major |

---

## 3. npm / frontend

| Item | Finding |
|---|---|
| Build tool | **Laravel Mix 6** (`webpack.mix.js` → `admin.js` + `admin.scss`) |
| Vite | **Not present** — migration required for modern Laravel skeleton / Jetstream 5 |
| Alpine | ^3.0.6 (OK with Livewire 3) |
| Tailwind | **2.2** (Jetstream/Livewire 3 typically expect Tailwind 3+) |
| Bootstrap | 5.1 (admin stack) |
| Axios | 0.21 (outdated; security bump recommended) |
| Mix required? | Yes today; **Vite migration recommended/required** when adopting Jetstream 5 + current Laravel tooling |

---

## 4. Application inspection summary

| Area | Status | Risk |
|---|---|---|
| Custom middleware | `Language` + standard L8 stack; Kernel uses `$routeMiddleware` + Fruitcake CORS | High at L11 structure change |
| Providers | Classic L8 list in `config/app.php`; AppServiceProvider shares `Setting` globally | Medium |
| Auth | Jetstream Livewire + Fortify; teams **enabled in config but not on User** | High (config/code mismatch) |
| Livewire | **23** components under `App\Http\Livewire`; `wire:model.defer`, `@this`, file uploads | **Highest** |
| API | Sanctum stub `/api/user` only | Low |
| Jobs / schedule | None / empty | Low |
| Mail | `IsibMail` (`build()` style) | Low–medium |
| Uploads | `FileUploadController` + Livewire `WithFileUploads`; `FILESYSTEM_DRIVER` env | Medium |
| Payments | **Thawani** — hardcoded keys/URLs in `ThawaniPaymentController` | High (ops/security) |
| Third-party APIs | Dhofar + ROP SOAP via `Http::` XML; TLS verify often off | High |
| Helpers | No app `helpers.php`; dead `App\CPU\Helpers` import | Low |
| Deprecated Laravel | Widespread `$dates` (~30+ models); `$routeMiddleware`; Fruitcake CORS | High |
| PHP 8.4 | Artisan already broken; octal-looking config keys in vehicle/dhofar configs | Medium |
| DB | MySQL; `whereRaw` in `VeOffer`; heavy `DB::table` in FrontendController | Medium |

### Custom middleware (`app/Http/Middleware`)

| Class | Purpose |
|--------|---------|
| **Language** | Sets locale from `Session::get('lang')`, else `app.fallback_locale`. Registered on `web` group. |
| **Authenticate** | Redirect guests to `route('login')` for non-JSON. |
| **RedirectIfAuthenticated** | Authenticated users → `RouteServiceProvider::HOME` (`/admin`). |
| **TrustProxies** | Standard proxy headers (incl. AWS ELB). |
| **TrustHosts** | Trusts app URL subdomains (commented out in Kernel global stack). |
| **TrimStrings** | Skips password fields. |
| **EncryptCookies** | Empty `$except`. |
| **VerifyCsrfToken** | Empty `$except`. |
| **PreventRequestsDuringMaintenance** | Empty `$except`. |

### Service providers (`app/Providers`)

| Provider | Registers / boots |
|----------|-------------------|
| **AppServiceProvider** | Shares `Setting` (by locale) to all views; Eloquent `Builder::macro('search')`. |
| **AuthServiceProvider** | Empty `$policies`; `registerPolicies()` only — **FaqPolicy not mapped**. |
| **RouteServiceProvider** | Loads `routes/web.php` + `routes/api.php`; HOME=`/admin`; rate limiter `api`. |
| **FortifyServiceProvider** | Fortify actions + login/2FA rate limiters. |
| **JetstreamServiceProvider** | `DeleteUser` action; API token permissions. |
| **EventServiceProvider** | `Registered` → email verification listener. |
| **BroadcastServiceProvider** | Present; **commented out** in `config/app.php`. |

### Livewire components (`app/Http/Livewire`)

| Component | Role |
|-----------|------|
| `Dashboard` | Admin home |
| `Users`, `CreateUser` | User CRUD |
| `Faqs`, `CreateFaq`, `EditFaq` | FAQ admin |
| `Settings` | App settings + **WithFileUploads** |
| `Insureds` | Insureds CRUD |
| `Travels`, `Domestics` | Admin insurance stubs |
| `FollowUp` | Follow-up form |
| `Form`, `InsuereCreate` | Thin wrappers |
| `Vehicles`, `VehiclesForm` | Frontend vehicle quote flow / ROP |
| `Vehicles\Form`, `Offer`, `Payment`, `Rop` | Vehicle subflow |
| `Admin\Vehicles`, `VehiclesOffers` | Admin vehicle CRUD |
| `Admin\Insurers`, `InsurersOffers` | Insurers + logos (**WithFileUploads**) |

### Third-party integrations

| Service | How | Notes |
|---------|-----|-------|
| **Dhofar Insurance** | `Http::` XML POST | `buyonline.dhofarinsurance.com` — credentials inlined |
| **ROP / oman-insurance** | `Http::` SOAP XML | Vehicle/License info services |
| **Thawani** | curl + `file_get_contents` | Production checkout API; keys hardcoded |
| **ricorocks soap** | Composer dep | Mostly unused; real calls use `Http::` |

---

## 5. Breaking changes by major version

### Laravel 8 → 9 (PHP ≥ 8.0.2)

- Replace `facade/ignition` → `spatie/laravel-ignition`
- Flysystem 3 (disk config / S3 / custom `img` disk)
- SwiftMailer → Symfony Mailer (`MAIL_MAILER`, not `MAIL_DRIVER`)
- Remove `fruitcake/laravel-cors` (framework CORS)
- HTTP client default timeout 30s (SOAP/quote calls may need explicit timeout)
- Jetstream / Livewire / breadcrumbs major bumps

### Laravel 9 → 10 (PHP ≥ 8.1)

- **`$dates` removed** → migrate all models to `$casts`
- `$routeMiddleware` → `$middlewareAliases`
- Sanctum ^3.2; Ignition ^2; Collision ^7 / PHPUnit ^10
- `minimum-stability`: `stable`
- Language directory publish model changes

### Laravel 10 → 11 (PHP ≥ 8.2) — largest structural jump

- Optional but expected: slim `bootstrap/app.php`, middleware move out of Kernel
- Jetstream ^5 + **Livewire ^3** (namespace `App\Livewire`, `wire:model.live`, events API)
- Sanctum ^4 — **publish migrations**
- Mix → Vite for Jetstream assets
- Floating-point / modifying-columns migration caveats (MySQL)

### Laravel 11 → 12 (PHP ≥ 8.2; 8.4 OK)

- Carbon 3
- PHPUnit ^11
- `image` validation excludes SVG by default (logo uploads)
- Local disk default root change if relying on framework defaults
- Soap package → ^3.x

### Laravel 12 → 13 (PHP ≥ 8.3; **8.4 OK**)

- `laravel/framework` ^13, `tinker` ^3, PHPUnit ^12
- CSRF / origin forgery protection config review
- Cache `serializable_classes` default `false`
- Cache/session prefix hyphenation if using defaults
- MySQL upsert / DELETE+JOIN nuances
- Soap → ^4.0

---

## 6. Automated tests

**Present:** Jetstream scaffold Feature tests (auth, profile, 2FA, API tokens, etc.) + example Unit/Feature tests under `tests/`.

**Missing for this product (critical before upgrade):**

1. Vehicle quote → offer → payment (Thawani) happy path + failure
2. ROP / license lookup SOAP responses
3. Dhofar quote/search SOAP responses
4. Travel + domestic insurance flows
5. Customer document upload/delete
6. Admin Livewire CRUD (users, insurers, vehicles, FAQs, settings)
7. Locale / `Language` middleware behavior
8. Auth admin gate (`/admin`, `auth:sanctum`)
9. Mail send with/without PDF attachment
10. Coupon / `selected_offer` payment status updates

Without these, regressions in payment/SOAP will only be found in production.

---

## 7. Step-by-step upgrade plan

### A. Preparation & backup

1. Full git branch (e.g. `upgrade/laravel-13`) — do not upgrade on `main` first
2. DB dump + `storage/` backup + `.env` copy
3. Inventory secrets currently hardcoded (Thawani, Dhofar, ROP) → plan env migration
4. Document current production PHP (likely older than CLI 8.4)
5. Add critical Feature tests listed above on **current** Laravel 8 (on compatible PHP)
6. Decide strategy for `joedixon/laravel-translation` and `laravel-erd` before L10+

### B. Temporary PHP for Laravel 8 work

| Goal | PHP |
|---|---|
| Keep Laravel 8 runnable while preparing | **PHP 8.0.x** (matches `^7.3\|^8.0`; avoids 8.4 fatals) |
| After reaching Laravel 11 | PHP **8.2+** |
| Final Laravel 13 | PHP **8.3 or 8.4** (8.4 is fine for L13) |

Do **not** stay on PHP 8.4 while still on Laravel 8.

### C. Per-major required changes

#### → Laravel 9

- Ignition swap
- Remove Fruitcake CORS
- Flysystem / Mailer env updates
- Bump Jetstream / Sanctum / Livewire / breadcrumbs
- Test file storage + mail

#### → Laravel 10

- Convert all `$dates` → `$casts`
- Rename middleware property
- Bump Sanctum / Ignition / Collision / PHPUnit
- Set `minimum-stability` to `stable`
- Retest models / dates

#### → Laravel 11

- Jetstream 5 + Livewire 3 migration (components, views, `defer` → `live`)
- Vite
- Sanctum 4 — publish migrations
- Decide `bootstrap/app.php` structure
- Fix teams config (disable teams or implement properly)
- Replace translation package

#### → Laravel 12

- Carbon 3
- PHPUnit 11
- Soap ^3
- Validate SVG / image rules
- Filesystem local disk defaults

#### → Laravel 13

- Framework ^13
- Tinker ^3
- PHPUnit 12
- Soap ^4
- CSRF / origin + cache `serializable_classes`
- Pin `CACHE_PREFIX` / `SESSION_COOKIE` if needed
- Deploy on PHP 8.3 / 8.4

### D. Package replacements (when upgrading)

| Remove / stop | Use instead |
|---|---|
| `fruitcake/laravel-cors` | Built-in Laravel CORS |
| `facade/ignition` | `spatie/laravel-ignition` |
| `joedixon/laravel-translation` | Fork / alternative translator / native lang |
| `kevincobain2000/laravel-erd` | Remove (dev-only) |
| Laravel Mix | Vite |
| Livewire 2 | Livewire 3 |

### E. Database migration risks

- Sanctum migration republish (L11+)
- `password_resets` → `password_reset_tokens` (if not already)
- Column `change()` migrations without doctrine/dbal (L11+)
- Decimal / float column type changes
- Duplicate migrations under `database/migrations/mg/` — audit before running
- Session driver = database — verify sessions table after cache/session prefix changes (L13)

### F. Testing checklist

- [ ] `composer install` / artisan boots on target PHP
- [ ] Login / register / password update
- [ ] Admin Livewire pages load
- [ ] Vehicle quote + ROP + Dhofar
- [ ] Thawani create/get session + DB `pay_status`
- [ ] Document upload/delete
- [ ] Settings / insurer logo uploads
- [ ] Locale switching
- [ ] Email send
- [ ] Breadcrumbs
- [ ] Translation UI (if kept)
- [ ] `npm run build` (Vite) assets load

### G. Rollback plan

1. Keep previous release artifact + DB dump tagged per major
2. Deploy previous release if smoke tests fail
3. Restore DB only if migrations ran (prefer expand/contract; avoid destructive migrations mid-upgrade)
4. Feature flags / maintenance mode during payment cutover
5. Do not upgrade production PHP to 8.4 until Laravel ≥ 11 (preferably 12/13)

### H. Final deployment checklist

- [ ] PHP 8.3/8.4 with required extensions (`soap`, `curl`, `mbstring`, `openssl`, etc.)
- [ ] `.env`: `MAIL_MAILER`, `FILESYSTEM_DISK`, payment/SOAP secrets
- [ ] `php artisan migrate --force` on staging first
- [ ] `php artisan config:cache route:cache view:cache`
- [ ] `npm ci && npm run build`
- [ ] `storage:link` (+ custom `img` link if still used)
- [ ] TLS verify strategy for SOAP endpoints reviewed
- [ ] Thawani callback URLs verified
- [ ] Queue still `sync` (OK) / cron empty (OK)
- [ ] Monitoring on payment + quote endpoints for 48h

---

## 8. Complexity rating: **High**

### Why

1. **Five major Laravel versions** plus PHP 8.0 → 8.4
2. **Livewire 2 → 3** across 23 business components (largest app cost)
3. **Mix → Vite** and Tailwind 2 → 3
4. **Blocked packages** (`joedixon/laravel-translation`, ERD, Fruitcake, Ignition)
5. **External money/SOAP integrations** with hardcoded credentials and brittle XML
6. **Incomplete Jetstream teams** + widespread `$dates`
7. **No domain test coverage** for quote/payment paths

### Effort estimate

| Phase | Rough effort |
|-------|----------------|
| Preparation + critical tests | 1–2 weeks |
| Staged upgrades (8→13) | 3–6+ weeks (depends on Livewire/SOAP hardening) |
| Laravel 12→13 alone | Comparatively small once on 12 |

---

## Recommended sequence

```text
PHP 8.0
  → stabilize Laravel 8
  → add critical tests
  → Laravel 9
  → Laravel 10 ($dates)
  → Laravel 11 (Livewire 3 + Vite + package replacements)
  → Laravel 12
  → PHP 8.4
  → Laravel 13
```

---

## Official references

- [Upgrade to Laravel 9](https://laravel.com/docs/9.x/upgrade)
- [Upgrade to Laravel 10](https://laravel.com/docs/10.x/upgrade)
- [Upgrade to Laravel 11](https://laravel.com/docs/11.x/upgrade)
- [Upgrade to Laravel 12](https://laravel.com/docs/12.x/upgrade)
- [Upgrade to Laravel 13](https://laravel.com/docs/13.x/upgrade)
- [Laravel releases / PHP support](https://laravel.com/docs/13.x/releases)
