mohamedhekal/tenantforge

Shared-database multi-tenancy foundation for Laravel SaaS: tenants, domains, memberships, API keys, and isolation scopes

Maintainers

Package info

github.com/mohamedhekal/tenantforge

pkg:composer/mohamedhekal/tenantforge

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-16 14:23 UTC

This package is auto-updated.

Last update: 2026-07-16 14:35:24 UTC


README

CI License: MIT PHP Laravel

Search terms: laravel, multitenancy, saas, tenants, api-keys, teams, php, laravel-package, multi-tenant, b2b-saas, isolation.

Shared-database multi-tenancy foundation for Laravel SaaS: tenants, domains, memberships, hashed API keys, plan stubs, and audited impersonation.

This is plumbing—not a finished product. Use it to start a B2B app without reinventing isolation basics.

Installation

composer require mohamedhekal/tenantforge
php artisan vendor:publish --tag=tenantforge-config
php artisan migrate

Provision a tenant

use Hekal\TenantForge\Facades\TenantForge;

$tenant = TenantForge::provision(
    name: 'Acme',
    ownerUserId: $user->id,
    slug: 'acme',
    domain: 'acme.app.test',
    planSlug: 'pro',
);

Scope models

use Hekal\TenantForge\Concerns\BelongsToTenant;

class Project extends Model
{
    use BelongsToTenant;
}

Initialize tenancy (middleware or manually):

Route::middleware('tenantforge.init')->group(...);
// identification: header X-Tenant | domain | subdomain (config)

API keys

['plain' => $plain, 'key' => $key] = TenantForge::apiKeys()->create($tenant, 'CI');
// store $plain once; only the hash is persisted

Middleware alias: tenantforge.api (X-Api-Key).

Entitlements (stubs)

Plans store a features list/map. TenantForge::allows('webhooks') checks the tenant’s active subscription.

Wire FlagDeck later for richer targeting; v0.1 keeps plans local and explicit.

Impersonation

$log = TenantForge::impersonation()->start($tenant, $adminId, $userId, reason: 'ticket #12');
TenantForge::impersonation()->stop($log);

Limitations (v0.1)

  • Shared DB only (no DB-per-tenant driver yet)
  • No Stripe/Paddle billing
  • No Vue portal or Filament admin bundled
  • Without tenant context, BelongsToTenant does not filter (intentional for migrations/CLI)—always initialize in HTTP/jobs

Testing

composer install && composer test

Isolation tests live under tests/Feature/TenancyTest.php.

License

MIT