artesaos/shield
Artesaos Shield gives Laravel apps a lightweight authorization layer for roles and permissions. Define abilities once, assign them to users, and protect routes, controllers, and Blade views with simple, expressive checks.
Architecture fit
Gate/Policy layer should remain the enforcement point, with Shield supplying the role/permission facts. Any implementation that bypasses Gates and enforces inside middleware or helpers should be rejected on design grounds.Gate/Policy with a small internal roles table, and (2) spatie/laravel-permission, the de facto ecosystem standard with active maintenance. Shield must beat both on cost or fit; the evidence does not support that.Integration feasibility
config/app.php, manual facade alias registration, and manual middleware wiring in Kernel.php — a file that no longer exists in Laravel 11+.down() path before it touches a shared database.hasRole/can helpers or a competing authorization package.Technical risk
illuminate/support to the Laravel 5.1–5.4 era and PHP to the 5.6/7.0 era. It will not resolve against Laravel 9/10/11/12 and PHP 8.1+. Expect composer require to fail outright on any current application.Gate::before interaction, multi-guard support, multi-tenancy/team scoping, wildcard permissions, and whether permission lookups are cached per request or hit the database on every check.Key questions
composer.json constraints for php and illuminate/*, and does the package resolve at all against our target Laravel and PHP versions?Gate/Policy, or does it enforce independently in middleware and helpers? Is it fail-open or fail-closed when a permission record is missing?User model on the default guard?@can/hasPermission call — one query, N queries, or a cached permission graph?Stack fit
Kernel.php middleware, facade aliases) no longer match the framework's structure.Gate/Policy plus spatie/laravel-permission. There is no scenario where a nine-year-dormant package is the right choice for new authorization code.Migration path
AuthorizationService interface (hasRole, hasPermission, assignRole) and route all application code through it. Shield becomes one implementation behind that seam. Swapping to Spatie or native Gates then becomes a single adapter change rather than a codebase-wide edit.roles, permissions, and pivot tables to the target schema; backfill in a single scripted job; run a dual-write window if role assignment happens at runtime; cut over reads, then remove writes, then drop tables.Compatibility
composer.json directly rather than inferring. A missing upper bound or a * constraint is itself a red flag in a package this old.composer update across the whole monorepo.Authorize trait conflicts on the User model if we already use Laravel's AuthorizesRequests/Authorize patterns.Sequencing
composer.json, run a composer require --dry-run in a scratch container against our exact PHP/Laravel pins. If it fails to resolve, stop — the evaluation is over and the recommendation is reject.AuthorizationService seam.Gate/Policy + Spatie. Do not let this evaluation block roadmap items.Maintenance
Support
Scaling
hasPermission inside a loop is a classic N+1 that only appears at scale.Failure modes
illuminate/* to the Laravel 5 era; the next major upgrade cannot proceed while it is installed. Mitigation: replace before the upgrade, not during it.AuthorizationService interface.Ramp-up
Gate/Policy layer plus spatie/laravel-permission covers this requirement with active maintenance and no schema ownership risk. If Shield is already running in a legacy application, do not expand it — wrap it behind an internal AuthorizationService interface, pin the version, assign an owner, and schedule the migration to Spatie as funded roadmap work rather than a future discovery.How can I help you explore Laravel packages today?