quantum-php / quantum-php/framework

Introduce First-Party Authorization Library with Adapter-Based RBAC Support

Open
#388 0 comments 0 reactions 1 assignee View on GitHub

@charoyan88 is already working on this.

Since Jan 15, 2026.

help wanted new feature
Dominant language
PHP
Stars
36
Forks
22
PR merge metrics
No merged PRs in 30d

Description

Summary

Quantum Framework currently provides a robust first-party Auth library (session & JWT) that fully covers authentication concerns.
However, there is no first-party solution for authorization (permissions / access control).

This leads to:

  • role checks scattered across controllers, services, and middlewares
  • inconsistent authorization patterns across projects
  • tight coupling between business logic and authentication details

This ticket proposes introducing a first-party Authorization library, designed in full alignment with QF architecture and philosophy:

  • adapter-based (no runtime branching)
  • explicit and class-driven
  • backward compatible
  • service-first
  • middleware-safe

Goals

  • Introduce a dedicated Authorization library (Quantum\Libraries\Authorization)
  • Keep Auth and Authorization strictly separated
  • Use permissions as the primary authorization primitive
  • Support RBAC as the initial authorization model
  • Allow multiple permission sources via adapters (config-based, DB-based)
  • Preserve Laravel-like DX (user()->can()) via delegation
  • Integrate cleanly with QF middlewares (no parameters)
  • Provide a safe migration path from users.role → full RBAC tables

Non-Goals (v1)

  • No ABAC / policies
  • No route DSL or parameterized middleware
  • No UI or admin tooling
  • No breaking changes to Auth
  • No removal of users.role

Core Principles (QF-Aligned)

  1. Auth answers “who are you?”
  2. Authorization answers “what can you do?”
  3. Services enforce authorization
  4. Middlewares are coarse-grained gates
  5. Adapters decide behavior — methods never branch
  6. Explicit classes over magic strings

Proposed Structure

Quantum/Libraries/Authorization/
 ├── AuthorizationService.php
 ├── AuthorizationFactory.php
 ├── Authorization.php
 ├── Contracts/
 │    └── PermissionResolverInterface.php
 ├── Adapters/
 │    ├── ConfigPermissionAdapter.php
 │    └── DatabasePermissionAdapter.php
 └── Exceptions/
      └── AuthorizationException.php

Core API

AuthorizationService
$authorization->can(User $user, string $permission, mixed $context = null): bool;
$authorization->authorize(User $user, string $permission, mixed $context = null): void;

User Convenience (DX Only)

$user->can('post.publish');
$user->authorize('post.publish');

Important:

  • User does not implement authorization logic
  • User only delegates to AuthorizationService

Adapter-Based Authorization (No Runtime Branching)

interface PermissionResolverInterface
{
    public function can(User $user, string $permission, mixed $context = null): bool;
}

Middleware Integration (IMPORTANT)

Constraint

QtMiddleware::apply() does NOT accept parameters.

Correct Pattern

Each authorization middleware represents a named permission gate.

abstract class PermissionMiddleware extends QtMiddleware
{
    public function apply(Request $request, Response $response, Closure $next)
    {
        $user = auth()->user();

        if (!$user || !$user->can('post.publish')) {
            return $response->setStatus(403);
        }

       return $next($request, $response);
    }
}

Migration Path Summary

  1. Config RBAC + users.role
  2. Introduce RBAC tables
  3. Sync config → DB
  4. Switch adapter
  5. Backfill user_roles
  6. Deprecate users.role

Acceptance Criteria

  • Authorization is a first-party library
  • Adapter-based resolution via factory
  • No runtime branching based on config
  • Middleware respects QtMiddleware constraints
  • Service-level authorization enforced
  • Backward compatibility preserved

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.