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

Laravel Entitlements Laravel Package

masterix21/laravel-entitlements

A flexible Laravel package for managing feature entitlements, plans, and quotas. Define features, attach them to plans or Eloquent models, then check access, consume limited usage, and control what each user or team can do via a clean, expressive API. Ideal for SaaS feature gating.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • masterix21/laravel-entitlements is a domain package for plan/license entitlement management in Laravel: plans composed of typed items (slot, computed, etc.), licenses as the unit of allocation, usages as the consumption record, and PlanTransition as the state machine for upgrades/downgrades/cancellation. It fits products with seat-based or metered feature gating where entitlement state must be auditable rather than recomputed ad hoc.
  • Release 1.3.1 is a hardening release, not a feature release. Its value to a TPM is risk reduction: it closes race conditions in slot release and concurrent changePlan(), adds a database-level invariant, and makes domain events transaction-safe. These are exactly the defects that surface as intermittent, hard-to-reproduce entitlement drift in production.
  • The package is opinionated about persistence (its own tables, publishable migrations/config) and about the UI layer (a first-class Filament plugin for plan management, plan changes, and force-release operations). That is a good fit if the host app already standardizes on Filament; it is a partial-fit if admin tooling is custom-built, in which case the Filament plugin is dead weight and only the core service is leveraged.
  • Configurable models via entitlements.models.* and a typed type_enum with label resolution make the package extensible without forking, which matters for long-term ownership.

Integration feasibility

  • Integration is standard Laravel package mechanics: publish config, publish migrations, run php artisan migrate, optionally publish translations and Filament assets. No service mesh, queue, or external dependency is introduced.
  • The 1.3.1 migration adds a unique index on entitlement_plan_items (plan_id, type). This is the single highest-friction item in the release: it will fail on any environment that already contains duplicate plan/item-type rows, which is plausible in databases that predate the Filament repeater validation.
  • Two behavioral changes require host-app code review rather than mere deployment:
    • Domain events now dispatch in DB::afterCommit. Any listener that previously read uncommitted state (or that relied on being invoked before rollback) changes semantics. Listeners are now not invoked at all when the surrounding transaction rolls back — which is the correct behavior, but it is a silent behavioral break for existing listeners.
    • Translations move from the app root lang/ to lang/vendor/laravel-entitlements/. Customized copies left in place will be silently ignored, producing untranslated UI rather than an error.
  • forceRelease() now decrements slot_used by the usage amount instead of always 1. This corrects a real accounting bug but changes historical expectations; any reporting built on prior behavior should be re-baselined.
  • The filament-badgeable-column constraint tightened to ^4.0. This is a build-reproducibility fix; it will surface as a composer conflict only in projects that pinned the transitive dependency at a Filament 3-compatible version.

Technical risk

  • Medium overall, concentrated in the database migration and the event-timing change. Both are one-way doors: the unique index requires data remediation before it can apply, and post-commit event dispatch cannot be trivially reverted without patching vendor code.
  • The concurrency fixes (anchor license locking, slot re-check-and-lock) reduce but do not eliminate risk. Row-level locking on a hot anchor license serializes plan changes for a license group; under load this is a throughput ceiling, and lock-ordering between changePlan() and slot operations is a deadlock surface that a patch release does not fully document.
  • Test coverage grew from 126 to 135 tests (433 assertions) with explicit regression tests per fix. That is credible but modest for a concurrency-sensitive domain; concurrency regressions are the class of bug least reliably caught by a unit/integration suite.
  • Vendor concentration risk is real: entitlement logic is load-bearing for billing and access control. Any defect here is a revenue or access incident, not a cosmetic bug.

Key questions

  • What are the supported Laravel/PHP/Filament version ranges, and does 1.3.1 change any of them implicitly via the filament-badgeable-column pin?
  • Is there a documented upgrade path from 1.3.0, including a duplicate-detection query for entitlement_plan_items (plan_id, type)?
  • Do any production rows currently sit in Releasing state (the state the slot race fix protects)? Is remediation required, or does the code self-heal?
  • Which host-app listeners depend on pre-commit entitlement events, and has each been reviewed for the afterCommit change?
  • How are slot_used counters reconciled after the forceRelease() amount change — is there a recompute command, or is drift accepted?
  • Are lock acquisitions wrapped with deadlock retry/backoff, and is lock ordering documented?
  • What observability exists for PlanTransition rows stuck in Pending or Failed?
  • Is the package multi-tenant aware, or does tenancy have to be layered on via the configurable models?

Integration Approach

Stack fit

  • Assumes a Laravel application with relational database support for row-level locking (MySQL/Postgres with InnoDB-equivalent semantics). The 1.3.1 fixes are locking-based; environments on SQLite or non-locking engines will not benefit from the concurrency guarantees and should not treat 1.3.1 as a correctness fix.
  • Filament is a first-class integration surface: plan CRUD, plan change, and force-release slot all have UI. If Filament is already the admin stack, integration cost is low. If not, scope the work to the core service plus custom admin endpoints and explicitly descope the plugin.
  • Configuration-driven model overrides and a typed type_enum mean the package can host custom item types with registered resolvers without forking — the recommended extension path.

Migration path

  1. Audit for duplicate (plan_id, type) rows in entitlement_plan_items before publishing the new migration; remediate or merge duplicates. Treat this as a blocking prerequisite, not a post-deploy fix.
  2. Publish and run the 1.3.1 migration (vendor:publish --tag="entitlements-migrations" then php artisan migrate) in staging first, with a snapshot for rollback.
  3. Move any customized translation files to lang/vendor/laravel-entitlements/ and delete the root copies to avoid shadowing confusion.
  4. Review every listener on the four PlanTransition events (and other entitlement domain events) for post-commit semantics. Update listeners that assumed pre-commit visibility; confirm that rollback-safe behavior is acceptable for each side effect (email, webhook, downstream provisioning).
  5. Re-baseline any metric or report derived from slot_used given the forceRelease() decrement change.
  6. Pin filament-badgeable-column to ^4.0 and verify the Filament admin renders — the unregistered view namespace failure mode is a hard UI break, not a warning.

