multi-tenant-patterns

Enforce Eloquent global scoping with business_id to isolate multi-tenant ERP data.

Updated May 14, 2024
One-click install
npx skills add https://github.com/wagnerra23/oimpresso.com --skill multi-tenant-patterns-wagnerra23
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: multi-tenant-patterns
Source: https://github.com/wagnerra23/oimpresso.com/tree/main/.claude/skills/multi-tenant-patterns
Command: npx skills add https://github.com/wagnerra23/oimpresso.com --skill multi-tenant-patterns-wagnerra23

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

This Skill prevents cross-tenant data leaks by standardizing how every business-scoped database access is filtered, especially across controllers, background jobs, and console commands.

Core Features & Use Cases

  • Global tenant isolation with business_id: Applies a single canonical global scope in Eloquent so controllers do not manually filter and accidentally bypass tenant rules.
  • Correct handling of background execution: Ensures queued Jobs and Artisan Commands do not rely on session() and instead receive business_id explicitly when cross-tenant isolation is required.
  • Deliberate cross-business access: Provides a safe pattern for using withoutGlobalScope with mandatory rationale, covering superadmin/platform-wide (business_id = null) behavior and SQL edge cases.

Quick Start

Apply the multi-tenant patterns when modifying any model, controller, job, command, or migration that touches tables containing business_id, and then run isolation tests to verify tenant A never sees tenant B data.

Frequently Asked Questions about multi-tenant-patterns

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I prevent cross-tenant data leaks in a multi-tenant Laravel ERP?

Prevent cross-tenant data leaks by applying a canonical Eloquent global scope that automatically filters all models using a business_id column, ensuring controllers never manually bypass tenant isolation rules.

Why does multi-tenant data isolation break in queued jobs and Artisan commands?

Multi-tenant data isolation breaks because background execution lacks HTTP session context, requiring you to pass business_id explicitly to queued jobs and Artisan commands instead of relying on session data.

How do I safely access cross-tenant data using Eloquent global scopes?

Safely access cross-tenant data by using the withoutGlobalScope method with deliberate justification, accommodating superadmin or platform-wide behavior where business_id is null alongside SQL edge cases.

What's the best way to test multi-tenant data isolation in PHPunit?

Test multi-tenant data isolation by running mandatory cross-tenant test coverage that verifies tenant A never sees tenant B data across controllers, queued jobs, and CLI execution paths.

Do I need an explicit business_id on every model for multi-tenant ERP isolation?

Yes, you need business_id on database tables to enforce multi-tenant ERP isolation, applying the ScopeByBusiness pattern to models, migrations, observers, and services that touch business data.

When should I not use Eloquent global scoping for multi-tenant data access?

Avoid Eloquent global scoping for multi-tenant data access only when deliberate cross-business access is required, using withoutGlobalScope with explicit rationale rather than bypassing tenant rules accidentally.