equidna / bee-hive
Reusable multi-tenant foundation for Laravel applications.
Requires
- php: ^8.2
- illuminate/database: ^12.0
- illuminate/http: ^12.0
- illuminate/support: ^12.0
Requires (Dev)
- orchestra/testbench: ^10.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
- squizlabs/php_codesniffer: ^3.11
README
Reusable multi-tenant foundation package for Laravel projects.
What It Includes
- Tenant resolver contract
- Tenant context container
- Eloquent global scope for tenant filtering
- BelongsToTenant trait with automatic tenant key fill
- Service provider with publishable config
Architecture
flowchart LR
A[Laravel Container] --> B[BeeHiveServiceProvider]
B --> C[TenantResolverInterface]
C --> D[Configured Resolver]
D --> E[TenantContext]
E --> F[TenantScope]
E --> G[BelongsToTenant Trait]
F --> H[Query Filtering by tenant key]
G --> I[Auto-fill tenant key on create]
F --> J{Tenant ID resolved?}
J -->|Yes| H
J -->|No| L[BeeHiveException]
L --> M[RFC 7807 Problem Details Response]
Loading
Flow summary:
- The service provider binds the configured tenant resolver and initializes
TenantContext. TenantScopereads the tenant from context to enforce query-level isolation.BelongsToTenantuses the same context to auto-assign tenant key values on model creation.- Missing tenant resolution always throws
BeeHiveExceptionwith an RFC 7807problem_detailsJSON response.
Error Response
When tenant resolution fails, BeeHiveException returns an RFC 7807 problem_details JSON response:
{
"type": "urn:beehive:error:tenant_not_resolved",
"title": "BeeHive Exception",
"status": 422,
"detail": "BeeHive tenant was not resolved.",
"code": "tenant_not_resolved"
}
Config keys (in config/bee-hive.php):
errors.status: HTTP status code for tenant resolution errors (default:422)logging.enabled: enable package log emission (default:true)logging.level: package log level (warningby default)logging.sample_rate: sampling ratio between0and1(default:1.0)
Environment variables:
BEE_HIVE_ERROR_STATUSBEE_HIVE_LOGGING_ENABLEDBEE_HIVE_LOG_LEVELBEE_HIVE_LOG_SAMPLE_RATE
Quality Checks
Run repository quality checks locally:
composer validate --no-check-publishcomposer audit --no-interaction./vendor/bin/phpcs --standard=ruleset.xml src config tests./vendor/bin/phpstan analyse --memory-limit=512M./vendor/bin/phpunit
CI additionally runs workflow linting (actionlint) to prevent invalid GitHub workflow syntax from reaching main.
Or run the aggregated command:
composer qacomposer qa:fastfor validate + lint + tests without audit/static analysis
Security Behavior
- Tenant-scoped reads and writes require a resolved tenant.
- Missing tenant resolution throws
BeeHiveException. - Model creation always applies the resolved tenant value, even if a different tenant value is provided in input.
Observability
BeeHive logs warning events when:
- A tenant-scoped query runs without a resolved tenant.
- A tenant-scoped model is created without a resolved tenant.
- A model create payload includes a tenant value different from the resolved context.
Each event includes a stable event_code field for alerting and dashboard rules.
Sampling behavior (logging.sample_rate) is tested deterministically in the test suite to avoid flaky observability checks.
The emitted package level still passes through the global Laravel logging configuration (channels, handlers, and minimum levels).
Event Catalog
| event_code | Trigger | Suggested severity | Context fields |
|---|---|---|---|
BEEHIVE_TENANT_UNRESOLVED_QUERY |
A tenant-scoped query runs without a resolved tenant | warning | model, tenant_key, resolver |
BEEHIVE_TENANT_UNRESOLVED_CREATE |
A tenant-scoped model create operation runs without a resolved tenant | warning | model, tenant_key |
BEEHIVE_TENANT_SPOOF_ATTEMPT |
Input tenant differs from resolved tenant during create | warning | model, tenant_key, incoming_tenant_id, resolved_tenant_id |
Suggested alerting thresholds:
- Alert immediately on any sustained
BEEHIVE_TENANT_UNRESOLVED_QUERYvolume in production. - Investigate any
BEEHIVE_TENANT_SPOOF_ATTEMPTevent as potentially malicious client behavior.