Commit graph

7 commits

Author SHA1 Message Date
Claude
ef7ed4ca77
fix: atomic usage recording and provisioning to prevent race conditions
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>
2026-03-24 13:09:49 +00:00
Claude
97889d04cc
chore: fix pint code style and add test config
Some checks failed
CI / tests (push) Failing after 1m24s
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>
2026-02-23 03:50:04 +00:00
Snider
adad6a1f47 perf(entitlements): optimise cache invalidation with tags (P2-023)
Add O(1) cache invalidation using cache tags for Redis/Memcached,
replacing O(n) feature iteration. Key improvements:

- Cache tags for workspace/namespace scoping (entitlement:ws:{id})
- Granular invalidation: invalidateUsageCache(), invalidateLimitCache()
- Event-driven cache management via EntitlementCacheInvalidated event
- Fallback to O(n) for non-taggable stores (file, database)
- recordUsage() now invalidates only the affected feature's cache

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:44:50 +00:00
Snider
5197094bd6 docs: add comprehensive PHPDoc to EntitlementService (P2-020)
- 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>
2026-01-29 15:39:21 +00:00
Snider
501ea1897e chore: add strict types to core files (P2-019)
- 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>
2026-01-29 15:16:10 +00:00
Snider
d0ad2737cb refactor: rename namespace from Core\Mod\Tenant to Core\Tenant
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>
2026-01-27 16:30:46 +00:00
Snider
86dbf4e763 fix: namespace to Core\Mod\Tenant, restructure package
- Changed namespace from Core\Core\Tenant to Core\Mod\Tenant
- Moved src/ contents to root
- Removed Host UK extension files (admin.php, MemberManager, TeamManager)
- Fixed composer.json autoload paths
2026-01-27 00:58:42 +00:00
Renamed from src/Services/EntitlementService.php (Browse further)