gesmuni/laravel-auth-base

Core domain interfaces and entities for Gesmuni Auth - a mode-agnostic RBAC authentication library

Maintainers

Package info

gitlab.gitlab.videoatencion.com/gesmuni/php-laravel/laravel-auth-base.git

pkg:composer/gesmuni/laravel-auth-base

Statistics

Installs: 146

Dependents: 1

Suggesters: 0

1.1.0 2026-03-27 10:25 UTC

This package is not auto-updated.

Last update: 2026-05-08 11:06:44 UTC


README

License: AGPL v3 PHP Version

Core domain interfaces and entities for Gesmuni Auth - a mode-agnostic RBAC authentication and authorization library.

This package provides the pure domain layer with interfaces, entities, value objects, and DTOs. It has zero dependencies and can be used in any PHP 8.1+ project. Concrete implementations (Eloquent adapters, HTTP clients, etc.) are provided in separate packages.

Features

  • Mode-Agnostic Architecture: Same interface for Local, Client, and Service deployment modes
  • Ports & Adapters Pattern: Clean separation between domain contracts and implementations
  • RBAC with Namespaces: Per-application role and permission isolation
  • Group-Based Permissions: Hierarchical groups with role inheritance
  • Two Actor Types: HUMAN (with roles) and APPLICATION (authentication only)
  • PHP 8.1+ Features: Native enums, readonly properties, typed properties
  • Zero Dependencies: Pure PHP domain layer

Installation

composer require gesmuni/laravel-auth-base

Package Structure

src/
├── Entities/              # 13 domain entities
│   ├── Actor.php          # HUMAN or APPLICATION actors
│   ├── Role.php           # Roles with permissions
│   ├── Permission.php     # Atomic permissions
│   ├── Group.php          # Hierarchical groups
│   └── ...
├── ValueObjects/          # Enums and value objects
│   ├── ActorType.php      # HUMAN | APPLICATION
│   ├── ActorStatus.php    # ACTIVE | SUSPENDED | BLOCKED | INACTIVE | DELETED
│   ├── PermissionSlug.php # Validated namespace.resource:action
│   └── ...
├── Contracts/
│   ├── Services/          # Public API interfaces
│   │   ├── AuthQuery.php  # Read-only operations
│   │   └── AuthAdmin.php  # Read + write operations
│   └── Repositories/      # Repository ports (13 interfaces)
│       ├── ActorRepository.php
│       └── ...
├── DTOs/                  # Data Transfer Objects
│   ├── Input/             # CreateActorInput, UpdateActorInput, etc.
│   └── Result/            # AuthResult
└── Exceptions/            # Domain exceptions
    ├── ActorNotFoundException.php
    ├── PermissionDeniedException.php
    └── ...

Core Concepts

Entities

The domain model consists of 13 entities:

  • Actor: HUMAN or APPLICATION with authentication and status
  • Role: Container for permissions within an app namespace
  • Permission: Atomic actions validated as namespace.resource:action
  • RolePermission: N:M relationship between roles and permissions
  • AppRegistration: Application namespaces (Service Mode)
  • AppUser: Actor-to-app bindings with per-app status
  • ActorRole: Direct role assignments to actors (Channel 1)
  • AppData: Per-app key-value data storage
  • AuditLog: Audit trail for all operations
  • RefreshToken: SHA-256 hashed tokens with rotation
  • Group: Hierarchical groups forming a tree
  • GroupMember: Actor membership in groups
  • GroupRole: Role assignments to groups (Channel 2)

Value Objects

  • ActorType enum: HUMAN, APPLICATION
  • ActorStatus enum: ACTIVE, SUSPENDED, BLOCKED, INACTIVE, DELETED
  • AppStatus enum: ACTIVE, SUSPENDED
  • AppUserStatus enum: PENDING, ACTIVE, SUSPENDED, REMOVED
  • PermissionSlug: Immutable value object with validation (namespace.resource:action)

Public Interfaces

AuthQuery (Read-Only)

interface AuthQuery
{
    // Permission checks
    public function hasPermission(string $actorId, string $permissionSlug): bool;
    public function hasAnyPermission(string $actorId, array $permissionSlugs): bool;
    public function hasAllPermissions(string $actorId, array $permissionSlugs): bool;
    public function getAllPermissions(string $actorId): array;

    // Actor queries
    public function getActor(string $actorId): Actor;
    public function getActorByEmail(string $email): ?Actor;
    public function getActorDirectRoles(string $actorId): array;
    public function getActorEffectiveRoles(string $actorId): array;

    // App data
    public function getAppData(string $actorId, string $key): ?string;
    public function getAllAppData(string $actorId): array;

    // Validation
    public function validateCredentials(string $email, string $password): AuthResult;
    public function isActorActive(string $actorId): bool;

    // Groups
    public function getActorGroups(string $actorId): array;
    public function getGroupMembers(string $groupId): array;
    public function getGroupRoles(string $groupId): array;
    public function getGroupAncestors(string $groupId): array;
    public function getGroupDescendants(string $groupId): array;
}

AuthAdmin (Read + Write)

AuthAdmin extends AuthQuery and adds write operations:

