Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Guardian Laravel Package

rennokki/guardian

Guardian is a Laravel package for managing roles and permissions. Define abilities, attach them to roles or users, and check access in routes, controllers, middleware, and Blade views through a clean, expressive API that keeps authorization logic simple, readable, and centralized.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

rennokki/guardian is a thin, Eloquent-native permissions layer: a permissions table, a polymorphic many-to-many pivot (model_has_permissions) so any model — not just User — can hold permissions, and a HasPermissions trait that adds givePermissionTo, revokePermissionTo, syncPermissions, hasPermissionTo and overrides Laravel's can()/cannot() so existing @can Blade directives and Gate checks continue to work unchanged. Wildcard support (e.g. posts.*) is included.

The important architectural distinction for us: this package models permissions only, not roles. There is no Role entity, no role hierarchy, no per-guard or per-team scoping, and no Role::assignPermission indirection. Roles have to be modeled either as naming conventions (admin, editor granted as permissions) or as a separate table we build. That is a deliberate simplicity trade — it maps cleanly onto small products with a handful of capability flags, and poorly onto anything with delegated administration, tenant-scoped grants, or a support team that needs to audit "why can this user do X."

It slots into the framework's authorization pipeline rather than alongside it, which is architecturally the right shape. The risk is that it occupies the authorization hot path while being a single-maintainer package with no release cadence.

Integration feasibility

Mechanically this is a low-effort integration: composer require, publish and run one migration, add the trait to the relevant models, seed permissions. Realistically 2–4 engineer-days for a greenfield surface: install, migration, seeding, backfill of any existing is_admin-style flags, gate/policy reconciliation, and test coverage. It does not require rewriting existing Gate::define or policy classes — the trait's can() override sits on top of them, though that override is exactly the thing to verify first, because it changes resolution order for every authorization check in the app.

Technical risk

Risk Severity Note
Maintenance status High Zero dependents and a low star count imply near-zero production usage; assume no upstream fixes
Laravel/PHP version ceiling High Must verify composer.json constraints against our target (Laravel 11/12, PHP 8.3+); abandonware in the auth path is a compounding liability
Roles not modeled Medium We own the role abstraction, its caching, and its audit story
Authorization hot path Medium can() override + wildcard matching affects every check; a wildcard bug is a privilege-escalation bug
Cache coherence Medium Permission caching plus multi-process/Octane deployment is a stale-grant/stale-revoke vector
No audit trail Medium No built-in history of who granted what; likely a compliance gap for us
Security disclosure path Medium No security policy, no CVE history, no one to notify

Key questions

  1. What are the package's declared illuminate/* and PHP constraints, and when was the last commit? Is the last release compatible with our target framework version?
  2. Does the can() override respect gates defined after the trait boots, and how does it interact with Gate::before super-admin patterns?
  3. Is permission caching on by default, what store does it use, and how is it invalidated on grant/revoke?
  4. How are wildcards evaluated — prefix match only, or full glob — and is there a deny/negative-permission concept, or is it additive-only?
  5. Does it support multiple guards (web vs. Sanctum API tokens) and does the polymorphic pivot handle morph-map aliasing?
  6. What is our realistic alternative — spatie/laravel-permission (roles + permissions + teams + broad adoption) — and what does Guardian actually buy us that Spatie does not?

Verdict on technical merit: viable for a small, single-tenant app with a short horizon. Not defensible as the authorization core of a multi-tenant or long-lived product without a fork-and-own commitment.

Integration Approach

Stack fit

Best fit is an existing Laravel app already using Eloquent models, standard Gate/Policy conventions, and a relational database — MySQL/Postgres both fine. The polymorphic pivot makes it convenient if permissions must attach to entities other than User (organizations, API clients, service accounts) without a second package.

Weak fit if we need: tenant-scoped permissions, role CRUD in an admin UI, delegated grant management, or an authorization model that a non-engineer auditor can read.

Migration path

