No description
Add a SHA-256 token_hash lookup column to workspace_invitations so that findByToken and findPendingByToken can locate the candidate row with a single indexed SQL query instead of loading up to 1000 rows and running bcrypt against each one sequentially. The bcrypt hash in the token column is still verified after the O(1) lookup, preserving the existing security guarantee while eliminating both the timing side-channel and the performance bottleneck. Changes: - Migration to add nullable indexed token_hash column - Model booted() creating/updating events compute SHA-256 alongside bcrypt - findByToken/findPendingByToken rewritten to WHERE token_hash then Hash::check - HashInvitationTokens command updated to populate token_hash for existing rows Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| .gemini | ||
| .github | ||
| changelog/2026 | ||
| Concerns | ||
| Console/Commands | ||
| Contracts | ||
| Controllers | ||
| Database | ||
| docs | ||
| Enums | ||
| Events | ||
| Exceptions | ||
| Features | ||
| Jobs | ||
| Lang/en_GB | ||
| Listeners | ||
| Middleware | ||
| Migrations | ||
| Models | ||
| Notifications | ||
| Routes | ||
| Rules | ||
| Scopes | ||
| Services | ||
| tests | ||
| View | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| Boot.php | ||
| CLAUDE.md | ||
| cliff.toml | ||
| composer.json | ||
| FINDINGS.md | ||
| GEMINI.md | ||
| LICENSE | ||
| phpunit.xml | ||
| README.md | ||
| TODO.md | ||
Core Tenant
Multi-tenancy module for the Core PHP Framework providing users, workspaces, and entitlements.
Features
- Users & Authentication - User management with 2FA support
- Workspaces - Multi-tenant workspace boundaries
- Entitlements - Feature access, packages, and usage tracking
- Account Management - User settings, account deletion
- Referrals - Referral system support
- Usage Alerts - Configurable usage threshold alerts
Requirements
- PHP 8.2+
- Laravel 11.x or 12.x
- Core PHP Framework (
lthn/php)
Installation
composer require lthn/php-tenant
The service provider will be auto-discovered.
Run migrations:
php artisan migrate
Usage
Workspace Management
use Core\Mod\Tenant\Services\WorkspaceManager;
use Core\Mod\Tenant\Services\WorkspaceService;
// Get current workspace
$workspace = app(WorkspaceManager::class)->current();
// Create a new workspace
$workspace = app(WorkspaceService::class)->create([
'name' => 'My Workspace',
'owner_id' => $user->id,
]);
Entitlements
use Core\Mod\Tenant\Services\EntitlementService;
$entitlements = app(EntitlementService::class);
// Check if workspace has access to a feature
if ($entitlements->hasAccess($workspace, 'premium_feature')) {
// Feature is enabled
}
// Check usage limits
$usage = $entitlements->getUsage($workspace, 'api_calls');
Middleware
The module provides middleware for workspace-based access control:
// In your routes
Route::middleware('workspace.permission:manage-users')->group(function () {
// Routes requiring manage-users permission
});
Models
| Model | Description |
|---|---|
User |
Application users |
Workspace |
Tenant workspace boundaries |
WorkspaceMember |
Workspace membership with roles |
Entitlement |
Feature/package entitlements |
UsageRecord |
Usage tracking records |
Referral |
Referral tracking |
Events
The module fires events for key actions:
WorkspaceCreatedWorkspaceMemberAddedWorkspaceMemberRemovedEntitlementChangedUsageAlertTriggered
Artisan Commands
# Refresh user statistics
php artisan tenant:refresh-user-stats
# Process scheduled account deletions
php artisan tenant:process-deletions
# Check usage alerts
php artisan tenant:check-usage-alerts
# Reset billing cycles
php artisan tenant:reset-billing-cycles
Configuration
The module uses the Core PHP configuration system. Key settings can be configured per-workspace or system-wide.
Documentation
License
EUPL-1.2 (European Union Public Licence)