interface AuthAdmin extends AuthQuery
{
    // Actors: create, update, delete, setStatus
    // Roles: create, update, delete, list, assignPermissions, revokePermissions
    // Permissions: register, registerMultiple, delete, list, listByGroup
    // AppUser: link, unlink, setStatus, assignRole, revokeRole
    // AppData: set, delete, clear
    // AppRegistration: register, suspend, delete, deleteGlobal
    // Groups: create, update, delete, setParent, addMember, removeMember, assignRole, revokeRole
}

Usage Examples

Example 1: Permission Check

use Gesmuni\Auth\Base\Contracts\Services\AuthQuery;

class PostController
{
    public function __construct(private AuthQuery $auth) {}

    public function edit(Post $post)
    {
        if (!$this->auth->hasPermission($userId, 'blog.post:edit')) {
            throw new PermissionDeniedException();
        }

        // Edit post...
    }
}

Example 2: Create Actor and Assign Role

use Gesmuni\Auth\Base\Contracts\Services\AuthAdmin;
use Gesmuni\Auth\Base\DTOs\Input\CreateActorInput;
use Gesmuni\Auth\Base\ValueObjects\ActorType;

class UserService
{
    public function __construct(private AuthAdmin $auth) {}

    public function createUser(string $email, string $name, string $password)
    {
        // Create actor
        $actor = $this->auth->createActor(new CreateActorInput(
            type: ActorType::HUMAN,
            email: $email,
            name: $name,
            password: $password,
        ));

        // Assign role
        $this->auth->assignRoleToActor($actor->id, null, $editorRoleId);

        return $actor;
    }
}

Example 3: Group-Based Permissions

// Create a group
$engineeringGroup = $auth->createGroup(new CreateGroupInput(
    name: 'Engineering',
    parentId: $everyoneGroupId,
));

// Add member
$auth->addMemberToGroup($userId, $engineeringGroup->id);

// Assign role to group (all members inherit)
$auth->assignRoleToGroup($engineeringGroup->id, null, $developerRoleId);

// Check permission (includes group roles)
$hasPermission = $auth->hasPermission($userId, 'code.repo:push');

Operating Modes

The interfaces are designed to work identically across three deployment modes:

Local Mode

The application imports the library directly. No network calls, null app_id.

Implementation package: gesmuni/laravel-auth-local

// In Local Mode
$authQuery->hasPermission($userId, 'content:edit');  // Resolves to "app.content:edit" implicitly

Client Mode

The application uses an HTTP wrapper that calls a remote auth service. Consumer code doesn't change.

Implementation package: gesmuni/laravel-auth-client

// In Client Mode (same code!)
$authQuery->hasPermission($userId, 'content:edit');  // HTTP call to remote service

Service Mode

The library is mounted behind an HTTP/gRPC API server. Multi-tenant with per-app namespaces.

Implementation package: gesmuni/laravel-auth-service

Domain Rules

Namespaces

  • Each application operates within its own namespace (e.g., crm, shop, blog)
  • The _auth namespace is reserved for system management
  • Permission slugs follow format: namespace.resource:action
  • In Local Mode, namespace is implicit (app.)

Groups

  • All groups form a single tree rooted at the system group everyone
  • everyone cannot have roles assigned (prevents unintended global grants)
  • Cycles are prevented: setGroupParent() validates the tree structure
  • Role inheritance: actors inherit roles from their groups AND all ancestor groups

Two-Channel Role Assignment

Effective permissions are the union of:

  1. Direct channel: ActorRole (direct actor-to-role assignments)
  2. Group channel: GroupRole (role assigned to actor's groups + ancestors)

System Protection

  • System roles (is_system = true) cannot be deleted
  • System groups (e.g., everyone) cannot be deleted or re-parented
  • everyone cannot have roles assigned

Actor Lifecycle

ACTIVE ⇄ SUSPENDED  (temporary, reversible)
ACTIVE → BLOCKED    (permanent, irreversible except to DELETED)
ACTIVE → INACTIVE   (auto-timeout, auto-reactivates on login)
Any → DELETED       (soft delete, retained for audit)

Exception Handling

All domain exceptions extend AuthException and include a context array:

try {
    $auth->deleteRole($roleId);
} catch (SystemRoleProtectedException $e) {
    // $e->context == ['role_id' => '...', 'role_name' => '...']
    Log::warning('Attempted to delete system role', $e->context);
}

Available exceptions:

  • ActorNotFoundException
  • PermissionDeniedException
  • InvalidNamespaceException
  • SystemRoleProtectedException
  • CyclicGroupReferenceException
  • SystemGroupProtectedException

Companion Packages

PackageDescription
gesmuni/laravel-auth-baseThis package - Core domain interfaces and entities
gesmuni/laravel-auth-local(Coming soon) Local Mode implementation with Eloquent, migrations, service provider
gesmuni/laravel-auth-client(Coming soon) Client Mode HTTP wrapper
gesmuni/laravel-auth-service(Coming soon) Service Mode API server

Development

Running Tests

composer test

Static Analysis

composer phpstan

Design Documentation

For the complete architectural specification, see auth-design-v1.md.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GNU Affero General Public License v3.0 or later - see the LICENSE file for details.

Credits

Part of the Gesmuni authentication and authorization ecosystem.