P1-010: Rate limiting (60 req/min) on EntitlementApiController P1-011: API authentication documentation and middleware P1-014: SSRF protection for webhook endpoints (PreventsSSRF trait) P1-015: Workspace access validation in middleware (breaking change) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
16 KiB
core-tenant TODO
Comprehensive task list for improving the multi-tenancy package. Items are prioritised by impact and urgency.
Legend
- P1 - Critical/Security (must fix immediately)
- P2 - High (affects production quality)
- P3 - Medium (should address soon)
- P4 - Low (quality of life improvements)
- P5 - Nice-to-have (future enhancements)
- P6 - Backlog (ideas for later consideration)
P1 - Critical / Security
SEC-001: Add rate limiting to EntitlementApiController
Status: Fixed (2026-01-29)
File: Controllers/EntitlementApiController.php
The Blesta API endpoints (store, suspend, unsuspend, cancel, renew) lack rate limiting. A compromised API key could be used to mass-provision or cancel packages.
Resolution:
- Added
#[RateLimit(limit: 60, window: 60, key: 'entitlement-api')]attribute to controller class - Documented recommended route configuration with
api.rateandthrottle:60,1middleware - Rate limiting at 60 requests/minute per API key when routes are registered
SEC-002: Validate API authentication on EntitlementApiController routes
Status: Fixed (2026-01-29)
File: Routes/api.php, Controllers/EntitlementApiController.php
The Blesta API controller routes are not visible in api.php - they may be registered elsewhere or missing authentication. Verify all Blesta API endpoints require proper API key authentication.
Resolution:
- Added comprehensive PHPDoc to controller documenting required authentication
- Documented required middleware:
api.auth:entitlements.write,api.rate,throttle:60,1 - Routes are currently commented out in core-commerce/routes/api.php but controller is ready
- When enabled, routes require API key with
entitlements.writescope
SEC-003: Encrypt 2FA secrets at rest
Status: Fixed (Jan 2026, commit a35cbc9)
File: Concerns/TwoFactorAuthenticatable.php, Migrations/0001_01_01_000000_create_tenant_tables.php
The user_two_factor_auth.secret column stores TOTP secrets. While marked as text, these should be encrypted at rest using Laravel's encrypted:string cast.
Acceptance Criteria:
- Add
'secret_key' => 'encrypted'cast to UserTwoFactorAuth model - Create migration to encrypt existing secrets
- Verify decryption works correctly in TotpService
SEC-004: Audit workspace invitation token security
Status: Fixed (Jan 2026, commit a35cbc9)
File: Models/WorkspaceInvitation.php
Invitation tokens are 64-character random strings, which is good. However:
- Tokens should be hashed when stored (store hash, compare with hash_equals)
- Add brute-force protection for invitation acceptance endpoint
- Consider shorter expiry for high-privilege roles (owner/admin)
Acceptance Criteria:
- Store hashed tokens instead of plaintext
- Add rate limiting to invitation acceptance
- Add configurable expiry per role type
SEC-005: Add CSRF protection to webhook test endpoint
Status: Fixed (2026-01-29)
File: Controllers/Api/EntitlementWebhookController.php, Services/EntitlementWebhookService.php
The test endpoint triggers an outbound HTTP request. Ensure it cannot be abused as a server-side request forgery (SSRF) vector.
Resolution:
- Added
PreventsSSRFtrait toEntitlementWebhookService - Created
InvalidWebhookUrlExceptionfor SSRF validation failures - All webhook operations (register, update, test, retry) now validate URLs:
- Blocks localhost and loopback addresses (127.0.0.0/8, ::1)
- Blocks private networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Blocks link-local addresses and reserved ranges
- Blocks local domains (.local, .localhost, .internal)
- Requires HTTPS for all webhooks
- Validates DNS resolution to prevent rebinding attacks
- Added
SafeWebhookUrlvalidation rule to controller store/update - Added timeout (10s) and connect timeout (5s) limits
SEC-006: Validate workspace_id in RequireWorkspaceContext middleware
Status: Fixed (2026-01-29)
File: Middleware/RequireWorkspaceContext.php
The middleware accepts workspace_id from multiple sources (header, query, input) without validating the authenticated user's access in all code paths.
Resolution:
- Changed default behaviour to ALWAYS validate user access (breaking change)
- Added
isValidWorkspaceId()check to validate workspace ID is positive integer - Added
logWorkspaceAccessAttempt()for security monitoring - Logs denied/invalid attempts at warning level, granted at debug level (debug mode only)
- To skip validation (NOT RECOMMENDED), pass
skip_validationparameter - Logs include: workspace_id, user_id, IP, user agent, URL, source of workspace context
P2 - High Priority
DX-001: Add strict_types declaration to all PHP files
Status: Open Files: Multiple files missing declaration
Several files are missing declare(strict_types=1);:
Models/Workspace.phpModels/User.phpServices/EntitlementService.php
Acceptance Criteria:
- Add strict_types to all PHP files
- Run tests to verify no type coercion issues
DX-002: Document EntitlementService public API
Status: Open
File: Services/EntitlementService.php
The EntitlementService is the core API for entitlement checks but lacks comprehensive PHPDoc. External consumers need clear documentation.
Acceptance Criteria:
- Add complete PHPDoc to all public methods
- Document exception conditions
- Add @throws annotations where applicable
- Create usage examples in documentation
TEST-001: Add tests for namespace-level entitlements
Status: Open
File: tests/Feature/EntitlementServiceTest.php
The test file covers workspace-level entitlements but not namespace-level (canForNamespace, recordNamespaceUsage, etc.).
Acceptance Criteria:
- Test
canForNamespace()with various ownership scenarios - Test entitlement cascade (namespace -> workspace -> user tier)
- Test
provisionNamespacePackage()andprovisionNamespaceBoost() - Test namespace cache invalidation
TEST-002: Add integration tests for EntitlementApiController
Status: Open
File: tests/Feature/EntitlementApiTest.php
Need HTTP-level integration tests for the API endpoints, including authentication, validation, and error cases.
Acceptance Criteria:
- Test all CRUD operations via HTTP
- Test validation error responses
- Test authentication failures
- Test rate limiting (once implemented)
PERF-001: Optimise EntitlementService cache invalidation
Status: Open
File: Services/EntitlementService.php
The invalidateCache() method iterates all features and clears each key individually. This is O(n) where n = feature count.
Acceptance Criteria:
- Use cache tags when available (Redis)
- Implement version-based cache busting
- Benchmark before/after with 100+ features
PERF-002: Add database indexes for common queries
Status: Open
File: Migrations/0001_01_01_000000_create_tenant_tables.php
Missing indexes identified:
users.tier(for tier-based queries)namespaces.slug(currently only unique in combination)entitlement_usage_records.user_id
Acceptance Criteria:
- Create migration adding missing indexes
- Verify query plan improvements with EXPLAIN
CODE-001: Extract WorkspaceScope to separate file
Status: Open
File: Scopes/WorkspaceScope.php
The WorkspaceScope class exists but is referenced in BelongsToWorkspace trait without actually being applied as a global scope. Clarify the architecture.
Acceptance Criteria:
- Document when WorkspaceScope vs BelongsToWorkspace should be used
- Consider applying WorkspaceScope as a proper global scope
- Update CLAUDE.md with guidance
CODE-002: Consolidate User model relationships
Status: Open
File: Models/User.php
The User model has many undefined relationships (Page, Project, Domain, Pixel, etc.) that reference classes not in this package. These should either be:
- Moved to the consuming application
- Made conditional on class existence
Acceptance Criteria:
- Audit all relationships for undefined classes
- Add
class_exists()guards or move to app layer - Document which relationships are package-native vs app-specific
CODE-003: Remove hardcoded domain in EntitlementApiController
Status: Open
File: Controllers/EntitlementApiController.php, Line 80
The workspace creation uses hardcoded domain 'hub.host.uk.com'. This should be configurable.
Acceptance Criteria:
- Move to config value
- Add sensible default
- Document in CLAUDE.md
P3 - Medium Priority
DX-003: Add return type hints to all Workspace relationships
Status: Open
File: Models/Workspace.php
Many relationship methods have correct docblocks but inconsistent return types. Standardise for IDE support.
Acceptance Criteria:
- Add explicit return types to all relationship methods
- Verify PHPStan/Larastan passes at level 6+
DX-004: Create EntitlementException subtypes
Status: Open
File: Exceptions/EntitlementException.php
Currently there's a single EntitlementException. Consider subtypes:
LimitExceededExceptionPackageNotFoundExceptionFeatureNotFoundException
Acceptance Criteria:
- Create exception hierarchy
- Update EntitlementService to throw specific exceptions
- Update documentation with exception types
TEST-003: Add tests for WorkspaceTeamService
Status: Open
File: Services/WorkspaceTeamService.php
No dedicated test file for WorkspaceTeamService. The service handles team CRUD, permissions, and member management.
Acceptance Criteria:
- Test team creation/update/deletion
- Test permission checks (hasPermission, hasAnyPermission, hasAllPermissions)
- Test member assignment to teams
- Test default team seeding
- Test member migration from roles to teams
TEST-004: Add tests for EntitlementWebhookService
Status: Open
File: Services/EntitlementWebhookService.php
Need tests for webhook dispatch, signature verification, and circuit breaker functionality.
Acceptance Criteria:
- Test webhook registration
- Test event dispatch (sync and async)
- Test signature signing and verification
- Test circuit breaker trigger and reset
- Test delivery retry logic
TEST-005: Add edge case tests for TotpService
Status: Open
File: Services/TotpService.php
Current tests may not cover:
- Clock drift (WINDOW parameter)
- Invalid base32 input
- Empty/null code handling
Acceptance Criteria:
- Test verification with clock drift
- Test malformed secret handling
- Test edge cases in base32 encode/decode
PERF-003: Lazy-load Workspace relationships
Status: Open
File: Models/Workspace.php
The Workspace model has 30+ relationships. Many are to external packages (Core\Mod\Social, etc.). Consider:
- Marking heavy relationships as lazy
- Using
withCountinstead of loading full relations for counts
Acceptance Criteria:
- Audit which relationships are commonly N+1 issues
- Add
$withproperty sparingly - Document recommended eager loading patterns
CODE-004: Standardise error responses across API controllers
Status: Open
Files: Controllers/EntitlementApiController.php, Controllers/Api/EntitlementWebhookController.php
Error response formats vary. Standardise to consistent structure:
{
"success": false,
"error": "Error message",
"code": "ERROR_CODE"
}
Acceptance Criteria:
- Create API response trait or service
- Apply to all API controllers
- Document response format
CODE-005: Add validation for webhook URL in registration
Status: Open
File: Services/EntitlementWebhookService.php
The register() method doesn't validate the webhook URL format or accessibility.
Acceptance Criteria:
- Validate URL format (must be https in production)
- Optionally verify URL is reachable
- Block internal IP ranges
FEAT-001: Add soft deletes to WorkspaceInvitation
Status: Open
File: Models/WorkspaceInvitation.php
Invitations are currently hard-deleted. Soft deletes would preserve audit trail.
Acceptance Criteria:
- Add SoftDeletes trait
- Update delete operations
- Add migration for deleted_at column
FEAT-002: Add invitation resend functionality
Status: Open
File: Models/WorkspaceInvitation.php
Users may miss invitation emails. Add ability to resend with updated expiry.
Acceptance Criteria:
- Add
resend()method to WorkspaceInvitation - Extend expiry on resend
- Track resend count/timestamps
- Rate limit resends
P4 - Low Priority
DX-005: Add IDE helper annotations
Status: Open
Add @mixin and @method annotations for better IDE autocomplete with Eloquent.
Acceptance Criteria:
- Add annotations to all models
- Document pattern for future models
DX-006: Create artisan command for provisioning packages
Status: Open
Manual package provisioning via tinker is error-prone. Add CLI command.
Acceptance Criteria:
php artisan tenant:provision-package {workspace} {package}- Add interactive mode
- Support dry-run option
TEST-006: Add mutation testing
Status: Open
Run infection/mutation testing to verify test quality.
Acceptance Criteria:
- Add infection to dev dependencies
- Configure for core services
- Achieve >80% mutation score on critical code
CODE-006: Extract constants from WorkspaceMember
Status: Open
File: Models/WorkspaceMember.php
Role constants should be in an enum for type safety.
Acceptance Criteria:
- Create WorkspaceMemberRole enum
- Update model to use enum
- Update all role comparisons
CODE-007: Add configurable invitation expiry
Status: Open
File: Models/Workspace.php, Line 654
The invite() method has hardcoded 7-day expiry. Make configurable.
Acceptance Criteria:
- Add config key
tenant.invitation_expiry_days - Document configuration option
FEAT-003: Add workspace transfer ownership
Status: Open
Allow workspace owners to transfer ownership to another member.
Acceptance Criteria:
- Add
transferOwnership()method to WorkspaceManager - Require confirmation from new owner
- Log ownership transfer in audit log
FEAT-004: Add bulk invitation support
Status: Open
Allow inviting multiple users at once (CSV upload or multi-email input).
Acceptance Criteria:
- Add
inviteMany()method - Support CSV email import
- Handle duplicates gracefully
P5 - Nice to Have
DX-007: Add OpenAPI/Swagger documentation
Status: Open
Generate API documentation from route definitions.
Acceptance Criteria:
- Add scramble or l5-swagger
- Document all API endpoints
- Include authentication requirements
FEAT-005: Add workspace activity log
Status: Open
Track all significant workspace actions for audit purposes.
Acceptance Criteria:
- Log member additions/removals
- Log permission changes
- Log package/boost changes
- Provide query interface
FEAT-006: Add usage forecasting
Status: Open
Predict when a workspace will hit limits based on usage trends.
Acceptance Criteria:
- Track daily usage aggregates
- Implement simple linear projection
- Show "estimated days until limit" in dashboard
FEAT-007: Add webhook event filtering
Status: Open
Allow webhooks to filter events by additional criteria (e.g., specific features only).
Acceptance Criteria:
- Add filter configuration to webhook
- Support feature code patterns
- Support threshold filtering for limit events
P6 - Backlog / Ideas
IDEA-001: GraphQL API for entitlements
Consider adding GraphQL endpoint for more flexible entitlement queries.
IDEA-002: Real-time usage updates
WebSocket support for live usage updates in dashboard.
IDEA-003: Entitlement simulation mode
Allow testing "what if I upgrade" scenarios without actual changes.
IDEA-004: Multi-region support
Support for workspace data residency requirements.
IDEA-005: Workspace templates
Pre-configured workspace setups for different use cases.
Completed
Move items here when done with completion date.