PHPackages                             modularize-rbac/core - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. modularize-rbac/core

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

modularize-rbac/core
====================

Framework-agnostic core for modular RBAC: modules, roles, permissions, i18n translations. Pure PHP, hexagonal architecture.

v1.9.0(2w ago)11.7k1MITPHPPHP ^8.2CI passing

Since May 22Pushed 2w agoCompare

[ Source](https://github.com/chrisdjst/access-core)[ Packagist](https://packagist.org/packages/modularize-rbac/core)[ GitHub Sponsors](https://github.com/sponsors/chrisdjst)[ RSS](/packages/modularize-rbac-core/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (6)Dependencies (2)Versions (36)Used By (1)

modularize-rbac/core
====================

[](#modularize-rbaccore)

Framework-agnostic core for modular RBAC: **modules + roles + permissions + i18n translations** in pure PHP 8.2+.

[![CI](https://github.com/chrisdjst/access-core/actions/workflows/ci.yml/badge.svg)](https://github.com/chrisdjst/access-core/actions/workflows/ci.yml)[![Packagist](https://camo.githubusercontent.com/009a4b989d1d919968b281ca64c3dbef0474a4bab240ce5d4f55dcf1f040688b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d6f64756c6172697a652d726261632f636f72652e737667)](https://packagist.org/packages/modularize-rbac/core)[![License: MIT](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)

What it is
----------

[](#what-it-is)

`access-core` is the framework-agnostic heart of the `modularize-rbac/*` family â€” pure PHP with zero framework dependency. It contains:

- **Domain layer** â€” entities (`Module`, `Role`, `Permission`, `Language`, `Translation`, `RoleModulePermission`, ...), immutable value objects (`Uuid`, `ModuleSlug`, `LanguageCode`, `GuardName`, `PermissionName`, `RoleLevel`), domain services (`PermissionFlagResolver`, `TranslationResolver`, `RoleModulePermissionSynchronizer`), domain events.
- **Application layer** â€” use-cases (`CreateModule`, `UpdateModule`, `SyncRoleModules`, `SetDefaultLanguage`, ...) and the ports the host must implement: `*Repository`, `UnitOfWork`, `Clock`, `IdGenerator`, `LocaleResolver`, `Authorizer`, `DomainEventDispatcher`, `ExternalPermissionGateway`.

Drop it into any PHP project, implement the ports with whatever ORM / HTTP / event bus you use, and the use-cases run.

Why a separate package
----------------------

[](#why-a-separate-package)

A clean port boundary between domain logic and Laravel-specific infrastructure:

- **SOLID**: each use-case has one job; the synchronizer is testable without a DB; ports are small and focused.
- **Reusable**: the same use-cases run from Laravel, Symfony, Slim, or plain-PHP CLI.
- **Testable**: 115 unit + application tests run in ~0.4s with no framework, no DB.

Install
-------

[](#install)

```
composer require modularize-rbac/core
```

PHP 8.2+. No other runtime dependency.

Existing adapters
-----------------

[](#existing-adapters)

- **Laravel**: [`modularize-rbac/laravel`](https://github.com/chrisdjst/access-laravel) â€” Eloquent repositories, HTTP controllers, FormRequests, migrations, optional Spatie integration.
- *Symfony, Slim, plain PHP*: not shipped today; PRs welcome.

Quick example (wiring use-cases by hand)
----------------------------------------

[](#quick-example-wiring-use-cases-by-hand)

```
use ModularizeRbac\Core\Application\Module\CreateModule\CreateModule;
use ModularizeRbac\Core\Application\Module\CreateModule\CreateModuleInput;
use ModularizeRbac\Core\Tests\Application\Doubles\{
    InMemoryModuleRepository,
    AllowingAuthorizer,
    PassthroughUnitOfWork,
    RecordingEventDispatcher,
    SequentialIdGenerator,
    FixedClock,
};

$create = new CreateModule(
    modules: new InMemoryModuleRepository(),
    authorizer: new AllowingAuthorizer(),
    uow: new PassthroughUnitOfWork(),
    events: new RecordingEventDispatcher(),
    ids: new SequentialIdGenerator(),
    clock: FixedClock::at('2026-05-22T00:00:00Z'),
);

$module = $create->execute(new CreateModuleInput(
    slug: 'events',
    name: 'Events',
    redirect: '/events',
    icon: 'calendar',
    rootModuleId: null,
    sortOrder: 10,
));

echo $module->id; // UUID
```

In real apps, replace the in-memory doubles with adapters that talk to your DB / event bus / authz system.

Architecture
------------

[](#architecture)

```
src/
â”œâ”€â”€ Domain/
â”‚   â”œâ”€â”€ Shared/                   # Uuid, Clock (port), IdGenerator (port), DomainEvent
â”‚   â”œâ”€â”€ Module/                   # Module entity, ModuleSlug VO, ModulePermission entity
â”‚   â”œâ”€â”€ Role/                     # Role entity, GuardName VO, RoleLevel VO
â”‚   â”œâ”€â”€ Permission/               # Permission entity, PermissionName VO
â”‚   â”œâ”€â”€ RoleModulePermission/     # RoleModulePermission entity + domain services
â”‚   â”œâ”€â”€ Translation/              # Language, Translation entities, TranslationResolver
â”‚   â””â”€â”€ Events/                   # ModuleCreated, RolePermissionsChanged, ...
â”œâ”€â”€ Application/
â”‚   â”œâ”€â”€ Module/                   # CreateModule, UpdateModule, DeleteModule, ListModules, ShowModule
â”‚   â”œâ”€â”€ Role/                     # ListRoles, ShowRole, UpdateRole, SyncRoleModules
â”‚   â”œâ”€â”€ Language/                 # ListLanguages, ShowLanguage, CreateLanguage, UpdateLanguage, DeleteLanguage, SetDefaultLanguage
â”‚   â””â”€â”€ Ports/                    # *Repository, UnitOfWork, LocaleResolver, Authorizer, ...
â””â”€â”€ Exceptions/                   # InvalidInput, NotFound, AuthorizationFailed

```

Ports you need to implement
---------------------------

[](#ports-you-need-to-implement)

For a host to use this package, it must provide implementations of these interfaces (defined in `src/Application/Ports/`):

PortWhat it does`ModuleRepository`Persist/lookup `Module` aggregates`RoleRepository`Persist/lookup `Role` aggregates`PermissionRepository`Persist/lookup `Permission` aggregates`LanguageRepository`Persist/lookup `Language` aggregates`TranslationRepository`Persist/lookup `Translation` rows by polymorphic owner`RoleModulePermissionRepository`Persist/lookup role-module binding rows`UnitOfWork`Wrap a closure in a transaction`Clock`Read "now" (`DateTimeImmutable`)`IdGenerator`Mint fresh UUIDs`LocaleResolver`Current locale + fallback locale`Authorizer`Resolve actor id; check abilities; throw `AuthorizationFailed``DomainEventDispatcher`Forward domain events to the host's bus`ExternalPermissionGateway`Optional â€” replicate grants/revokes into an external authz store (e.g. Spatie). A `NullExternalPermissionGateway` is a valid no-op.The Laravel adapter implements all of these against Eloquent + Laravel's container.

Domain services
---------------

[](#domain-services)

These pure-function services hold the non-trivial business logic; they're directly callable from any use-case or host code:

- **`PermissionFlagResolver`** â€” converts the canonical 5-flag boolean tuple (`is_listing_allowed`, `is_reading_allowed`, `is_writing_allowed`, `is_editing_allowed`, `is_delete_allowed`) into Spatie-style action names (`list`, `view`, `create`, `update`, `delete`).
- **`RoleModulePermissionSynchronizer`** â€” given a module slug + desired flag set + current permissions a role holds, computes the (grant, revoke) plan. **Preserves non-managed permissions** like `manage`/`sign`/`approve` that the host may have added outside this package.
- **`TranslationResolver`** â€” resolves a field's translation in a target locale, falling back to a configured default locale, then to the raw attribute.

Test plan
---------

[](#test-plan)

```
composer install
composer test    # 115 tests, ~0.4s, no framework
composer stan    # PHPStan level 8
```

License
-------

[](#license)

MIT â€” see [LICENSE](./LICENSE).

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance97

Actively maintained with recent releases

Popularity24

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

11

Last Release

15d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/30989810?v=4)[Christopher Steffens Theilacher ](/maintainers/chrisdjst)[@chrisdjst](https://github.com/chrisdjst)

---

Top Contributors

[![chrisdjst](https://avatars.githubusercontent.com/u/30989810?v=4)](https://github.com/chrisdjst "chrisdjst (51 commits)")

---

Tags

i18nrolespermissionsrbacmodulesdddhexagonalaccess-control

###  Code Quality

TestsPest

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/modularize-rbac-core/health.svg)

```
[![Health](https://phpackages.com/badges/modularize-rbac-core/health.svg)](https://phpackages.com/packages/modularize-rbac-core)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k98.0M1.3k](/packages/spatie-laravel-permission)[santigarcor/laratrust

This package provides a flexible way to add Role-based Permissions to Laravel

2.3k5.6M46](/packages/santigarcor-laratrust)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k3.5M115](/packages/bezhansalleh-filament-shield)[pktharindu/nova-permissions

Laravel Nova Grouped Permissions (ACL)

136409.8k](/packages/pktharindu-nova-permissions)[silvanite/novatoolpermissions

Laravel Nova Permissions (Roles and Permission based Access Control (ACL))

100262.7k2](/packages/silvanite-novatoolpermissions)[hasinhayder/tyro

Tyro - The ultimate Authentication, Authorization, and Role &amp; Privilege Management solution for Laravel 12 &amp; 13

6753.6k5](/packages/hasinhayder-tyro)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
