PHPackages                             tetthys/permissions - 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. tetthys/permissions

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

tetthys/permissions
===================

0.0.1(6mo ago)018PHPPHP ^8.2

Since Dec 29Pushed 6mo agoCompare

[ Source](https://github.com/tetthys/permissions)[ Packagist](https://packagist.org/packages/tetthys/permissions)[ RSS](/packages/tetthys-permissions/feed)WikiDiscussions dev Synced today

READMEChangelog (1)DependenciesVersions (2)Used By (0)

Tetthys Permissions
===================

[](#tetthys-permissions)

A lightweight, framework-agnostic **string-based permission engine** with **read-through / write-through caching**, designed for Laravel integration but usable without it.

Permissions are stored as **immutable snapshots (JSON arrays)** and identified by a flexible **Subject reference (type / id / optional scope)**.

---

Core Concepts
-------------

[](#core-concepts)

### 1. SubjectRef (Who owns permissions?)

[](#1-subjectref-who-owns-permissions)

Every permission set belongs to a **Subject**:

- `type` — logical category (e.g. `user`, `staff`, `role`)
- `id` — identifier (ULID, UUID, string)
- `scope` — optional context (e.g. organization, tenant)

```
[scope]:[type]:[id]

```

Examples:

- `user:01HV...`
- `staff:01HV...`
- `org:1:user:01HV...`

---

### 2. Permissions

[](#2-permissions)

Permissions are **plain strings**, representing domain actions:

```
staff.read
staff.update
orders.create
orders.refund

```

No table names, no columns, no booleans in business logic.

---

### 3. Pipeline (Read / Write Flow)

[](#3-pipeline-read--write-flow)

#### Read (read-through cache)

[](#read-read-through-cache)

```
get(subject)
 ├─ check cache
 │   └─ hit → return
 └─ miss
     ├─ load snapshot from store (DB / other)
     ├─ normalize
     ├─ write to cache
     └─ return PermissionSet

```

#### Write (write-through cache)

[](#write-write-through-cache)

```
put(subject, permissions)
 ├─ normalize
 ├─ persist snapshot to store
 ├─ update cache
 └─ emit PermissionChanged event

```

---

Installation (Laravel)
----------------------

[](#installation-laravel)

```
composer require tetthys/permissions
```

Publish configuration (optional):

```
php artisan vendor:publish --tag=tetthys-permissions-config
```

---

Database Setup
--------------

[](#database-setup)

Minimal snapshot table:

```
Schema::create('permission_snapshots', function (Blueprint $table) {
    $table->id();
    $table->string('subject_type');
    $table->string('subject_id');
    $table->json('permissions');

    // Optional scope (multi-tenant)
    // $table->string('org_id')->nullable();

    $table->unique(['subject_type', 'subject_id']);
});
```

---

Basic Usage
-----------

[](#basic-usage)

### Create a Subject

[](#create-a-subject)

```
use Tetthys\Permissions\Core\Value\SubjectRef;

$subject = new SubjectRef(
    type: 'user',
    id: (string) $user->id
);
```

---

### Store Permissions (Replace Snapshot)

[](#store-permissions-replace-snapshot)

```
use Permissions;

Permissions::put($subject, [
    'staff.read',
    'staff.update',
]);
```

---

### Read &amp; Check Permissions

[](#read--check-permissions)

```
$set = Permissions::get($subject);

if (! $set->has('staff.update')) {
    abort(403);
}
```

---

### Remove Permissions

[](#remove-permissions)

```
Permissions::forget($subject);
```

---

Using the Facade
----------------

[](#using-the-facade)

The Laravel Facade is automatically registered.

```
use Permissions;
use Tetthys\Permissions\Core\Value\SubjectRef;

Permissions::get($subject);
Permissions::put($subject, [...]);
Permissions::forget($subject);
```

---

Optional Subject Helper
-----------------------

[](#optional-subject-helper)

For convenience, you may use the helper:

```
use Tetthys\Permissions\Integration\Laravel\Support\Subject;

Permissions::put(
    Subject::user((string) $user->id),
    ['orders.read']
);
```

---

Events
------

[](#events)

Every write emits a domain event:

```
Tetthys\Permissions\Core\Event\PermissionChanged
```

Example listener:

```
Event::listen(PermissionChanged::class, function (PermissionChanged $event) {
    // $event->subjectStableId
    // $event->permissions
    // $event->occurredAtUnix
});
```

Use cases:

- Audit logging
- Session invalidation
- External sync

---

Configuration
-------------

[](#configuration)

`config/tetthys-permissions.php`

```
return [
    'ttl_seconds' => 300,
    'cache_prefix' => 'permissions:',

    'store' => [
        'table' => 'permission_snapshots',
        'subject_type_column' => 'subject_type',
        'subject_id_column' => 'subject_id',
        'permissions_column' => 'permissions',
        'scope_column' => null,
    ],
];
```

---

Design Goals
------------

[](#design-goals)

- Framework-agnostic core
- No boolean permission columns
- Immutable permission snapshots
- Cache-first reads
- Explicit, observable writes
- Easy migration from legacy `can_*` flags

---

Typical Migration Strategy
--------------------------

[](#typical-migration-strategy)

1. Read legacy flags (`can_*`)
2. Convert to permission strings
3. Store snapshot via `Permissions::put()`
4. Switch all checks to `PermissionSet::has()`
5. Remove legacy columns

---

License
-------

[](#license)

MIT

###  Health Score

30

—

LowBetter than 62% of packages

Maintenance68

Regular maintenance activity

Popularity6

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

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

Unknown

Total

1

Last Release

187d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/115064626?v=4)[tetthys](/maintainers/tetthys)[@tetthys](https://github.com/tetthys)

### Embed Badge

![Health badge](/badges/tetthys-permissions/health.svg)

```
[![Health](https://phpackages.com/badges/tetthys-permissions/health.svg)](https://phpackages.com/packages/tetthys-permissions)
```

###  Alternatives

[kartik-v/yii2-password

Useful password strength validation utilities for Yii Framework 2.0

761.3M17](/packages/kartik-v-yii2-password)[vitalybaev/laravel5-dkim

Laravel 5/6 package for signing outgoing messages with DKIM.

3163.1k](/packages/vitalybaev-laravel5-dkim)

PHPackages © 2026

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