Two realistic entry points:

  • From ad-hoc flags (users.is_admin, users.can_export): straightforward. Create permissions named after the flags, backfill the pivot in a single migration, leave the boolean columns in place read-only for one release as a rollback path, then drop them.
  • From spatie/laravel-permission: only worth doing if we are deliberately simplifying away from roles. The data model differs (Spatie has roles, model_has_roles, plus a separate model_has_permissions); we would flatten role→permission assignments into direct grants, which is lossy and hard to reverse. If we are already on Spatie, staying on Spatie is almost certainly the cheaper decision.

Compatibility

Verify before committing: framework and PHP constraints; the pivot's model_type column length versus our longest namespaced model class (and whether we use Relation::morphMap); MySQL index byte limits on (permission_id, model_type, model_id); behavior under Laravel Octane and under queue workers with long-lived processes and a cached permission set; and whether the cache respects our configured cache store (Redis vs. array in tests).

Sequencing

  1. Spike (1–2 days). Read the source — it is small — including the can() override, wildcard matcher, and cache invalidation. Do not skip this; the package is too small to have a community that has found its edge cases.
  2. ADR. Decide Guardian vs. Spatie vs. hand-rolled trait, with the abandonment risk written down and an explicit owner for a fork if needed.
  3. Pilot. Apply to one non-critical module (e.g. report exports) behind the existing gate layer, so a failure degrades one feature rather than the whole auth surface.
  4. Backfill + dual-read. Seed permissions, backfill pivots, run old and new checks in parallel with logging of disagreements for one release.
  5. Cutover and delete legacy flags; add a regression test suite around wildcard grants and revoke-invalidation.
  6. Own it. Fork into our namespace or vendor the source at the version we validated, so an upstream disappearance is not an incident.

Operational Impact

Maintenance

This is the dominant cost. Single maintainer, no dependents, no visible release cadence — effectively we are adopting a code sample, not a supported library. Budget for: a named internal owner, a forked copy under our org, and a standing item to re-evaluate on every Laravel major upgrade. The good news is the surface is small — a few hundred lines of trait and migration — so a fork is genuinely tractable rather than aspirational.

Support

No commercial support, no security disclosure process, no backfill of issues. Our support path is "the engineer who read the source." That is acceptable for a capability-flag system and unacceptable if this is customer-facing entitlement enforcement with contractual SLAs.

Scaling

Per-check cost is a cached lookup after the first hit, so read scaling is fine — provided the cache is enabled and shared. Watch for:

  • N+1 on authorization-heavy list endpoints (permission checks per row in a policy); mitigate with eager loading or a per-request memoized permission set.
  • Pivot table growth in polymorphic designs where permissions attach to many model types; index (model_type, model_id) explicitly.
  • Cache invalidation fan-out across web, queue, and scheduled processes; a revoke that only clears one process's cache is a live security gap until TTL expiry.

Failure modes

Failure Symptom Detection
Stale cache after revoke User retains access post-revocation Canary test asserting revoke → immediate 403
Wildcard over-grant * or posts.* matches more than intended Unit tests on the matcher with adversarial names (posts_admin, posts.)
Permission deleted, pivot orphaned Silent no-op grants, confusing admin UI FK constraint with cascade, plus a reconciliation job
Morph map drift Rows keyed on FQCN, code uses alias (or vice versa) Assert stored model_type values in a test
can() override regression Gates/policies stop firing or fire out of order Full policy test suite green before cutover
Upstream abandonment mid-upgrade Blocked Laravel upgrade Recorded in ADR; fork is the mitigation

Ramp-up

Low. A mid-level Laravel engineer is productive in under a day — the API is five methods and one trait. The non-obvious learning is the can() override semantics and the caching behavior; document both in the ADR so the next engineer does not rediscover them during an incident.

Bottom line for the roadmap: cheap to try, cheap to abandon, and cheap to own — but only if we treat it as internal code we are adopting rather than a dependency we are consuming. If the product needs roles, tenant scoping, or an auditable grant history within the next 12 months, choose spatie/laravel-permission now and skip the migration; the switching cost later is higher than the incremental integration cost today.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc