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

Tomato Roles Laravel Package

tomatophp/tomato-roles

Tomato Roles is a Laravel package for managing roles and permissions with a ready-made admin UI. Create roles, assign permissions to users, and control access across your app without building the CRUD yourself. It fits the TomatoPHP ecosystem and keeps role-based access simple to configure and maint...

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. tomatophp/tomato-roles is an ACL layer, not an authorization engine. Its entire reason to exist is the pre-wired role/permission admin surface inside Tomato Admin on Splade (Laravel + Livewire + Blade), reportedly delegating to spatie/laravel-permission. That makes it an internal-tooling fit only: back-office, support, and operations users managing admin-console access. It is not a candidate for customer-facing authorization regardless of how clean the demo looks. If our admin UI is Filament, Nova, Inertia, or a custom SPA, this package delivers zero value — the underlying schema is almost certainly Spatie, which we could adopt directly.

Integration feasibility. Mechanically low-friction: publishable config, migrations, and policies; a HasRoles-style trait on User; plugin registration per Tomato Admin convention; seeders for default roles and guards. A working end-to-end role assignment is a half-day of work in a compatible codebase. The real feasibility question is not "can we install it" but "does deny-by-default hold at both the HTTP and Blade layers," which is a 15-minute spike we should treat as a hard go/no-go gate rather than a formality.

Technical risk. This is the crux of the evaluation, and it is asymmetric in the wrong direction:

Risk Evidence PM consequence
Ecosystem validation 2 stars, 0 dependents, no CI signal, no support channel We are the QA department; budget for reading src/
Single-maintainer concentration ~21 patch releases, one primary maintainer Fork-and-vendor is the operating model, not a contingency
Stack coupling v1.1.21 fixed a Splade SelectFilter API change in UserTable A minor Splade/Livewire bump can break the admin surface
Silent privilege escalation Authorization defects fail open, not visually Validation is funded as part of adoption, not follow-up
Guard semantics Non-default admin guards are standard in Splade #1 production authz bug in this ecosystem
Multi-tenancy No evidence of team/tenant scoping Hard stop if our admin is tenant-partitioned

Note the v1.1.21 fix landed in a filterable UserTable, meaning the shipped blast radius is broader than a narrow role editor — it reaches into user management list screens. That is a scoping fact, not a footnote.

Key questions to resolve before approval.

  1. Does composer.json wrap spatie/laravel-permission, or reimplement the schema and checks? Wrapping = thin UI shell, acceptable risk. Reimplementing = bespoke authorization core with near-zero external review.
  2. What Laravel/Livewire/Splade versions are pinned, and do they intersect our exact matrix?
  3. What are the migration table names and key types (UUID vs bigint), and does the guard column model match our panel guard?
  4. Is there a permission:cache-reset equivalent, and is it wired into the role-edit flow?
  5. Does UserTable overlap functionality we already own, creating a duplicate user-management surface?
  6. Is the multi-tenant/team dimension in scope, or global only?

Integration Approach

Stack fit. Adopt only if we are already committed to Tomato Admin + Splade. The package removes boilerplate CRUD — role editor, permission attach, user assignment — and creates no differentiation. Frame it internally as a time-boxed accelerator for an existing "admin roles and permissions" milestone, not a platform bet. If the stack match is absent, the correct move is spatie/laravel-permission plus a hand-built admin UI at roughly 2–4 engineer-days.

Migration path. Assume a brownfield codebase with ad-hoc is_admin booleans and scattered policy methods. The path is: inventory existing authorization checks → define a canonical permission list as data (config/permissions.php or a seeder) using resource.action dotted names → seed roles per environment → run the new permission model in parallel behind a feature flag for one release cycle → reconcile discrepancies → cut over. Do not publish migrations unless we need to alter the schema; once published, we own it and upgrades become manual diffs. Diff the shipped migrations against any pre-existing ACL tables first, and decide UUID vs bigint up front — retrofitting after data exists is a real migration, not a config tweak.

Compatibility. Pin the exact version matrix — Laravel, Livewire, Splade, and this package as a tested tuple. Never float on ^1.1. Likewise, if the package wraps Spatie, pin Spatie explicitly in our own composer.json so the engine version is not transitively dictated by a low-adoption wrapper. Treat every Splade/Livewire bump as a smoke-test event for the admin list screens.

