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

Nova Permission Laravel Package

bbs-lab/nova-permission

bbs-lab/nova-permission adds a Laravel Nova UI for spatie/laravel-permission, letting you create roles and permissions, assign them to users, and manage access control directly from Nova without custom admin screens.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This package is a thin but opinionated authorization layer that sits between Laravel Nova and spatie/laravel-permission, extending Spatie's model from global (role-level) permissions to per-instance ("granular") permissions. Architecturally it is a natural fit for any Nova-administered Laravel app that already uses Spatie — it fills a real gap (Nova has no first-class UI for scoped authorization) without introducing a new permission engine. The v2.0.0 release is best understood as a stability and correctness release that formalizes 1.x's implicit contracts into hard requirements, not a feature release. The feature set is unchanged; what changes is that the previously aspirational parts now actually work.

Integration feasibility. Feasible for a greenfield or clean-upgrade path; materially harder for an existing 1.x install. Three integration surfaces carry the weight:

  • Model contract: authenticatable models must use BBSLab\NovaPermission\Traits\HasRoles (not Spatie's) and implement CanOverridePermission. Any policy calling hasPermissionToOnModel() is coupled to the package trait, so this is a cross-cutting change touching every authorization call site, not a package swap in isolation.
  • Migrations: package migrations are now real PHP files that auto-run on php artisan migrate. This is convenient but removes an explicit opt-in step — you can no longer reason about schema changes from your own migration history alone. Only Spatie's migration remains publishable (--tag="permission-migrations").
  • Policy base class: base Policy methods now return ?bool while keeping the Model $model parameter. Overrides must not narrow the signature — a silent source of fatal errors during upgrade if any project policy was written against 1.x.

Technical risk. The dominant risks are upgrade-time, not runtime:

  1. Composite unique index migration. Replacing Spatie's unique(name, guard_name) with unique(name, guard_name, authorizable_id, authorizable_type) will fail on any existing dataset containing duplicate (name, guard_name) rows — which is exactly the state 1.x encouraged, because scoped permissions couldn't be created. Existing installs may hold duplicate-named permissions with null authorizable_id that only differed by intent. This needs a data audit before migrating. The MySQL-safe explicit index name mitigates the 64-character identifier limit but signals the constraint is real.
  2. Cache default flipped to off. The old gate_cache key is gone; caching is opt-in via config('nova-permission.cache.enabled') (default false, env NOVA_PERMISSION_CACHE / NOVA_PERMISSION_CACHE_TTL). Correct-by-default, but it means a silent performance regression for any deployment that was relying on the old gate cache and doesn't notice the config key changed. This should be treated as a required post-deploy config change, not an optional one.
  3. Trait/contract coupling to a third-party namespace. The package now owns the authorization trait rather than Spatie's. Any other package or internal code that type-hints or uses Spatie's HasRoles directly will need review.
  4. Nova version surface. Nova 4 support was restored (it had silently broken) via a compatibility shim, and Nova-5-only dev dependencies were dropped. "Silently broke" is the operative phrase: it implies the 1.x compatibility claim was untested, so we should treat Nova 4 support as newly introduced and verify it ourselves rather than inheriting 1.x assumptions.
  5. PHP 8.2 gap. The requirement is ^8.2 but the CI matrix is PHP 8.3–8.5. The floor is nominally supported but not tested. If any environment runs 8.2, flag it.

Key questions.

  • Do we have duplicate (name, guard_name) permission rows in production, and do we have a remediation script if so?
  • Is anything in our codebase or dependency tree consuming Spatie's HasRoles trait directly, or type-hinting against Spatie's policy/permission classes?
  • Do any of our policies override the base Policy methods with narrowed signatures or non-nullable bool returns?
  • Was gate_cache enabled in our config? If so, who owns turning on NOVA_PERMISSION_CACHE and validating TTL/invalidation behavior?
  • Are we on Nova 4 or 5, and on which side of the shim do we land?
  • Do we accept auto-running package migrations, or do we need to gate them in CI/CD?

Integration Approach

Stack fit. Requires PHP ^8.2, Laravel Nova ^4.0 || ^5.0, and spatie/laravel-permission ^6. The Spatie 6 constraint is the sharpest edge: if we are on Spatie 5, this release forces a Spatie major upgrade concurrently, which brings its own migration and cache-key changes. Sequence these as two distinct changes, not one.

Migration path. Treat this as a coordinated schema + auth-contract upgrade, not a composer bump:

  1. Pin and inventory. Freeze the current version, confirm exact Nova, Laravel, PHP, and Spatie versions in every environment including local/workbench.
  2. Upgrade Spatie to ^6 first, independently, and validate roles/permissions behavior with the existing package still on 1.x if feasible. This isolates Spatie's breaking changes from the package's.
  3. Audit data. Query for duplicate (name, guard_name) permissions and for any permission rows with non-null authorizable_id/authorizable_type created under 1.x (which, given the 1.x defects, likely do not exist or are malformed). Decide on a merge/rename strategy before running the composite-index migration.
  4. Adopt the new trait and contract on the authenticatable model(s), then grep for and fix every policy override that narrows the Policy base method signature.
  5. Run migrations in a staging clone against a production-shaped dataset. The composite index creation is the single most likely failure point; validate it on MySQL specifically given the explicit index-name workaround.
  6. Re-enable caching deliberately: set NOVA_PERMISSION_CACHE and TTL, verify per-model authorization-cache invalidation (called out as fixed) with a role change → permission check round-trip.
  7. Cut over, then exercise the Nova permission builder search (now debounced and actually filtering) and both general and granular permission flows.

Compatibility. The explicit ?bool return type on base policy methods is the compatibility boundary for project code; the Model $model parameter retention is the other. Both are static, greppable, and fixable — good properties. The trait swap is the least greppable: HasRoles is a common import name and collisions may look identical at a glance. Use a static analysis pass rather than code review.

Sequencing. Spatie 6 → package trait/contract adoption → policy signature fixes → migrations (staging first) → cache enablement. Do not combine the Spatie major with the package major in a single PR; if something breaks, you want to know which.

Operational Impact

Maintenance. Genuinely improved. Full Pest suite at 100% line coverage, mutation testing, architecture tests, PHPStan level 8, Pint, a GitHub Actions matrix (Nova 4 & 5 × Laravel 11–13 × PHP 8.3–8.5), and Dependabot. For a package operating in the authorization path of an admin panel, this is the difference between "trust the README" and "trust the build." The mutation-testing and architecture-test signals are meaningful — they suggest the maintainer intends to prevent the class of silent breakage that killed Nova 4 support in 1.x.

Support. Mixed but net positive. Documentation was rewritten and now includes a Requirements section, a granular-permissions guide, a caching page, and a Testing page, plus a workbench that doubles as a demo (seeded admin/writer/reader roles, Post and Service resources showing general vs. granular permissions, Nova impersonation). That materially lowers ramp-up. The counterweight is a single-maintainer, small-namespace package (BBSLab) now owning the authorization trait — that is a real bus-factor consideration for something in the auth path.

Scaling. Opt-in caching is the right default for correctness but puts the burden on us to reason about permission volume. Granular permissions multiply the permission-check surface: per-instance checks on list views are the classic N+1 authorization problem. The fixed per-model authorization-cache invalidation is therefore load-bearing, not incidental. Before enabling granular permissions broadly, we should load-test a Nova index with realistic permission cardinality and confirm cache invalidation doesn't thrash on role edits.

Failure modes. Ranked:

  • Migration failure on the composite index due to pre-existing duplicate permission names — blocks deploy, requires data remediation under time pressure.
  • Silent cache regression — gate_cache key removed, new key off by default; config carried over from 1.x does nothing and nobody notices until the admin panel is slow.
  • Fatal errors from narrowed policy signatures in project code — surfaced at request time, not at boot, so likely caught in staging only if the relevant resources are actually exercised.
  • Trait collision / stale Spatie trait usage — authorization behaving inconsistently across models, which is subtle and dangerous in an admin panel.
  • Nova 4 shim regressions — the 1.x path silently broke before; the new CI matrix covers both majors, which reduces but does not eliminate this.

Ramp-up. Low for a developer familiar with Spatie and Nova: the mental model is unchanged, the workbench is a working reference, and the docs are rewritten. Budget realistic effort for the upgrade itself — the trait/contract adoption, policy signature sweep, and data audit are a day or two on a small app and more where policies are numerous. Add explicit onboarding for the caching model, since "off by default and centralized" is easy to misread as "we don't need to think about it."

TPM recommendation. Adopt v2.0.0, but as a planned change with a data-audit gate, not a routine bump. The release's core value proposition — granular permissions that actually work, verified by tests — is real and was previously unavailable despite being advertised in 1.x. Do not enable granular permissions in production until the composite-index migration and cache-invalidation behavior have both been validated against a production-shaped dataset.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle