Laravel Production Readiness Review
Context
This skill performs a comprehensive, read-only production readiness audit of a Laravel
application. It evaluates the project across 6 dimensions and produces a scored, actionable
report.
Scope: Laravel 8.x through 12.x applications using Eloquent, Blade, Sanctum/Passport,
Queues, Horizon, Livewire, Inertia, and the broader Laravel ecosystem.
Tools covered: Composer, Artisan, Eloquent ORM, Laravel config system, Blade templates,
Laravel HTTP client, Queue workers, Horizon, Telescope, Pulse, Forge, Vapor, Envoyer.
This is a read-only audit. Modifying files during an audit would make the findings unreliable and could break the project. Only use Glob, Grep, and Read tools.
Rules
Step 1: Identify the Laravel Project
Orient yourself in the Laravel codebase. Use Glob to discover the project structure:
Glob: **/composer.json, **/artisan, **/config/*.php, **/routes/*.php
Glob: **/app/Http/Kernel.php, **/bootstrap/app.php, **/config/app.php
Glob: **/database/migrations/*.php, **/app/Models/*.php
Glob: **/.env*, **/.gitignore, **/Dockerfile, **/docker-compose.*
Glob: **/.github/workflows/*.{yml,yaml}
Read composer.json to determine:
- Laravel version (laravel/framework constraint)
- Key packages (Sanctum, Passport, Horizon, Telescope, Pulse, Livewire, Inertia, etc.)
- PHP version constraint
| Indicator |
What it tells you |
Watch out for |
laravel/sanctum |
API token / SPA auth |
Missing token expiration, no ability revocation |
laravel/passport |
OAuth2 provider |
Token lifetime too long, unused grant types |
laravel/horizon |
Queue monitoring |
Dashboard exposed without auth |
laravel/telescope |
Debug/dev tool |
Enabled in production, no auth gate |
laravel/pulse |
Production monitoring |
Dashboard auth not configured |
livewire/livewire |
Full-stack components |
Unprotected component methods, missing authorization |
inertiajs/inertia-laravel |
SPA bridge |
Over-sharing props, exposing server data to client |
spatie/laravel-permission |
Roles & permissions |
Missing authorization checks on routes |
| No queue driver config |
Sync queue |
Heavy operations blocking HTTP requests |
Also check the Laravel version to know which patterns apply:
- Laravel 11+: Slim skeleton — no
Http/Kernel.php, middleware in bootstrap/app.php, /up health route built-in
- Laravel 10 and below: Traditional structure —
Http/Kernel.php, Exceptions/Handler.php
Step 2: Run All Six Audits
Load and apply each reference checklist one at a time, in order. For each one, actually run
the Glob and Grep patterns to discover findings — don't guess or assume from the stack alone.
Read these files from references/:
security-checklist.md — secrets, injection, auth, CSRF, mass assignment, rate limiting
scalability-checklist.md — N+1 queries, eager loading, pagination, queues, caching
reliability-checklist.md — exception handling, logging, health checks, transactions
hardening-checklist.md — APP_DEBUG, session config, env validation, dependency pinning
code-quality-checklist.md — tests, debug helpers, type safety, structural anti-patterns
operational-readiness.md — CI/CD, deployment, .env.example, monitoring, rollbacks
For each finding, note the file path and line number. Vague findings ("somewhere in the
codebase there might be...") are not useful. Be specific.
Severity classification:
- CRITICAL — Actively dangerous; fix before deploying (e.g. hardcoded secret,
APP_DEBUG=true in production, SQL injection via DB::raw() with user input)
- WARNING — Meaningful risk or debt that should be addressed soon (e.g. missing rate limiting, no eager loading, no queue worker)
- SUGGESTION — Would improve quality or resilience but isn't a blocker (e.g. missing Telescope auth gate, no monitoring)
Credential Redaction (Mandatory)
When reporting findings that contain secrets, API keys, passwords, or tokens, ALWAYS redact
the actual value. Show only the first 4 characters followed by ••••••••. Never output full
credential values in the report. Example: sk_live_••••••••, AKIA••••••••, ghp_••••••••.
Step 3: Score Each Dimension
Score each dimension 0–10 using the rubric in references/report-template.md.
Quick reference:
| Score |
Meaning |
| 9–10 |
Production-grade |
| 7–8 |
Good — minor gaps only |
| 5–6 |
Acceptable — some risks |
| 3–4 |
Concerning — significant gaps |
| 0–2 |
Critical — not safe for production |
Overall rating:
- READY — All dimensions 7+
- ALMOST — Most dimensions 6+, none below 4
- NOT READY — Any dimension below 4
Step 4: Write the Report
Read references/report-template.md and produce the final report using that exact structure.
- Be specific, not generic. Don't say "consider adding rate limiting." Say: "No rate limiting on
POST /login — the throttle middleware is missing from routes/web.php:14. Add throttle:5,1 to the login route or configure RateLimiter::for('login', ...) in AppServiceProvider."
- Acknowledge what's working. Real Laravel projects always have some things done well. Find them and say so.
- Order findings by impact. The most dangerous issues should appear first.
- Explain the "why" in plain language. A brief, honest explanation of the real-world risk helps developers prioritize correctly.
- Give concrete, Laravel-specific fixes. Provide the actual Laravel code, Artisan command, or config change — not generic pseudocode.
- Reference CWE/OWASP when relevant. Include the CWE ID (e.g. CWE-798) so developers can look up the full context.
Tool Usage
- Glob — File discovery (configs, migrations, models, controllers, routes, tests)
- Grep — Pattern matching (secrets, anti-patterns, missing configurations)
- Read — Inspect specific files for context and line-level findings
- Never use Edit, Write, or Bash — this is a read-only audit
Tone
This audit is most useful when it's direct without being alarmist. A missing rate limiter is a
warning, not a catastrophe. An exposed APP_KEY or database password in source code is a
catastrophe. Calibrate your language accordingly.
When the project is in genuinely good shape, say so. When something is serious, be clear about
why it's serious. Developers trust audits that treat them as intelligent professionals who can
handle honest feedback.
Gotchas
Laravel 11+ has no Http/Kernel.php. Middleware is registered in bootstrap/app.php instead. Don't flag missing Kernel.php as an issue on Laravel 11+ projects — check the Laravel version first.
APP_DEBUG=true in .env isn't always a finding. The .env file is for local development. Only flag it if .env.production or deployment configs have it set to true, or if there's evidence the .env file is used in production (e.g., no .env.production and deployment scripts reference .env directly).
Missing tests isn't always WARNING-level. A brand new project with 2 controllers doesn't need 80% coverage. Calibrate the severity to the project's maturity — check git log age and migration count.
Telescope in composer.json isn't a vulnerability. Telescope is typically installed as a dev dependency (require-dev). Only flag it if it's in require (not require-dev) AND there's no auth gate in TelescopeServiceProvider.
Rate limiting may exist at the infrastructure level. Before flagging missing rate limiting, check for Nginx/Apache configs, Cloudflare rules, or load balancer settings. Note: you can't always see these from code alone — mention it as a caveat rather than a definitive finding.
Examples
Example finding (CRITICAL)
### 1. Hardcoded Stripe Key in Config — Security
**Severity:** CRITICAL
**Reference:** CWE-798
**File:** `config/services.php:18`
**Finding:** Stripe secret key is hardcoded instead of using `env()`:
`'secret' => 'sk_live_••••••••'`
**Why it matters:** This key is committed to git history and visible to anyone with repo access.
It grants full access to your Stripe account — charges, refunds, customer data.
**Fix:**
// config/services.php
'stripe' => [
'secret' => env('STRIPE_SECRET'),
],
// .env
STRIPE_SECRET={value from secrets manager}
Example finding (WARNING)
### 4. N+1 Query in OrderController — Scalability
**Severity:** WARNING
**File:** `app/Http/Controllers/OrderController.php:34`
**Finding:** `Order::all()` without eager loading, then accessing `$order->customer` in the
Blade view. With 100 orders, this makes 101 database queries.
**Fix:**
// Before
$orders = Order::all();
// After
$orders = Order::with('customer')->paginate(25);
Example "What You Did Well"
## What You Did Well
- Sanctum is properly configured with token expiration and ability scoping
- All models define explicit `$fillable` arrays — no mass assignment risk
- Migrations are well-structured with proper indexes on foreign keys
- Form Requests are used consistently across all controllers
- Queue jobs implement `ShouldQueue` with retry and backoff configuration
Anti-patterns
- Not a penetration test. This is a static code review, not an intrusive security assessment. It does not test running applications or exploit vulnerabilities.
- Not a compliance certification. This does not certify SOC 2, PCI-DSS, HIPAA, or GDPR compliance. It can identify common gaps, but formal compliance requires a qualified auditor.
- Not a replacement for automated scanning tools. For dependency vulnerability scanning, use
composer audit. For secret scanning, use gitleaks or trufflehog. This skill complements those tools with architectural and configuration review.
- Don't guess findings. Every finding must reference a specific file and line number discovered via Glob/Grep/Read. Never report an issue based on assumptions about the stack.
- Don't modify files. This is strictly read-only. Never use Edit, Write, or Bash tools during the audit.
References
references/security-checklist.md — 16 security checks with CWE references and Laravel-specific Grep patterns
references/scalability-checklist.md — Eloquent N+1, pagination, queues, caching, session drivers
references/reliability-checklist.md — Exception handling, logging channels, health checks, transactions
references/hardening-checklist.md — APP_DEBUG, Telescope/Debugbar exposure, cookie security, trusted proxies
references/code-quality-checklist.md — Pest/PHPUnit, debug helpers, Larastan, structural anti-patterns
references/operational-readiness.md — CI/CD, Forge/Vapor/Envoyer, monitoring, rollbacks
references/report-template.md — Report structure, scoring rubric, tone guidelines
1---2name: laravel-prod-ready3description: Run a comprehensive production readiness audit on a Laravel application. Use this skill whenever someone wants to know if their Laravel app is ready to ship, launch, or go live — even if they phrase it as "security check", "pre-launch review", "is this production-ready?", "audit my project", "code review before deploy", "go-live checklist", "deploy checklist", "launch readiness", "is this safe to deploy", or similar. Also trigger when someone asks for help with security vulnerabilities, finding hardcoded secrets, checking their CI/CD setup, evaluating the reliability/scalability of their Laravel backend, or asks "what am I missing before launch". This skill systematically evaluates a Laravel project across 6 dimensions (Security, Scalability, Reliability, Hardening, Code Quality, Operational Readiness) and produces a scored report with actionable, Laravel-specific fixes — not just a list of problems, but a clear picture of what's production-grade and what needs work.4license: MIT5---67# Laravel Production Readiness Review89## Context1011This skill performs a comprehensive, read-only production readiness audit of a Laravel12application. It evaluates the project across 6 dimensions and produces a scored, actionable13report.1415**Scope:** Laravel 8.x through 12.x applications using Eloquent, Blade, Sanctum/Passport,16Queues, Horizon, Livewire, Inertia, and the broader Laravel ecosystem.1718**Tools covered:** Composer, Artisan, Eloquent ORM, Laravel config system, Blade templates,19Laravel HTTP client, Queue workers, Horizon, Telescope, Pulse, Forge, Vapor, Envoyer.2021**This is a read-only audit.** Modifying files during an audit would make the findings unreliable and could break the project. Only use Glob, Grep, and Read tools.2223---2425## Rules2627### Step 1: Identify the Laravel Project2829Orient yourself in the Laravel codebase. Use Glob to discover the project structure:3031```32Glob: **/composer.json, **/artisan, **/config/*.php, **/routes/*.php33Glob: **/app/Http/Kernel.php, **/bootstrap/app.php, **/config/app.php34Glob: **/database/migrations/*.php, **/app/Models/*.php35Glob: **/.env*, **/.gitignore, **/Dockerfile, **/docker-compose.*36Glob: **/.github/workflows/*.{yml,yaml}37```3839Read `composer.json` to determine:40- **Laravel version** (laravel/framework constraint)41- **Key packages** (Sanctum, Passport, Horizon, Telescope, Pulse, Livewire, Inertia, etc.)42- **PHP version** constraint4344| Indicator | What it tells you | Watch out for |45|---|---|---|46| `laravel/sanctum` | API token / SPA auth | Missing token expiration, no ability revocation |47| `laravel/passport` | OAuth2 provider | Token lifetime too long, unused grant types |48| `laravel/horizon` | Queue monitoring | Dashboard exposed without auth |49| `laravel/telescope` | Debug/dev tool | Enabled in production, no auth gate |50| `laravel/pulse` | Production monitoring | Dashboard auth not configured |51| `livewire/livewire` | Full-stack components | Unprotected component methods, missing authorization |52| `inertiajs/inertia-laravel` | SPA bridge | Over-sharing props, exposing server data to client |53| `spatie/laravel-permission` | Roles & permissions | Missing authorization checks on routes |54| No queue driver config | Sync queue | Heavy operations blocking HTTP requests |5556Also check the Laravel version to know which patterns apply:57- **Laravel 11+**: Slim skeleton — no `Http/Kernel.php`, middleware in `bootstrap/app.php`, `/up` health route built-in58- **Laravel 10 and below**: Traditional structure — `Http/Kernel.php`, `Exceptions/Handler.php`5960### Step 2: Run All Six Audits6162Load and apply each reference checklist **one at a time**, in order. For each one, actually run63the Glob and Grep patterns to discover findings — don't guess or assume from the stack alone.6465Read these files from `references/`:66671. `security-checklist.md` — secrets, injection, auth, CSRF, mass assignment, rate limiting682. `scalability-checklist.md` — N+1 queries, eager loading, pagination, queues, caching693. `reliability-checklist.md` — exception handling, logging, health checks, transactions704. `hardening-checklist.md` — APP_DEBUG, session config, env validation, dependency pinning715. `code-quality-checklist.md` — tests, debug helpers, type safety, structural anti-patterns726. `operational-readiness.md` — CI/CD, deployment, .env.example, monitoring, rollbacks7374For each finding, note the **file path and line number**. Vague findings ("somewhere in the75codebase there might be...") are not useful. Be specific.7677**Severity classification:**78- **CRITICAL** — Actively dangerous; fix before deploying (e.g. hardcoded secret, `APP_DEBUG=true` in production, SQL injection via `DB::raw()` with user input)79- **WARNING** — Meaningful risk or debt that should be addressed soon (e.g. missing rate limiting, no eager loading, no queue worker)80- **SUGGESTION** — Would improve quality or resilience but isn't a blocker (e.g. missing Telescope auth gate, no monitoring)8182### Credential Redaction (Mandatory)8384When reporting findings that contain secrets, API keys, passwords, or tokens, ALWAYS redact85the actual value. Show only the first 4 characters followed by `••••••••`. Never output full86credential values in the report. Example: `sk_live_••••••••`, `AKIA••••••••`, `ghp_••••••••`.8788### Step 3: Score Each Dimension8990Score each dimension 0–10 using the rubric in `references/report-template.md`.9192Quick reference:9394| Score | Meaning |95|---|---|96| 9–10 | Production-grade |97| 7–8 | Good — minor gaps only |98| 5–6 | Acceptable — some risks |99| 3–4 | Concerning — significant gaps |100| 0–2 | Critical — not safe for production |101102**Overall rating:**103- **READY** — All dimensions 7+104- **ALMOST** — Most dimensions 6+, none below 4105- **NOT READY** — Any dimension below 4106107### Step 4: Write the Report108109Read `references/report-template.md` and produce the final report using that exact structure.110111- **Be specific, not generic.** Don't say "consider adding rate limiting." Say: "No rate limiting on `POST /login` — the `throttle` middleware is missing from `routes/web.php:14`. Add `throttle:5,1` to the login route or configure `RateLimiter::for('login', ...)` in `AppServiceProvider`."112- **Acknowledge what's working.** Real Laravel projects always have some things done well. Find them and say so.113- **Order findings by impact.** The most dangerous issues should appear first.114- **Explain the "why" in plain language.** A brief, honest explanation of the real-world risk helps developers prioritize correctly.115- **Give concrete, Laravel-specific fixes.** Provide the actual Laravel code, Artisan command, or config change — not generic pseudocode.116- **Reference CWE/OWASP when relevant.** Include the CWE ID (e.g. CWE-798) so developers can look up the full context.117118### Tool Usage119120- **Glob** — File discovery (configs, migrations, models, controllers, routes, tests)121- **Grep** — Pattern matching (secrets, anti-patterns, missing configurations)122- **Read** — Inspect specific files for context and line-level findings123- **Never use Edit, Write, or Bash** — this is a read-only audit124125### Tone126127This audit is most useful when it's direct without being alarmist. A missing rate limiter is a128warning, not a catastrophe. An exposed `APP_KEY` or database password in source code is a129catastrophe. Calibrate your language accordingly.130131When the project is in genuinely good shape, say so. When something is serious, be clear about132why it's serious. Developers trust audits that treat them as intelligent professionals who can133handle honest feedback.134135---136137## Gotchas138139- **Laravel 11+ has no `Http/Kernel.php`.** Middleware is registered in `bootstrap/app.php` instead. Don't flag missing Kernel.php as an issue on Laravel 11+ projects — check the Laravel version first.140141- **`APP_DEBUG=true` in `.env` isn't always a finding.** The `.env` file is for local development. Only flag it if `.env.production` or deployment configs have it set to true, or if there's evidence the `.env` file is used in production (e.g., no `.env.production` and deployment scripts reference `.env` directly).142143- **Missing tests isn't always WARNING-level.** A brand new project with 2 controllers doesn't need 80% coverage. Calibrate the severity to the project's maturity — check git log age and migration count.144145- **Telescope in `composer.json` isn't a vulnerability.** Telescope is typically installed as a dev dependency (`require-dev`). Only flag it if it's in `require` (not `require-dev`) AND there's no auth gate in `TelescopeServiceProvider`.146147- **Rate limiting may exist at the infrastructure level.** Before flagging missing rate limiting, check for Nginx/Apache configs, Cloudflare rules, or load balancer settings. Note: you can't always see these from code alone — mention it as a caveat rather than a definitive finding.148149---150151## Examples152153### Example finding (CRITICAL)154155```156### 1. Hardcoded Stripe Key in Config — Security157**Severity:** CRITICAL158**Reference:** CWE-798159**File:** `config/services.php:18`160**Finding:** Stripe secret key is hardcoded instead of using `env()`:161 `'secret' => 'sk_live_••••••••'`162**Why it matters:** This key is committed to git history and visible to anyone with repo access.163 It grants full access to your Stripe account — charges, refunds, customer data.164**Fix:**165 // config/services.php166 'stripe' => [167 'secret' => env('STRIPE_SECRET'),168 ],169 // .env170 STRIPE_SECRET={value from secrets manager}171```172173### Example finding (WARNING)174175```176### 4. N+1 Query in OrderController — Scalability177**Severity:** WARNING178**File:** `app/Http/Controllers/OrderController.php:34`179**Finding:** `Order::all()` without eager loading, then accessing `$order->customer` in the180 Blade view. With 100 orders, this makes 101 database queries.181**Fix:**182 // Before183 $orders = Order::all();184 // After185 $orders = Order::with('customer')->paginate(25);186```187188### Example "What You Did Well"189190```191## What You Did Well192- Sanctum is properly configured with token expiration and ability scoping193- All models define explicit `$fillable` arrays — no mass assignment risk194- Migrations are well-structured with proper indexes on foreign keys195- Form Requests are used consistently across all controllers196- Queue jobs implement `ShouldQueue` with retry and backoff configuration197```198199---200201## Anti-patterns202203- **Not a penetration test.** This is a static code review, not an intrusive security assessment. It does not test running applications or exploit vulnerabilities.204- **Not a compliance certification.** This does not certify SOC 2, PCI-DSS, HIPAA, or GDPR compliance. It can identify common gaps, but formal compliance requires a qualified auditor.205- **Not a replacement for automated scanning tools.** For dependency vulnerability scanning, use `composer audit`. For secret scanning, use `gitleaks` or `trufflehog`. This skill complements those tools with architectural and configuration review.206- **Don't guess findings.** Every finding must reference a specific file and line number discovered via Glob/Grep/Read. Never report an issue based on assumptions about the stack.207- **Don't modify files.** This is strictly read-only. Never use Edit, Write, or Bash tools during the audit.208209---210211## References212213- `references/security-checklist.md` — 16 security checks with CWE references and Laravel-specific Grep patterns214- `references/scalability-checklist.md` — Eloquent N+1, pagination, queues, caching, session drivers215- `references/reliability-checklist.md` — Exception handling, logging channels, health checks, transactions216- `references/hardening-checklist.md` — APP_DEBUG, Telescope/Debugbar exposure, cookie security, trusted proxies217- `references/code-quality-checklist.md` — Pest/PHPUnit, debug helpers, Larastan, structural anti-patterns218- `references/operational-readiness.md` — CI/CD, Forge/Vapor/Envoyer, monitoring, rollbacks219- `references/report-template.md` — Report structure, scoring rubric, tone guidelines