Sequencing (each step is a gate).

  1. Read before installing — composer.json, database/migrations/*, TomatoRolesServiceProvider.php + models. Answers the wraps-Spatie question and the schema fit. (~2 hours, no commitment.)
  2. Spike on a throwaway branch — install, publish config, register plugin, attach trait, seed admin/viewer. Prove deny-by-default at both layers with one test asserting a viewer gets 403 on an edit route and does not see the corresponding @can block. Stop here if it fails.
  3. Decide vendor-vs-depend — fork the repo, name an owner, document the exit runbook to raw Spatie.
  4. Build the real model — centralized Permissions enum/constants file referenced by middleware, Blade, policies, and tests; Gate::before super-admin bypass returning null; negative-case and cache round-trip tests.
  5. Parallel run and cutover — feature-flagged, one full release cycle, with its own release window. Do not ship the ACL cutover inside a feature launch; rollback must be clean.

Integration pattern to enforce in review. Layer authorization deliberately: route-level coarse gate, explicit abort_unless/can() check in controllers and Livewire actions, and Blade @can as cosmetic only. Every @can must have a matching server-side check behind it or we have shipped a UI that lies about its security posture. Prefer $user->can('permission') over hasRole() so business logic stays decoupled from role names — that is also our swap path later.

Operational Impact

Maintenance. Treat this as vendored, not depended-on. Low stars and zero dependents mean upstream fixes arrive on one maintainer's schedule; the active patch line (v1.1.20 → v1.1.21 with a merged external PR) reassures on abandonment risk but says nothing about correctness. Name a fork owner and keep the exit runbook current. Expected upkeep: 2–5 engineer-days per Laravel major, 5–10 per Splade/Livewire major, plus smoke tests on admin list screens with each bump.

Support. None. No Stack Overflow tag, no Discord, no paid tier, no documented support channel. Escape hatches are reading src/ and Spatie's docs. Keep the source open beside the IDE for week one and expect the first integration bug to be diagnosed by reading code, not by asking anyone.

Scaling. Two cost centers. First, the shipped UserTable extends into user management — filterable admin list queries are the expensive ones at scale, so instrument them before the admin user base grows. Second, permission cache behavior: cache invalidation here is a security bug, not a performance bug. A stale cache means a revoked role retains access until TTL expiry. The round-trip test (assign → assert allowed → revoke → assert denied, without process restart) belongs in CI, and a cache reset must be wired into the role mutation flow.

Failure modes and how we detect them.

  • Cross-guard leakage — a web-guard user satisfying an admin-guard hasPermissionTo(), or the same role name in another tenant inheriting permissions. Detect via explicit negative tests per guard; this is the top production authz bug in this ecosystem.
  • Stale permission cache — cache reset fixes the symptom, so log it rather than closing the ticket; recurring occurrences mean the mutation flow is incomplete.
  • UI-only gating — a shipped @can with no matching middleware or check behind it.
  • Silent escalation — the general case: nothing breaks visually, so only tests and audit logging surface it. Fund an audit trail on role/permission mutation from day one.
  • Splade drift — the v1.1.21 SelectFilter issue is the template: an upstream API change surfacing as a package bug rather than a clean composer conflict.

Ramp-up. Roughly 0.5 day to first working role assignment, 1–2 days to production confidence including the negative-case and cache tests. Add 2–4 days if we build a custom role editor for dimensions the packaged UI does not understand (per-department scoping, row-level rules — expect to fight the fixed UI there, not the trait). Recommend a named fork owner and a short internal runbook covering the three debugging commands (getRoleNames(), getAllPermissions(), Gate::forUser()->allows()) so triage does not depend on one person's memory.

PM recommendation. Approve as an opportunistic internal-tooling dependency conditioned on three gates: (a) the deny-by-default spike passes at HTTP and Blade layers, (b) the wraps-Spatie question resolves affirmatively, and (c) the exact version matrix is pinned and covered by tests. Reject if authorization is customer-facing, security-critical, compliance-driven, multi-tenant, or requires ABAC/SSO/row-level policy. Because domain code continues to ask $user->can('resource.action'), this decision is reversible within a sprint — which is precisely what makes it approvable at all.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator