mabrouk/permission
A Laravel package for managing roles and permissions, helping you assign access rights to users and protect routes or features with a simple, configurable permission system.
This package manages per-user endpoint registrations (webhooks/API targets) and keeps a cache of each user's endpoint set so request-time lookups don't hit the database. Version 4.0.1 is a patch that fixes the cache not being invalidated when a new endpoint is added — the single most important behaviour to verify in your first hour with the package.
Minimal setup:
composer require <vendor>/<package> (4.x requires PHP 8.1+ / Laravel 10+ — confirm against the composer constraints before upgrading a 3.x app).php artisan vendor:publish --tag="<package>-migrations" && php artisan migrate.php artisan vendor:publish --tag="<package>-config". Read this file first — it defines the cache store, key prefix, and TTL that everything else hinges on.HasEndpoints trait) to your User model.Where to look first, in order: the config file → the migration (tells you the columns and indexes the cache is keyed on) → the service provider (shows what gets bound and whether an event listener or observer is responsible for invalidation) → the README's "Caching" section.
First use case: create an endpoint for a user via the package API (or $user->endpoints()->create([...]) if you're using the relation), then immediately read the endpoint list back through the cached accessor in the same request and again in a fresh request. On 4.0.1 both reads must include the new endpoint. On 4.0.0 the second read would have been stale — which is the bug this release closes. Make that a test in your suite, not a manual check.
Register through the package, not the database. The cache invalidation in 4.0.1 is wired into the package's model/observer path. If any code path inserts endpoints directly (raw DB::table(...)->insert(), a seeder, an importer), the cache will not be flushed. Route all writes — create, update, delete, soft-delete, restore — through the model or the service class. If you must bypass it, call the package's cache-flush method explicitly afterwards.
Model events are the invalidation seam. The natural extension point is the endpoint model's created/saved/deleted events. If you need custom behaviour (e.g. fanning out to a per-team cache key as well as a per-user one), register an additional observer rather than editing vendor code, and keep it idempotent — events can fire more than once inside a transaction that retries.
Bulk operations need an extra step. Model::insert() and mass update() calls skip model events entirely. For imports or backfills, disable the cache during the operation (a maintenance flag or a withoutCache helper), run the write, then warm the cache in one pass. Per-row invalidation across 50k rows is a stampede, not a strategy.
Queue-friendly warm-up. After deploys and bulk changes, a small artisan command or job that iterates users and primes the cache avoids the thundering-herd pattern where every user's first request after a deploy re-queries. If the package exposes a TTL in config, pair the warm-up cadence with it so you're never warming entries that expire before they're read.
Multi-tenant / multi-guard. If endpoints are scoped by tenant as well as user, the cache key must include the tenant discriminator or you'll serve one tenant's endpoints to another. Confirm the key composition from the config prefix and the package's key-building method; override it if the default is user-only.
Testing pattern. Use the array cache driver in tests only if you've verified key behaviour, otherwise use database or file so prefix and TTL logic actually runs. A RefreshDatabase test that asserts a second read reflects a newly created endpoint is the regression test worth keeping.
Upgrading 4.0.0 → 4.0.1. No API changes. Deploy normally, but if you added endpoints during the 4.0.0 window and your cache TTL is long, flush the endpoint cache once after deploying so the stale entries are cleared rather than waiting out the TTL.
created flushes but restored (soft deletes) does not — check your model's $dates/soft-delete setup and test restore explicitly.php artisan cache:forget <key> and re-read. If the flush fixes it, it's an invalidation path, not a query bug.file and database drivers do not support them and will fail or silently misbehave. redis or memcached are the safe choices for tagged invalidation; array in tests will mask tag problems entirely.DB::afterCommit() or wrap writes so the flush lands after commit.How can I help you explore Laravel packages today?