Product Decisions This Supports
- Build vs. buy on a commodity capability. Role and permission administration is table stakes, not differentiation. This package converts roughly one sprint of bespoke Nova resource work — role/permission CRUD, the grouped permission matrix, user↔role and role↔permission attach/detach, search, and supporting policies — into a composer install. That reclaimed sprint goes to domain authorization rules and policies, which are product-specific and where the actual competitive leverage sits.
- Roadmap scoping and sequencing. Fund basic RBAC now for MVP, internal back-office tooling, and admin-facing releases. Explicitly defer ABAC, tenant/team-scoped permissions, approval workflows, SSO/SCIM provisioning, and audit-grade compliance reporting until customer demand or a regulatory trigger justifies the investment. The package is useful precisely as a boundary marker: it delivers the "basic" tier and visibly does not deliver the rest, which makes upgrade conversations with customers concrete rather than hypothetical.
- Time-to-market for a blocked release. If a deal, a pilot, or an internal ops team is stalled on "who can change what," this shortens the path to a shippable admin surface. It fits where speed beats governance maturity — and it lets you ship the admin screen without committing the platform roadmap.
- Feature discovery before funding an access-governance program. Put this in front of design partners and internal admins and the real gaps surface early — audit trail, tenant isolation, approvals, bulk provisioning. Learning that from a demo costs days; learning it after a six-month build costs a quarter.
- Operational leverage and support cost. A centralized Nova surface for access changes reduces ad-hoc database edits and the engineering tickets that follow them ("please add Jane to billing-manager"). That is a recurring saving, and it is the easiest benefit to quantify post-launch: tickets per month for role changes, before and after.
- Vendor-risk posture — an "accelerator, not a platform" call. 87 stars, a single-agency maintainer, no commercial SLA, and a last release in December 2024. This should never become a strategic dependency. Two things make that acceptable: the "0 dependents" figure is a measurement artifact (Packagist cannot crawl dependents of a package requiring closed-source
laravel/nova), so treat it as unknown adoption, not no adoption; and because it is a UI layer over spatie/laravel-permission, all state lives in standard Spatie tables.
- A genuine two-way door. The architecturally decisive rule is one line in code review: no application or policy code ever imports a
Sereny\ class. Application authorization binds to Spatie's contract — HasRoles, Gate, policies, can: middleware. With that boundary held, swapping UI providers (to vyuldashev/nova-permission, to a hand-rolled screen, or to nothing) is a composer change plus re-registering a tool; role and permission data is untouched. If the package stalls on a future Nova major, you lose an admin screen and production authorization keeps working. Cheap entry, cheap exit — that asymmetry is what justifies deciding now without a full vendor bake-off.
- Pricing and packaging input. Knowing that RBAC admin costs roughly a sprint of bespoke work sets a concrete floor for what an "advanced access control" tier is worth charging for — and clarifies which capabilities (audit trail, tenant scoping, approvals) belong behind that tier versus in the base product.
When to Consider This Package
Adopt when all of these are true:
- You already run a licensed Laravel Nova 4.x or 5.x install. Nova is the binding compatibility constraint, not this package — Nova is closed-source and its majors are full internal rewrites. Budget a spike at every Nova upgrade.
spatie/laravel-permission is installed, configured, migrated, and your Nova-authenticated model uses HasRoles. Retrofitting either later is a migration project, not a config change.
- You have made, and written down, two decisions: whether Spatie teams are enabled, and which guard(s) you use. Teams changes the semantics of the entire screen — roles resolve per team and the stock UI will not model team assignment meaningfully. Guard mismatches fail silently: a
web-guarded role assigned to an api-guarded actor returns a quiet false from can(), with no error to chase.
- You can accept the vendor profile: small niche adoption, bus-factor-of-one, no published compatibility guarantee beyond composer constraints. Pin the package, Nova, and Spatie to exact versions in
composer.json; floating constraints on any of the three is how a working admin screen breaks on a Tuesday.
- Basic RBAC is genuinely sufficient for the next 6–12 months of the roadmap.
Look elsewhere — or build — when any of these are true:
- Audit trail is a requirement. There is no built-in change history for role or permission mutations. If "who changed whose access, when" is a compliance obligation, scope that as a blocker now, not a nice-to-have later; supplement with a Spatie permission event listener or model observer writing to an append-only log. Do not assume you can bolt it on cheaply after the fact.
- Multi-tenancy or teams are core to the product. Teams-enabled changes what the UI means, and the package does not meaningfully model per-team assignment. Decide before installation, never after.
- You are not on Nova, or you are considering leaving it. The whole value proposition is a Nova presentation layer. Without Nova there is nothing here — go directly to
spatie/laravel-permission plus your own screen, or evaluate a different admin stack.
- You need a maintained, supported dependency with an SLA. This is a single-maintainer package tracking Nova majors reactively. If procurement or security review requires vendor guarantees, this will not clear the bar.
- Your fleet is load-balanced with per-node caches. Spatie caches permission lookups; with per-node file caches, a role change in Nova updates one node and produces divergent, intermittent, node-dependent authorization. Move to Redis first or do not adopt.
- You need fine-grained delegation — regional admins, approval chains, just-in-time access. Out of scope here; that is a build or a different product category.
How to Pitch It (Stakeholders)
To executives — the one-paragraph version. We need role and permission administration before we can ship an admin-facing release. Building it ourselves costs about a sprint of Nova engineering for a capability that is identical in every product we compete with — it wins us no customers. This package delivers that screen for the cost of a composer install and a short setup spike. The state it manages lives in standard spatie/laravel-permission tables, so our production authorization never depends on this vendor: if the package stalls, we lose a UI and nothing else. Total exposure is roughly one sprint saved, one small pinned dependency added, and one architectural rule — no application code imports the package — that keeps the exit a composer change. This is a deliberate two-way door, and the two-way door is the point.
To engineering — the operating constraints. Three non-negotiables. (1) Gate the tool server-side, not just in the navigation menu — hide the tool from non-super-admins via a Nova gate and assert in a test that a non-admin hitting the route gets a 403. Without this, anyone who reaches the screen can grant themselves permissions; that is a privilege-escalation path, not a UI nicety. (2) Never let application or policy code import a Sereny\ class. Bind authorization to Spatie's contract (HasRoles, Gate, policies, can: middleware) and enforce the boundary in code review. (3) Seed roles and permissions; treat the UI as convenience only. The UI exists so ops can assign users to roles — not so it becomes the source of truth for the taxonomy. Lock a resource.action naming convention before the grouped matrix is exposed, or you will get view invoices, Invoices-View, and invoice_view in the same afternoon. Then test authorization flows, not the UI: granting a role must change what the app permits, and that suite must pass against both a seeder-populated database and one mutated through the UI.
Operational notes to carry into the launch. Document the manual fallback now — a tinker one-liner to assign a role without the UI — and put it somewhere a non-engineer can find it. An outage that is an inconvenience beats one that becomes an incident. Deleting a role is a live-fire operation: the UI will let an admin delete a role four people depend on, and Spatie's cascade drops the assignments, so consider a policy blocking deletion of any role in the canonical seeder list. Use the Role resource as the primary workflow surface — attach permissions to roles, assign roles to users; direct user→permission grants produce an access graph nobody can reason about six months later. Finally, record the exit in the decision log and re-evaluate at each Nova major: this is an accelerator, not a platform, and it stays cheap to leave only as long as the coupling rule holds.