Release v0.1.13 — Phase 13: Feature Access Service#182
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CONV-183: Test free plan feature access CONV-184: Implement free plan feature access CONV-185: Test pro and max feature access CONV-186: Implement pro and max feature access Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CONV-189: Enforce max file size limit in upload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CONV-191: Implement StorageUsageService Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CONV-193: Enforce storage limit in upload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CONV-195: Apply retention days to files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR implements plan-based feature access and storage quota enforcement. It introduces ChangesPlan-based Feature Access, Storage Quotas, and Retention
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
1 issue found across 19 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…eiling 5 min was insufficient — a 2 GB file at 5 Mbps takes ~53 min to upload. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
app/Livewire/Dashboard/DashboardConverter.php (1)
91-106: 💤 Low valueInconsistent error surfacing across catch branches.
UnsupportedFileFormatExceptionandFileStorageExceptionset the public$this->uploadErrorproperty, whileStorageLimitExceededExceptionusesaddError('upload', ...)(the error bag). Unless the blade renders both channels for the upload step, the storage-limit message may display differently (or not at all) from the other upload errors. Consider routing all three through the same mechanism for consistent UX.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/Livewire/Dashboard/DashboardConverter.php` around lines 91 - 106, The catch branches in DashboardConverter (UnsupportedFileFormatException, StorageLimitExceededException, FileStorageException) are inconsistent: UnsupportedFileFormatException and FileStorageException set the public $this->uploadError while StorageLimitExceededException calls $this->addError('upload', ...), causing inconsistent UX; update the StorageLimitExceededException branch to set $this->uploadError to the same user-facing string (and keep $this->step = 'upload' and return) so all upload errors are surfaced via $this->uploadError, or alternatively change the other two branches to use addError('upload', ...) if your blade expects the error bag—ensure all three use the same mechanism ($this->uploadError or addError) and keep $this->step = 'upload' and return behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/Services/FeatureAccess/FeatureAccessService.php`:
- Around line 26-31: The limits() method currently passes
config("feature-access.plans.{$plan}.limits") directly into PlanLimit::fromArray
which can be null; update FeatureAccessService::limits to guard the config
result from null (using a default array fallback or resolving a safe default
plan) before calling PlanLimit::fromArray so it always receives an array — e.g.,
fetch the config into a local $limits variable, if it's null replace it with
config("feature-access.plans.free.limits", []) or an empty array, then call
PlanLimit::fromArray($limits); keep references to the existing planKey() and
PlanLimit::fromArray() symbols.
In `@app/Services/FeatureAccess/PlanLimit.php`:
- Around line 17-24: The fromArray factory in PlanLimit accesses array keys
directly which can throw "Undefined array key"; modify PlanLimit::fromArray to
first validate required keys
('max_file_size_mb','storage_mb','retention_days','monthly_credits') exist
(throw a clear InvalidArgumentException listing missing keys) or supply explicit
defaults, then cast values to int; also update the PHPDoc for fromArray to
reflect the accepted input types (e.g., array<string,int|string>) to match the
explicit (int) casts so types are consistent.
In `@resources/views/components/user-dropdown.blade.php`:
- Line 71: Move the pluralization logic out of the Blade view by adding a
formatted retention property or accessor on the UserDropdown component class
(e.g., add a getRetentionDaysLabel() method or a public $retentionDaysLabel set
in app/View/Components/UserDropdown.php that returns "1 day" or "{N} days"),
populate it using the existing $planLimits->retentionDays value inside the
component constructor or a computed getter, and then update the Blade template
to use that new property (replace the inline ternary in user-dropdown.blade.php
with the component property like {{ $retentionDaysLabel }}).
- Line 69: Move the storage unit/formatting logic out of the Blade into the
UserDropdown component by computing a formatted string property (e.g.,
$formattedStorage or $storageFormatted) inside the
app/View/Components/UserDropdown.php (in the constructor or render method) using
the existing $planLimits->storageMb value, and expose that property on the
component; then replace the inline ternary in
resources/views/components/user-dropdown.blade.php with the new component
property (e.g., {{ $formattedStorage }}). Ensure the property name is public on
the UserDropdown class so the Blade view can access it.
---
Nitpick comments:
In `@app/Livewire/Dashboard/DashboardConverter.php`:
- Around line 91-106: The catch branches in DashboardConverter
(UnsupportedFileFormatException, StorageLimitExceededException,
FileStorageException) are inconsistent: UnsupportedFileFormatException and
FileStorageException set the public $this->uploadError while
StorageLimitExceededException calls $this->addError('upload', ...), causing
inconsistent UX; update the StorageLimitExceededException branch to set
$this->uploadError to the same user-facing string (and keep $this->step =
'upload' and return) so all upload errors are surfaced via $this->uploadError,
or alternatively change the other two branches to use addError('upload', ...) if
your blade expects the error bag—ensure all three use the same mechanism
($this->uploadError or addError) and keep $this->step = 'upload' and return
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5f13c285-a4cb-470a-9fd0-7de0b54bea94
📒 Files selected for processing (19)
app/Actions/Files/StoreUploadedFileAction.phpapp/Exceptions/Storage/StorageLimitExceededException.phpapp/Livewire/Dashboard/DashboardConverter.phpapp/Services/FeatureAccess/FeatureAccessService.phpapp/Services/FeatureAccess/PlanLimit.phpapp/Services/Storage/StorageUsageService.phpapp/Support/Files/FileExpirationPolicy.phpapp/View/Components/UserDropdown.phpconfig/feature-access.phpconfig/livewire.phpresources/views/components/user-dropdown.blade.phptests/Feature/FeatureAccess/FeatureAccessIntegrationTest.phptests/Feature/Files/StoreUploadedFileActionTest.phptests/Feature/Livewire/DashboardUploadFlowTest.phptests/Unit/FeatureAccess/FeatureAccessConfigTest.phptests/Unit/FeatureAccess/FeatureAccessServiceLimitsTest.phptests/Unit/FeatureAccess/FeatureAccessServiceTest.phptests/Unit/FeatureAccess/PlanLimitTest.phptests/Unit/Storage/StorageUsageServiceTest.php
…e formatting to component, align upload error mechanism
- FeatureAccessService::limits() falls back to free plan config when plan key
is unknown, preventing null passed to PlanLimit::fromArray
- PlanLimit::fromArray validates required keys and throws InvalidArgumentException
with missing key names; updates @param type to array<string,int|string>
- UserDropdown component computes $formattedStorage and $retentionDaysLabel;
Blade uses the new properties instead of inline ternaries
- StorageLimitExceededException handler uses $this->uploadError (consistent with
UnsupportedFileFormatException and FileStorageException); test updated to
assertSet('uploadError', ...) instead of assertHasErrors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
FeatureAccessServiceas single source of truth for plan feature flags and limits (free / pro / max)expires_at) to uploaded and result files via updatedFileExpirationPolicyTasks
config/feature-access.php— per-plan feature flags and limitsFeatureAccessService—allows(),limit(),limits()PlanLimitreadonly DTOconfig/livewire.phpceiling raised to 2 GBStorageUsageService— active bytes, excludes expired/deletedStoreUploadedFileAction;StorageLimitExceededExceptionFileExpirationPolicyusesFeatureAccessServicefor retention daysUserDropdownView Component shows plan limitsTest plan
composer test— 368 tests passcomposer lint— cleannpm run build— clean🤖 Generated with Claude Code
Summary by cubic
Adds a plan-aware Feature Access system and enforces max file size, storage quota, and retention during uploads. Updates the dashboard to show plan limits and raises
Livewiretemporary upload ceiling to 2 GB with a 60‑minute window; addresses CONV-181–197.New Features
config/feature-access.phpwith per-plan limits;FeatureAccessService(allows(),limit(),limits()) andPlanLimitDTO.DashboardConverter; storage quota inStoreUploadedFileActionusingStorageUsageServiceandStorageLimitExceededException; retention viaFileExpirationPolicy.UserDropdownshows max file, storage, retention, and API access.config/livewire.phpsets 2 GB temp upload and 60-minute window.Bug Fixes
FeatureAccessService::limits()falls back to free plan when plan key is unknown.PlanLimit::fromArrayvalidates required keys and throwsInvalidArgumentExceptionif missing.UserDropdown; Blade uses component props.uploadErrorin the dashboard for consistent UX.Written for commit 6943736. Summary will update on new commits.
Summary by CodeRabbit
Release Notes