elpandape/filament-permission
elpandape/filament-permission is a Filament plugin for managing roles and permissions in Laravel admin panels. It provides UI resources for creating roles, assigning permissions, and controlling access to Filament resources and pages, helping teams implement authorization quickly.
Scope and evidence base. The only artifact supplied is the v1.10.0 changelog. No package metadata, composer constraints, service-provider surface, test suite results, or downstream consumers were provided. This assessment therefore reads the release as a security-model change to a privileged-role (super-admin) governance package — evidently with a Filament-style admin panel and relation-manager UI — and flags everything that must be verified before adoption rather than asserting it.
Architecture fit. The package sits on the authorization boundary: it governs who may hold and hand on the top-tier "privileged" role, and it enforces that boundary in both policy code and panel UI (relation managers). For a TPM this is high-blast-radius territory — a defect here is a privilege-escalation or a lockout, not a cosmetic bug. It fits well where an application needs a single, well-guarded super-admin role, mediated through an operator UI, with the invariant that the platform can never be left without an administrator. It is a poorer fit for organisations needing fine-grained, delegated role administration (see the revocation tightening below) or multi-tenant scoping that the changelog does not address.
What v1.10.0 actually changes. Three behaviour changes and one API addition:
| Change | Direction | TPM read |
|---|---|---|
| Privileged role is now granted by a current holder rather than by nobody | Widening of UI capability (previously no path existed in-product) | Deliberate, reasoned trade-off: the author argues "refuse to everybody" only pushed escalation onto a clunkier route (grant a role the whole catalogue, then hand that over). Net security posture is arguably improved by making the sanctioned path explicit and auditable — but it is a genuine capability expansion and needs security sign-off |
Grant check is evaluated against the role, not its permissions, so it does not leak via grants.unrestricted |
Tightening / anti-leak | Important: a user holding the "unrestricted grant" permission cannot use it to obtain or confer the privileged role. Good separation-of-duties property; must be regression-tested, as it is the kind of check that silently inverts |
| A role can only be revoked by someone who could have granted it; the relation manager no longer offers to detach roles "reaching further than the editor" | Tightening | Fixes a real over-permission in the UI. Most likely source of user-visible workflow breakage — role admins will lose detach buttons they previously had |
| The privileged role cannot be stripped from its last holder | Tightening / availability guard | Prevents the classic "panel with no admins, fixable only by SSH" outage. Operationally this means a deliberate de-privileging of the final holder is now impossible in-product — a runbook item, not a bug |
PrivilegedRole::isLastHolder() added |
API surface | Small, useful primitive; lets our own code and tests assert the lockout invariant. Public API means semver commitment — treat as a support obligation |
Technical risk.
^1.9 will absorb it silently.Key questions for the maintainer.
isLastHolder() consider soft-deleted or deactivated holders? A "last holder" who cannot log in is not a holder in practice.grants.unrestricted scoped — global, per-panel, per-tenant? Does the anti-leak check hold in multi-tenant panels?Stack fit. Presumably a Laravel package with a Filament panel integration and a policies/gates layer. Integration is low-friction at the mechanical level — composer require/update, no migrations or schema changes are indicated — and high-friction at the governance level, because it changes who can do what in the admin UI. Budget effort for policy review and QA, not for plumbing.
Compatibility and version stance. Treat v1.10.0 as behaviourally breaking inside a minor version. Pin exactly (1.10.0) rather than floating ^1.10 until the next patch is reviewed, and confirm PHP/Laravel/Filament constraint compatibility against the package's composer.json before scheduling — the changelog does not state supported versions.
Migration path.
Sequencing.
If the maintainer cannot confirm audit logging or a documented upgrade path, sequence a security review gate ahead of the staging soak rather than parallel to it.
Maintenance. Small, stable surface — one new public method is the entire forward-compatibility commitment. Ongoing cost is dominated by reviewing future releases of this package carefully, not by upkeep. Set the expectation that every release touching the privileged-role rules gets a policy diff review; the changelog's prose style is explanatory rather than precise, so source review is mandatory.
Support and process. Three runbook and training updates are required at go-live:
Scaling. No scaling concern in the performance sense — this is authorization logic, not a hot path. The scaling limit is administrative: with more admins and more roles, the "you may only revoke what you could grant" rule pushes delegated role management up to holders. At small scale that is a feature (separation of duties). At organisational scale it can create a bottleneck where every role change routes through a handful of super admins. If delegation is a near-term requirement, treat this as a known constraint and plan either a scoped-role design or a documented exception process — do not work around it by broadening the privileged role.
Failure modes.
| Failure | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Admin loses a detach action they depended on | Medium | Low–Medium (process friction, support load) | Pre-announce; document the grant-then-revoke path |
| Over-broad handover of the privileged role (no process gate) | Medium | High (privilege escalation) | Approval workflow outside the package; audit review |
Anti-leak check regresses in a future release, letting grants.unrestricted confer the privileged role |
Low | High | Regression test in your own suite; assert on every upgrade |
| Last-holder guard misjudges "holder" (deactivated/soft-deleted users) | Low–Medium | High (panel with no usable admin) | Test with a deactivated sole holder; maintain verified CLI recovery drill |
| Silent behavioural change absorbed by a floating version constraint | Medium | Medium–High | Pin exact versions; gate package upgrades on policy diff review |
| Audit trail for handovers absent | Unknown | Medium–High (compliance) | Confirm with maintainer; add application-level logging if missing |
Ramp-up. Roughly half a day for an engineer familiar with Laravel authorization to read the source diff and build the role × action test matrix; roughly half a day of QA to exercise the handover and lockout paths in staging; plus a short enablement note for panel administrators. The unfamiliar piece is not the code but the policy intent — the release is explicitly reasoned about who should be able to reach the top, and the team needs to agree that reasoning is acceptable for this system before shipping.
Overall recommendation. Adopt, with a policy review gate and exact version pinning. The release is a net improvement in both security posture (revocation now bounded by grant authority; no leak through grants.unrestricted) and availability (no last-holder lockout), and the maintainer shows sound reasoning about the threat model. The residual risks are process risks — unreviewed capability expansion and untested lockout recovery — not code-quality risks, and both are cheap to close.
How can I help you explore Laravel packages today?