Addresses #42 — race condition in EntitlementService usage recording.
Changes:
1. New atomic check-and-record methods:
- checkAndRecordUsage() — workspace-scoped
- checkAndRecordNamespaceUsage() — namespace-scoped
These use DB::transaction() with lockForUpdate() on usage records
to prevent concurrent requests from reading the same count and
both passing the limit check (TOCTOU race).
2. New locked usage query methods:
- getLockedCurrentUsage() — bypasses cache, uses SELECT FOR UPDATE
- getLockedNamespaceCurrentUsage() — namespace equivalent
These are used within the atomic transactions to get a consistent
usage count under pessimistic locking.
3. provisionPackage() and provisionNamespacePackage():
Wrapped base-package check-and-cancel in DB::transaction() with
lockForUpdate() to prevent duplicate active base packages from
concurrent provisioning requests.
4. provisionBoost():
Wrapped in DB::transaction() with lockForUpdate() on existing
boosts. Added duplicate detection for blesta_addon_id to prevent
the same external addon from being provisioned twice.
5. provisionNamespaceBoost():
Wrapped in DB::transaction() with lockForUpdate() on existing
namespace boosts to serialise concurrent provisioning.
The existing can() + recordUsage() pattern is preserved for backward
compatibility. Callers should migrate to checkAndRecordUsage() for
race-safe usage tracking.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add phpunit.xml and tests/Pest.php for standalone test execution.
Apply Laravel Pint formatting fixes across all source files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Document provisionNamespacePackage with examples
- Document provisionNamespaceBoost with boost/duration types
- Document invalidateNamespaceCache with auto-invalidation triggers
- Add cross-references to workspace-level equivalents
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add declare(strict_types=1) to Workspace.php
- Add declare(strict_types=1) to User.php
- Add declare(strict_types=1) to EntitlementService.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Simplifies the namespace hierarchy by removing the intermediate Mod
segment. Updates all 118 files including models, services, controllers,
middleware, tests, and composer.json autoload configuration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>