chore: install laravel telescope as dev-only debugging dashboard
Installs laravel/telescope ^5.0 (v5.12.5) as a dev-dependency.
Three-layer production safety adapted to Laravel 11 layout (no
Kernel.php; routing/schedule in bootstrap/app.php +
routes/console.php):
1. composer.json `extra.laravel.dont-discover` lists
laravel/telescope. After editing, `php artisan package:discover`
regenerates bootstrap/cache/packages.php — without this step
the auto-discovery cache still registers the vendor provider.
2. AppServiceProvider::register() gates registration to local +
testing environments. Registers BOTH the vendor
Laravel\Telescope\TelescopeServiceProvider (routes, migrations,
publishing) AND the project's App\Providers\TelescopeService
Provider (gate + filter) — they're sibling classes that extend
ServiceProvider independently, not parent/child, so both must
register for the dashboard to work. bootstrap/providers.php
deliberately does NOT list either Telescope provider.
3. .env TELESCOPE_ENABLED flag (false in .env.example). Runtime
toggle that disables Telescope even when the providers are
registered.
Production safety verified via simulated APP_ENV=production check:
confirms no Telescope-* providers are loaded.
Authorization: viewTelescope gate restricts dashboard to users
with the super_admin Spatie Permission role. Even in local
environments, only super_admin can view. Default was an email
allow-list stub — replaced with `$user->hasRole('super_admin')`.
Pruning: Schedule::command('telescope:prune --hours=48') added in
routes/console.php (Laravel 11's schedule location), environment-
gated to local + testing only.
Documentation: /dev-docs/TELESCOPE.md added; CLAUDE.md gets a
Development-tooling section. The doc explicitly calls out the
dual-provider registration (vendor + app) which differs from the
single-provider pattern in older Laravel versions.
Migrations applied: telescope_entries, telescope_entries_tags,
telescope_monitoring tables. Route registration verified in local
(42 telescope.* routes).
Tests: 1208/1208 passing — Telescope loads in the testing
environment as well, so the suite exercised it without issues.
Deployment note (flag for separate docs): a production operator
who runs `php artisan migrate` manually will still apply the
Telescope migrations — but because the providers never register
in production, the tables stay empty.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
dev-docs/TELESCOPE.md
Normal file
101
dev-docs/TELESCOPE.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Laravel Telescope (dev-only)
|
||||
|
||||
Local debugging dashboard for queries, jobs, mails, redis, events,
|
||||
exceptions. **Never registered in production.**
|
||||
|
||||
## Access
|
||||
|
||||
- Local URL: <http://localhost:8000/telescope>
|
||||
- Auth requirement: authenticated user with `super_admin` role
|
||||
(Spatie Permission). The `viewTelescope` gate is the access
|
||||
control; even in `local`, only super_admin can view.
|
||||
|
||||
## Production safety — three-layer defense
|
||||
|
||||
Crewli runs Laravel 11 (no `Kernel.php`; routing/schedule live in
|
||||
`bootstrap/app.php` + `routes/console.php`). The defense layers
|
||||
adapted to that layout are:
|
||||
|
||||
1. **`composer.json` `extra.laravel.dont-discover`** lists
|
||||
`laravel/telescope`, so Laravel's auto-discovery never registers
|
||||
the vendor `Laravel\Telescope\TelescopeServiceProvider`. After
|
||||
editing this list, run `php artisan package:discover` once to
|
||||
refresh `bootstrap/cache/packages.php`.
|
||||
2. **`AppServiceProvider::register()`** gates manual registration
|
||||
to `local` + `testing` only, and registers BOTH the vendor
|
||||
provider (routes/migrations/publishing) and the project's
|
||||
`App\Providers\TelescopeServiceProvider` (gate + filter):
|
||||
```php
|
||||
if ($this->app->environment('local', 'testing')) {
|
||||
$this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
|
||||
$this->app->register(\App\Providers\TelescopeServiceProvider::class);
|
||||
}
|
||||
```
|
||||
`bootstrap/providers.php` deliberately does NOT list either
|
||||
Telescope provider — both registrations live behind this
|
||||
environment gate.
|
||||
3. **`.env` `TELESCOPE_ENABLED` flag.** `false` in `.env.example`.
|
||||
Runtime toggle that disables Telescope even when the providers
|
||||
are registered (e.g. to silence Telescope locally during a
|
||||
profiling session).
|
||||
|
||||
If you ever see Telescope on production: revert immediately,
|
||||
audit the three layers above, and treat as a security incident.
|
||||
The dashboard exposes every query, payload, and job — including
|
||||
secrets in payloads.
|
||||
|
||||
### Verifying production safety
|
||||
|
||||
```bash
|
||||
APP_ENV=production php -r "
|
||||
require 'vendor/autoload.php';
|
||||
\$app = require 'bootstrap/app.php';
|
||||
\$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
foreach (array_keys(\$app->getLoadedProviders()) as \$p) {
|
||||
if (stripos(\$p, 'telescope') !== false) echo 'LOADED: ' . \$p . PHP_EOL;
|
||||
}
|
||||
"
|
||||
```
|
||||
|
||||
Expected output: nothing. Any line means a layer is breached.
|
||||
|
||||
## Pruning
|
||||
|
||||
Scheduled in `routes/console.php` (Laravel 11 layout):
|
||||
|
||||
```php
|
||||
Schedule::command('telescope:prune --hours=48')
|
||||
->daily()
|
||||
->environments(['local', 'testing']);
|
||||
```
|
||||
|
||||
48-hour retention. Adjust if dev DB is filling up.
|
||||
|
||||
## What Telescope captures
|
||||
|
||||
- All Eloquent queries with bindings + execution time (N+1 detection)
|
||||
- Background jobs with payload + status + retry history
|
||||
- Sent mails with rendered HTML + plaintext + recipient
|
||||
- Redis commands
|
||||
- Cache reads/writes
|
||||
- Events fired with listeners
|
||||
- Exceptions with stack traces
|
||||
- HTTP requests with headers + payload
|
||||
|
||||
## What NOT to use Telescope for
|
||||
|
||||
- Production debugging — never enabled there
|
||||
- Long-term audit trails — Spatie ActivityLog handles that
|
||||
(see ARCH-FORM-BUILDER §17.1)
|
||||
- Performance benchmarking — use APM tools designed for it
|
||||
|
||||
## Disabling temporarily
|
||||
|
||||
If Telescope is slowing down a specific dev workflow:
|
||||
|
||||
```bash
|
||||
TELESCOPE_ENABLED=false php artisan serve
|
||||
```
|
||||
|
||||
Or set globally in `.env` and restart your server. Re-enable when
|
||||
done.
|
||||
Reference in New Issue
Block a user