grizzlylab/deny-routes-by-env-bundle
Symfony bundle that restricts routes to specific environments, letting you deny configured paths outside allowed envs. Simple configuration keeps dev-only or admin routes unreachable in production without touching controllers or firewall rules.
Architecture fit. The first finding is disqualifying on its face: despite being filed as a "Laravel/PHP package," grizzlylab/deny-routes-by-env-bundle is a Symfony bundle, not a Laravel package. Its integration surface — a Bundle subclass, a DependencyInjection extension with a configuration tree, and a kernel.request event listener — has no counterpart in Laravel's service container, package discovery, or HTTP kernel. There is no architectural seam for it to plug into a Laravel application. Even inside a Symfony codebase the footprint is narrow and legitimate (gate dev/debug/admin routes out of production by environment), but that is a different product decision than the one implied by the brief.
Integration feasibility. As a drop-in for Laravel: zero. As a reference implementation for a Laravel-native equivalent: high. The underlying behavior is small and well-understood — resolve the matched route, compare against an environment-scoped deny list, and abort with 404 (or 403) before the controller runs. In Laravel this is a ~30-line middleware using $request->route()->getName() and app()->environment(), registered in bootstrap/app.php (L11+) or Http/Kernel.php. Reimplementation cost is measured in hours, not sprints.
Technical risk. Material, and concentrated in the fact that this package is an access control, not a convenience utility:
APP_ENV unset in a container), the deny rule silently does nothing and the protected routes are live. There is no evidence in the package metadata of a fail-closed contract or CI coverage proving it.Key questions. Before any decision: (1) Is the target application actually Laravel, or is the brief mislabeled and the estate is Symfony? (2) Last commit and last tagged release date, and which Symfony/PHP versions are supported? (3) Does the bundle throw 404 or 403, and does it log denials? (4) Is the deny list compiled into the route cache at warmup, or evaluated at runtime? (5) Does it fail closed when the environment is unknown or the config is empty? (6) Is there a test suite and CI? (7) Does it cover sub-requests, ESI fragments, and console/messenger entry points?
Verdict. Do not adopt. Treat the package as a specification for a first-party middleware.
Stack fit. Poor for Laravel and only marginal for Symfony. For a Laravel estate, the correct framing is build-vs-buy, and the build side wins decisively: the feature is a middleware, and Laravel already ships every primitive required (app()->environment(), route name resolution, abort(), Route::middleware()). Pulling in a Symfony bundle would mean standing up a parallel framework abstraction for one boolean check.
Migration path. Extract the behavior, not the code:
DenyRoutesInEnvironment middleware in app/Http/Middleware, config in config/route-deny.php, published via a standard service provider if this needs to be shared across services.Compatibility. Target PHP 8.2+ and the Laravel versions actually in the estate (10/11/12). If any Symfony services exist, the upstream bundle could be evaluated there on its own merits, but the two implementations should not be conflated — same policy, two codebases, one shared config schema.
Sequencing.
artisan-adjacent web routes).Maintenance. First-party middleware is ~50 lines including tests and is maintained by people already on call for the application. The upstream bundle, by contrast, would introduce a third-party dependency on an access-control path with a 4-star, zero-dependent, single-maintainer footprint — the maintenance cost is not the code, it is the standing obligation to audit a stranger's commits on a security boundary.
Support. Community-only, no SLA, no security policy evident in the package metadata, no dependents to surface CVEs or breakage. Escalation path is "read the vendor code yourself." That is unacceptable for a control whose failure mode is route exposure.
Scaling. Runtime cost is negligible — one hash lookup per request against a small deny list, no I/O, no allocation worth measuring. The scaling concern is organizational, not computational: the deny list must stay in sync with route names as the application grows. Route renames silently orphan deny rules, and an orphaned rule is an unprotected route. Mitigation is a test that walks the registered route collection and asserts every route matching a sensitivity pattern (admin/, debug/, *_test) is either explicitly permitted or denied — a lint, not a runtime check.
Failure modes.
APP_ENV unset or misspelled in a container; deny list resolves to an empty set; routes serve normally with no error. Highest-severity mode.route:cache/config:cache refresh leaves the previous policy in force.Ramp-up. Very low for the reimplementation — any mid-level Laravel engineer can build and test this in a day. Ramp-up on the upstream bundle is higher and less valuable: understanding a Symfony bundle's DI extension and listener priority ordering to audit a control you could have written yourself. The asymmetry favors building.
How can I help you explore Laravel packages today?