modera/security-bundle
Modera Security Bundle provides reusable security components for Symfony applications, including user authentication, role-based access control, and integration points for managing permissions in Modera-based projects. It helps centralize security configuration and common access-control workflows.
Architecture fit: none. Despite being surfaced in a Laravel/PHP package review, modera/security-bundle is a Symfony bundle, not a Laravel package. It targets the Symfony Security component (voters, firewall listeners, TokenInterface), ships a Symfony DI extension for service wiring, and maps its domain model through Doctrine ORM. Laravel has no bundle concept, its authorization stack is Illuminate\Auth + Gate/Policy, and its persistence defaults to Eloquent. There is no seam where this drops in. The [READ-ONLY] prefix is Modera's marker for archived/split-repo code, not an active product line.
Integration feasibility: low. Making it work in Laravel means porting three separable concerns: (1) the DI extension and service definitions, (2) the Doctrine mapping for User/Group/Permission, and (3) the enforcement layer, which is coupled to Symfony's security context. At that point the package has been rewritten, and the only durable asset left is the Users → Groups → Permissions relational shape — a commoditized pattern already native to Laravel and implemented by maintained packages. The real cost in any RBAC build is the enforcement path (permission resolution, caching, invalidation at the security boundary), not the schema, and this bundle's enforcement path does not transfer.
Technical risk: high.
Key questions for the team:
Gate/Policy plus a maintained RBAC package (e.g. spatie/laravel-permission) already cover the requirement?Stack fit. Mismatched at every layer: Symfony DI vs. Laravel service providers, Doctrine entities vs. Eloquent models, Symfony voters vs. Laravel gates. Treat it as a reference implementation to read, not a dependency to install.
Recommended path — extract, don't adopt.
User ↔ Group ↔ Permission, likely many-to-many on both hops, plus any computed getPermissions()).belongsToMany relations and a pivot-table cache of effective permissions.Gate::before/policies, resolving from the cached permission set rather than walking relations per request.spatie/laravel-permission — actively maintained, Laravel-native, same model.Migration path. If a legacy Symfony service already runs this bundle, use a strangler pattern: stand up the Laravel authorization layer in parallel, dual-write group/permission assignments, and cut reads over per endpoint behind a feature flag. Do not bridge Symfony's security context into Laravel's — route through a shared data store instead.
Compatibility. Assume PHP 5.6–7.0 and Symfony 2.8/3.x. It will not install cleanly on PHP 8.x. If a spike is required for due diligence, run it in an isolated container, never in the application's dependency graph.
Sequencing.
Maintenance. Adoption means permanent custodianship: no upstream fixes will arrive, so every PHP minor, framework major, and security advisory becomes internal work. Budget ongoing ownership against a one-time build — the build is cheaper within roughly two upgrade cycles.
Support. None. No maintainer response, no issue triage, no security disclosure channel. For code sitting on the authorization boundary, that absence is a finding in any audit and a blocker in most organizations.
Scaling. The mapped model invites N+1 queries on permission resolution and a multi-hop join per authorization check. Any production implementation needs an effective-permission cache (per-user, per-tenant) with explicit invalidation on group or role mutation, plus a warm-up strategy. This is the highest-effort part of the build regardless of which library is chosen.
Failure modes to design against:
Ramp-up. Low learning return, high translation cost. The only durable knowledge transfer is the domain model, legible in an afternoon; engineers will spend more time fighting the abandoned dependency graph than understanding the design.
Recommendation: do not adopt as a dependency. Consume it as a one-time architectural reference, build the RBAC layer natively on Laravel's Gate/Policy or a maintained package, and record the decision so it is not re-litigated when the next "we found a library for this" surfaces.
How can I help you explore Laravel packages today?