Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions .github/workflows/claude-code-review.yml

This file was deleted.

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Organization Based (OrBAC) , Attibute Based (ABAC) , Rol-Permission (RBAC) Base
- Built-in Blade Directives for permission control inside **Blade** files
- Mysql, MariaDB, Postgres Support
- Built-in Caching Layer with Configurable TTL
- **Laravel Octane / Vapor safe** — `aauth` is a request-scoped binding; no cross-request state leak
- Community Driven and Open Source Forever

---
Expand Down Expand Up @@ -65,6 +66,12 @@ Optionally, You can seed the sample data with:
php artisan db:seed --class=SampleDataSeeder
```

## Laravel Octane / Vapor

AAuth resolves the `aauth` service as a **request-scoped** binding (`$app->scoped()`). Under Octane and Vapor the resolved instance is flushed at every `RequestTerminated` event, so the active user, role, organization node IDs, permissions and ABAC rules cannot leak across requests sharing the same long-lived worker. No `config/octane.php` flush entry is needed.

Under classic PHP-FPM behaviour is unchanged.

You can publish the config file with:

```bash
Expand Down
56 changes: 56 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,61 @@
# Upgrade Guide

## Upgrading to 21.1.0 (security + reliability minor)

This release is fully backward compatible — `composer update` from any 21.x will not break a working host application. No migration, no config change, no signature change.

### What changed

**1. AAuth container binding is now request-scoped (security fix, HIGH severity)**

The `aauth` binding in `AAuthServiceProvider` was a `singleton` and now uses `scoped()`. Under classic PHP-FPM each request is a fresh process, so this is a no-op (same number of constructor calls per request, same DB queries, same observable behaviour).

Under **Laravel Octane / Vapor** the change closes an authorization-bypass vector: the resolved `AAuth` instance no longer survives the request boundary, so User A's role / organization node IDs / permissions / ABAC rules / super-admin flag cannot leak into User B's request on the same worker.

- **Action required for PHP-FPM consumers:** none.
- **Action required for Octane / Vapor consumers:** none. If you previously worked around this with `config/octane.php`'s `'flush' => ['aauth']` entry, you can remove it (it's harmless if you leave it).

**2. Recursive organization-node service methods now propagate exceptions**

`OrganizationService::updateNodePathsRecursively()` and `deleteOrganizationNodesRecursively()` previously wrapped their body in a `try/catch` that silently swallowed exceptions while still committing the outer transaction. The new implementation wraps the recursion in `DB::transaction()` so any failure rolls back the entire subtree and re-throws the original exception.

- The public method signatures (`OrganizationNode $node, ?bool $withDBTransaction = true`) are unchanged.
- The only observable behavioural difference: errors that were previously silent now surface to the caller. If you relied on the silent-failure behaviour, wrap the call in your own `try/catch`.

**3. New aligned-order `detachOrganizationRoleFromUserBy()` method**

`RolePermissionService::detachOrganizationRoleFromUser()` historically takes parameters in the inverse order from `attachOrganizationRoleToUser()`. We did not change the existing method's parameter order — that would silently corrupt data for every consumer. Instead we added:

```php
$service->detachOrganizationRoleFromUserBy(
$organizationNodeId,
$roleId,
$userId,
); // matches attachOrganizationRoleToUser order
```

The existing `detachOrganizationRoleFromUser($userId, $roleId, $organizationNodeId)` keeps working and emits no runtime notice. It is marked `@deprecated` in its docblock so IDEs and PHPStan flag call sites for migration. It will be removed in the next major release.

- **Migration recipe:**
```bash
# Find call sites
grep -rn 'detachOrganizationRoleFromUser(' app/ packages/
```
Replace `detachOrganizationRoleFromUser($u, $r, $n)` with `detachOrganizationRoleFromUserBy($n, $r, $u)`.

### Verifying the upgrade

After `composer update`:

```bash
vendor/bin/pest # your own test suite should still pass
vendor/bin/phpstan # may surface @deprecated notices for the legacy detach method — informational only
```

---

## Upgrading from v1 to v2

This guide covers upgrading from AAuth v1 to v2.

## Requirements
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-22
Loading