Compatibility

  • 1.3.1 is a patch version but carries three effective breaking changes for host apps: the unique index (data-dependent), the afterCommit event dispatch (listener-dependent), and the translation path (asset-dependent). Version-number-based risk assessment is unsafe here; treat it as a minor release for planning purposes.
  • No deprecations are introduced. No public API is removed. The Entitlements facade docblock now declares changePlan(), cancelTransition(), and applyDueTransitions(), which is documentation-only but improves static analysis and IDE support.
  • The Filament UX fixes (current plan visible but disabled, TransitionAlreadyResolved surfaced as a notification instead of a 500) reduce support noise and are safe to adopt.

Sequencing

  • Phase 1 — Data audit and staging migration (duplicate check, index, translation move). Gate: clean migrate on a production-sized snapshot.
  • Phase 2 — Event listener review and, if any listener is affected, deploy the listener changes and the package bump in the same release window, since the two are coupled.
  • Phase 3 — Filament plugin adoption and admin regression pass (plan form type uniqueness, delete guards, change-plan flow, force release across the license group).
  • Phase 4 — Adopt the Boost AI guidelines into the repo so AI-assisted contributions follow the package's strategy semantics and post-commit event guarantee. Low effort, disproportionate return on correctness of future changes.
  • Do not split the event-timing change from the package upgrade; deploying them separately creates a window where listeners run against the wrong transaction semantics.

Operational Impact

Maintenance

  • Low steady-state maintenance: config, migrations, and translations are all publishable and versioned. The main ongoing cost is upstream tracking — this package's correctness surface is concurrency, where regressions are discovered in production rather than in CI.
  • The new unique index converts a class of silent data corruption into a loud constraint violation. Operationally that is a win, but it means a previously-silent bug now manifests as admin-facing form errors; support docs should pre-empt this.
  • Shipping Boost AI guidelines reduces the cost of onboarding contributors and reduces the chance of AI-assisted code reintroducing the exact pitfalls fixed here (double-decrement, non-atomic transitions). Treat the guidelines directory as a maintained artifact, not a one-time readme.

Support

  • Expect a short spike in tickets after rollout, from three sources: plan save failures from the new index (only if duplicates were not pre-remediated), untranslated admin strings from the translation path move, and any downstream automation whose listener stopped firing on rollback. All three are diagnosable but none are self-evident from the error surface.
  • The Filament UX fixes measurably reduce ticket volume: TransitionAlreadyResolved now produces a notification rather than a 500, and plan deletion for referenced plans is blocked with an explanation rather than failing at the database. Both were guaranteed support generators previously.
  • IncompatiblePlanTransition being raised upfront for downgrades below current computed usage, and for plan changes toward empty plans, moves failures from post-commit inconsistency to a predictable, catchable exception. Support can now script a known response.

Scaling

  • Throughput on plan changes is bounded by the anchor license row lock. A single high-traffic license group with frequent transitions becomes a serialization point. Model this before assuming linear scaling; for most seat-based products the volume is negligible, but for metered/usage-heavy accounts it is not.
  • Slot release now takes locks on the usages it is about to mark. Hot-slot contention is the realistic bottleneck under bursty provisioning. Watch for lock wait timeouts as the leading scaling indicator.
  • The applyDueTransitions() path is batch-shaped and is the natural place to absorb deferred transition processing; the facade now documenting it suggests it is the intended escape hatch for load-shedding plan changes.
  • Reads (entitlement checks) remain uncontentious; the cost model is write-side, which is the favorable shape.

Failure modes

  • Migration failure on duplicate (plan_id, type) rows — high likelihood if not pre-audited, high blast radius (deploy blocked). Mitigate with a pre-flight duplicate query.
  • Silent listener non-invocation on rollback after the afterCommit change — low likelihood, high severity if a listener performed downstream provisioning that now has no compensating action.
  • Double-decrement of slot_used is now fixed, but existing data written under the old behavior may still be wrong. Treat historical counters as suspect and reconcile.
  • Usages stuck in Releasing still exist as a state; the fix prevents new instances from double-releasing but does not add a reconciler. Without an operational sweep, drift remains possible from prior occurrences.
  • Deadlock or lock-timeout bursts under concurrent plan change and slot release on the same license group — the locking fixes are correct in ordering intent but do not advertise retry semantics.
  • Filament table rendering breakage from an unresolvable filament-badgeable-column version — now prevented by the ^4.0 pin, but any host app with an existing lockfile must run composer update on that package rather than assuming the constraint applies retroactively.
  • Missing translations after the path move degrade admin UX without erroring, making the regression easy to miss in QA.

Ramp-up

  • Moderate for the core domain: strategy semantics, plan/item invariants, and transition validation are non-obvious and were previously tribal knowledge. The 1.3.1 documentation work — README covering plan_transition config keys, all four PlanTransition events, a complete exceptions reference, plus the Boost guidelines — materially shortens this and is the most transferable part of the release.
  • Ramp-up for the Filament plugin is low; the UI fixes make the admin surface more self-explanatory.
  • Ramp-up for the concurrency model is the residual gap: the post-commit event guarantee is documented, but lock scope, lock ordering, and deadlock retry behavior are not. Budget an engineer-day for a team member to read SlotStrategy and changePlan() directly before owning this package.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource